Establishing the design system

Build a minimal, token-based design system with CSS custom properties; light-first approach with dark mode via media query; no CSS frameworks or external fonts

Context

Before shipping any content, the site needed a visual language. I had strong opinions on what that should be:

  • Minimal: No hero sections, skills grids, or decoration. Content first.
  • Monochromatic: Grayscale foundation with semantic color for state (healthy/warning/error).
  • System fonts: No Google Fonts requests. Native typefaces for speed.
  • Token-based: All values (colors, spacing, sizes) as CSS variables, never inline.
  • Light-first: CSS defaults to light mode; dark mode is a media query remap.

The goal wasn’t to look “modern”—it was to look clear, read well, and avoid the overhead of a CSS framework.

Options considered

  1. Use a CSS framework (Tailwind, Open Props, Pico CSS)

    • Pros: Faster setup, pre-built components
    • Cons: Adds overhead, forces decisions I didn’t want, cargo-cult classes
  2. Roll custom CSS with a design system

    • Pros: Full control, minimal footprint, teaches constraints
    • Cons: Requires upfront documentation, more thought
  3. Use styled-components or CSS-in-JS

    • Pros: Component-scoped styles
    • Cons: JavaScript overhead, overkill for a static site

I chose option 2: custom CSS + documented design system.

What I chose and why

A token-based design system documented in three files:

  • DESIGN.md — Principles, color palette, typography scale, component patterns. Read before any style change.
  • src/styles/tokens.css — All values as CSS custom properties. Light mode defaults, dark mode via @media (prefers-color-scheme: dark).
  • src/styles/global.css — Reset and base element styles.

The color palette

Light mode uses warm grays that don’t strain the eyes:

  • Text: #1a1a1a (very dark gray, not pure black)
  • Backgrounds: #ffffff, #f8f8f8, #f0f0f0 (graduated levels)
  • Borders: #e0e0e0 (subtle dividers)
  • Semantic: Green (#2d7a4a), amber (#b8860b), red (#a94444), blue (#4a6fa5)

Dark mode inverts these by remapping the same CSS variables—no duplicate CSS, just different values.

Typography

System font stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, ...

Font sizes are fluid using clamp():

--font-base: clamp(1rem, 1.4vw, 1.125rem);

This scales smoothly from mobile to desktop without media queries.

Layout

A simple Layout.astro component provides:

  • Header with nav (site title + links to Home, About, Colophon)
  • Main content area
  • Footer with contact info and links

Max-width of 900px keeps text readable. Responsive by default via flexbox.

What I delegated

I asked Claude to:

  1. Create DESIGN.md with complete design system documentation
  2. Create DESIGN.md with complete design system documentation
  3. Create and implement tokens.css with CSS custom properties
  4. Create and implement global.css with base element styles
  5. Build Layout.astro with header, nav, and footer
  6. Style all three pages (home, about, colophon)
  7. Update the home page with proper semantic structure

I did not ask Claude to make design decisions—I specified the constraints and let Claude implement them.

How I verified

  1. Dev server running — No build errors, http://localhost:4321 responds
  2. Visual inspection — Opened the site in light and dark modes, checked readability
  3. Contrast ratios — All text meets WCAG AA (4.5:1 minimum)
  4. Responsive — Tested mobile width (320px) and desktop; nav stacks correctly
  5. Links and focus states — All interactive elements have visible focus outlines
  6. No external requestscurl localhost:4321 shows zero Google Fonts requests

What I’d revisit

  • Font sizes on mobile: Currently using clamp() to scale fluidly, but I haven’t user-tested the readability on a real iPhone yet.
  • Color contrast on semantic colors: The warning color (#b8860b) is borderline on contrast. Might need to darken it if accessibility tests fail.
  • Print styles: Not implemented yet. Could be useful for archival.
  • Code block styling: Currently uses --color-bg-secondary background. Might want syntax highlighting if I add a lot of code snippets.

What I delegated

Claude created DESIGN.md, design tokens, Layout component, and all page styling

How I verified

Dev server running, visual inspection across light/dark modes, contrast ratios checked against WCAG AA