Build log

Shipping the prototype

Scott 4 min read

This is a build log. It exists so future-me remembers what choices were intentional and what choices were lazy.

What we kept

  1. Bun + TypeScript. No bundler. Bun runs .ts directly.
  2. Block-based pages. Each page is a list of typed blocks. Adding a block type is one function.
  3. Design tokens + CSS vars. Theme JSON becomes :root variables and utility classes. No CSS-in-JS.
  4. Prose variants. Long-form blog content gets .prose-article — distinct typography rhythm vs. marketing pages.
  5. Color schemes. A section opting into data-scheme="dark" re-skins every nested element. Zero per-block overrides.

What we cut

  • Markdown. Posts are HTML strings inside JSON. Markdown can be added with a loader later.
  • Blog index / archive. Each post renders standalone. Cross-linking via menus.
  • Asset pipeline. Images are URLs. No resizing, no responsive srcset.
  • Dev server with watch. Build + open. That's plenty for now.

What surprised me

The smallest version that's worth using is much smaller than I think it should be.

A static site generator is mostly: read JSON, concatenate strings, write files. The interesting design work is the theme contract — what tokens exist, how they reference each other, how composite styles compose. Once that's right, blocks become almost incidental.

Numbers

FileWhat it does
src/render/theme.tsJSON → CSS compiler
src/render/blocks.tsBlock registry + renderers
src/render/menu.tsMenu tree → HTML
src/render/page.tsHeader + body + footer
src/cli.tsGlue + write to dist/

What's next

  • Markdown loader for post bodies
  • RSS + sitemap
  • Blog index with pagination
  • Dev server with watch + live reload

Read the first post to see what the article variant looks like in practice.