Alpha: Ships on npm at 7.0.0-alpha.07.0.0-alpha.0

Rebrand a Site in one line

Change the theme field in every record, check that each still parses, and compare every page of the Site under the old Theme and the new.

A record names its Theme in one field, "theme". Change it in every record of a Site and the whole Site redraws in another Brand: color, typefaces, dividers, how the featured plan stands out. No word moves.

Prerequisites

  • A Site's records in pages/, all under one Theme. Harbor tides has ten.

Pick the Theme

The field takes one of five: certificate, vaultline, quaypoint, callboard or directory. Each Theme is a Brand's tokens plus four render policies. To wear your own Brand, write a Theme.

pages/harbor/home.json
{
  "$schema": "https://next.mdxui.dev/schema.json",
  "theme": "quaypoint",
  "template": "api-product",
  "title": "Harbor tides: every berth, every tide",
  "description": "Tide tables for every berth in the harbor, as one API: heights, times and the window your keel clears.",
  "frame": "none",
  "sections": [
    {sections.0 · nav
          "kind": "nav",
          "shell": {
            "inset": "bleed",
            "density": "none",
            "surface": "glass",
            "sticky": true
          },
          "block": {
            "type": "nav",
            "menu": "none",
            "brand": { "href": "/", "text": "Harbor tides", "mark": "waves" },
            "links": [
              ["/pricing", "Pricing"],
              ["/integrations", "Integrations"],
              ["/blog", "Blog"]
            ],
            "cta": { "href": "/contact", "label": "Talk to the harbor" }
          }
        },
    {sections.1 · hero
          "kind": "hero",
          "shell": { "inset": "contained", "density": "hero" },
          "block": {
            "type": "hero",
            "layout": "centered",
            "stack": 560,
            "title": "Every berth, every tide.",
            "lede": "One call returns the tide table for any berth in the harbor: the times, the heights and the window your keel clears.",
            "actions": [
              { "href": "/pricing", "label": "See the plans", "kind": "solid" },
              {
                "href": "/contact",
                "label": "Talk to the harbor",
                "kind": "ghost"
              }
            ],
            "fine": ["1,000 calls a month free", "Heights to the chart datum"]
          }
        },
    … 12 more sections
  ]
}

Change one line in every record

A Site wears one Theme, so change every record at once. Run node rebrand.ts directory; it sets the field, parses each record and writes it back. A Theme changes no bound, so a record that parsed still parses.

rebrand.ts
// node rebrand.ts directory: every record in pages/ moves to one Theme, and still parses.
const theme = process.argv[2] ?? 'directory';
if (!(THEME_NAMES as readonly string[]).includes(theme)) throw new Error(`${theme} is not one of ${THEME_NAMES.join(', ')}`);

let moved = 0;
for (const file of (await readdir('pages', { recursive: true })).filter((f) => f.endsWith('.json'))) {
  const record = JSON.parse(await readFile(`pages/${file}`, 'utf8'));
  if (record.theme === theme) continue;
  record.theme = theme;
  PageSchema.parse(record); // a Theme changes no bound, so a record that parsed still parses
  await writeFile(`pages/${file}`, `${JSON.stringify(record, null, 2)}\n`);
  moved++;
}
console.log(`${moved} records now wear ${theme}`);

Compare before you ship

These docs render every page of every worked Site under all five Themes. Flip the chips on the Result, or flip the whole Site below, before you commit a Brand. Check the pages where the policies show most: pricing for the featured plan, long pages for the dividers.

Result
Harbor tides › pricing · directoryOpen the render

Result

Every record names the new Theme and parses, and every page renders in one Brand. Build it with Ship a Site.

Result
Harbor tides › pricing · directoryOpen the render
{
  "$schema": "https://next.mdxui.dev/schema.json",
  "theme": "quaypoint",
  "template": "api-product",
  "title": "Harbor tides: every berth, every tide",
  "description": "Tide tables for every berth in the harbor, as one API: heights, times and the window your keel clears.",
  "frame": "none",
  "sections": [
    {sections.0 · nav
          "kind": "nav",
          "shell": {
            "inset": "bleed",
            "density": "none",
            "surface": "glass",
            "sticky": true
          },
          "block": {
            "type": "nav",
            "menu": "none",
            "brand": { "href": "/", "text": "Harbor tides", "mark": "waves" },
            "links": [
              ["/pricing", "Pricing"],
              ["/integrations", "Integrations"],
              ["/blog", "Blog"]
            ],
            "cta": { "href": "/contact", "label": "Talk to the harbor" }
          }
        },
    {sections.1 · hero
          "kind": "hero",
          "shell": { "inset": "contained", "density": "hero" },
          "block": {
            "type": "hero",
            "layout": "centered",
            "stack": 560,
            "title": "Every berth, every tide.",
            "lede": "One call returns the tide table for any berth in the harbor: the times, the heights and the window your keel clears.",
            "actions": [
              { "href": "/pricing", "label": "See the plans", "kind": "solid" },
              {
                "href": "/contact",
                "label": "Talk to the harbor",
                "kind": "ghost"
              }
            ],
            "fine": ["1,000 calls a month free", "Heights to the chart datum"]
          }
        },
    … 12 more sections
  ]
}

Next steps

On this page