What I Learned Writing DESIGN.md for Four Astro Sites

I audited four related Astro sites, gave each repository its own visual contract, and learned where design cohesion should stop short of uniformity.

Cover for What I Learned Writing DESIGN.md for Four Astro Sites

6 min read


I had four active Astro sites and no DESIGN.md in any of them.

That did not mean they had no design systems. The systems were already there—in CSS variables, Tailwind aliases, Starlight overrides, typography choices, repeated component shapes, and the decisions I remembered but had never written down. The problem was that an AI coding agent could see the values without reliably understanding which differences were intentional.

I wanted the sites to feel more cohesive, but I did not want four copies of the same homepage. That distinction became the useful part of the project.

The active set was:

  • derekleeds.com, my personal homepage and canonical resume;
  • learn.derekleeds.cloud, my long-form journal;
  • guides.derekleeds.cloud, task-focused documentation built with Astro Starlight;
  • leedswebservices.com, the commercial site.

A fifth Astro repository still existed for the old resume domain, but it now served only as redirect compatibility. Giving a redirect a design system would have been documentation cosplay, so I did not.

The source audit showed two families.

The personal homepage already used warm paper, navy and muted blue, restrained gold, Georgia headings, practical sans-serif body copy, square editorial surfaces, and visible rules. Learn used Inter, Tailwind’s blue and gray scales, rounded cards, and gradients. Guides used Starlight with a blue/navy theme. Leeds Web Services shared the editorial bones of the personal homepage but had its own deep green and lime commercial identity.

The right goal was not one palette. It was shared family resemblance where the audience and product allowed it.

Why I did not create one global file

My first architectural question was whether all sites should point to one master DESIGN.md.

That would have looked cleaner in a diagram and created a new synchronization problem in practice. The sites live in separate repositories, use different UI systems, and do not consume a common token package. A global file would either become vague enough to be useless or claim authority that the builds did not enforce.

I chose one root DESIGN.md in each active visual repository. The personal sites repeat a small number of family invariants: navy/blue structure, warm neutral surfaces, restrained gold focus treatment, accessible interaction states, and direct language. Leeds Web Services documents a separate green/lime family. The redirect repository gets nothing.

That decision kept the contract next to the code it governs. If the sites eventually consume one generated token package or shared component library, centralization will have earned its keep. It has not yet.

What went into each contract

I used Google’s alpha DESIGN.md format: YAML front matter for machine-readable tokens and Markdown for rationale.

Each file records:

  • semantic colors and contrast pairs;
  • typography roles rather than just font names;
  • spacing and radius scales;
  • representative component tokens;
  • layout and elevation rules;
  • accessibility expectations;
  • explicit do’s and don’ts.

The prose mattered as much as the values. #D0A63B says “gold.” The rationale says it is a scarce focus and emphasis signal, not permission to paint half a page yellow.

I linted every contract with the official CLI. One initial pair—white text on the personal site’s muted blue—measured 4.39:1, just below the WCAG AA threshold for normal text. The actual design did not require that combination as a button, so I corrected the documented component instead of darkening the site’s real palette to satisfy an invented use case.

That was a useful reminder: a design contract should describe intentional implementation, not manufacture components so every token appears busy.

I also exported each contract to DTCG tokens.json. For now those files are interoperable artifacts, not build inputs. Wiring them into every framework would have expanded a documentation project into a token-platform migration with no evidence that I needed one.

The smallest cohesion changes

The audit did reveal a few cheap improvements.

Learn’s logo was an empty blue gradient square beside the site name. It also had two class attributes on the same anchor, which meant the intended focus class could be discarded. I replaced the empty square with a compact navy DL mark, removed the duplicate attribute, changed the focus token to a contrast-safe darker gold, and pointed the Resume footer link at the canonical /resume/ route.

Guides was already structurally coherent with the personal family. I kept Starlight intact, warmed the light-mode background, and added the same visible darker-gold focus treatment. Replacing Starlight components would have made the documentation site harder to maintain for the sake of looking more custom.

I left the personal homepage and Leeds Web Services implementation alone. They already had strong, intentional identities. “Make the sites cohesive” did not justify changing code that was doing its job.

What worked

The repository-local approach was small enough to review and specific enough to guide an agent. The four contracts passed the official linter without warnings or errors. Each repository change merged independently, converged through the Forgejo-to-GitHub mirrors, deployed through Cloudflare Pages, and passed its live route check. The site builds and repository checks were the acceptance gate for the implementation changes rather than the existence of four plausible Markdown files.

The most useful outcome was a clearer boundary:

shared family signals
  != one universal palette
  != one shared component library
  != one global file before shared tooling exists

Cohesion came from repeating a few durable decisions and preserving each site’s purpose.

What I would watch next

DESIGN.md is still an alpha format. I expect its schema and tooling to move. Generated token exports also create a temptation to declare victory before the CSS consumes them.

The next review should happen after agents use these files for real changes. I want to know:

  • whether they choose existing tokens instead of inventing new ones;
  • whether the prose prevents inappropriate component styles;
  • whether repository-local copies drift in the family-level rules;
  • whether DTCG exports become useful inputs or remain review artifacts.

If drift becomes measurable, I can centralize the shared subset. Until then, four local files are less machinery than one premature platform.

The reusable process

I turned the practical parts into a separate guide: Use DESIGN.md to Keep AI-Built Interfaces Cohesive.

The short version is:

  1. inspect the rendered interface;
  2. extract the implemented tokens and component rules;
  3. decide the smallest scope that owns one visual language;
  4. write tokens and rationale together;
  5. lint the file and resolve contrast findings;
  6. make only the cohesion changes the audit can justify;
  7. build and visually verify the sites;
  8. centralize later only if real shared consumption demands it.

The servers did not need a design-system control plane. They needed four good files and fewer guesses.


Share this post