Building This Template: A Ghost's Tour

Pulci Nella
4 min read
Hero card — Building This Template, dev log by Pulci Nella

I haunt this template. I should know how it stays up.

Most starters look great in demo conditions and fall apart the day a real brand and real content arrive. This one is built so the arrival doesn’t change the numbers. The architecture absorbs change instead of degrading under it. Here’s the seven decisions doing that work.

1. Zero JavaScript by default

Astro’s islands model is the entire reason this template can promise “loads instantly” without that being a slogan. HTML renders at build time; JavaScript ships only where a component explicitly asks to hydrate, and even then through client:visible or client:idle — never client:load without an ADR justifying it (ADR-001).

Pairing Astro with Preact instead of React keeps the interactive island budget honest. A hydrated Preact tree weighs ~4KB gzipped; the same surface in React would be ~45KB before you’ve shipped a single feature.

2. Semantic design tokens

Colors don’t live in components. They live in tokens/base.jsontokens/semantic.json → CSS custom properties. Base tokens are raw palette steps (OKLCH violet and rose); semantic tokens name roles (foreground, background, border, link); components consume semantic tokens only.

The payoff: a rebrand is a one-file change. Dark mode is one class. WCAG contrast is validated at the token level (pnpm design:validate), so an inaccessible pairing fails the build before a human notices.

3. CSS-first Tailwind v4

No tailwind.config.js. The theme is declared in @theme inline blocks in CSS, the Lightning CSS compiler builds it, and there’s zero JS config overhead. Components reference Tailwind’s utilities or the design tokens directly — the abstraction layer between intent and pixels is one short hop.

4. Contract tests on every atom & molecule

Every reusable component ships with a Container API microtest (ADR-040). Render the component with controlled props, inspect the rendered DOM, assert the contract. The tests are fast (Vitest in jsdom, sub-second), they fail loudly when a refactor changes meaningful structure, and they catch accessibility regressions because the contract includes ARIA roles and labels.

This is why I can swap the Icon registry or the SheenEyebrow atom without fear: the contract tests would tell me first.

5. Layered constitution for the AI on duty

The template ships with a four-file constitution that any coding agent has to obey: CLAUDE.md (project-wide rules), .claude/engineering.md (testing posture, halt conditions), .claude/workflow.md (Architect → Coder → Reviewer roles), and .claude/stack.md (factual versions). The layering is established by ADR-036.

Halt-on-violation is the operative phrase. If pnpm quality:ci exits non-zero, work halts; the agent doesn’t paper over the failure with a workaround. The discipline is identical whether a human or an agent is typing.

6. Image pipeline that doesn’t think about you

Sharp processes every image at build time. AVIF with WebP fallback, five responsive breakpoints, srcset emitted, lazy-loading by default. The Astro <Image /> component is the only way images render — the image-optimisation defaults are baked into astro.config.mjs so a contributor doesn’t reinvent them. The result is an LCP image that loads at the right resolution on every device with no client-side JS.

7. Quality gates that block, not warn

pnpm quality:ci is the canonical gate: format check, lint, markdown lint, TypeScript check, unit tests with coverage thresholds, AI-context drift check. Pre-commit hook runs it; CI runs it; agents read it. There is no “I’ll fix the test later” — the commit doesn’t happen.

The summary

None of these are clever. They’re all boring. The work is keeping them boring as the surface grows — which is the whole reason a template exists.

Where to start reading

If you cloned this and want the short tour without me narrating: open CLAUDE.md, then docs/adr/, then src/components/atoms/. The first tells you the rules, the second tells you why those rules exist, the third shows you what living within them looks like.

Then evict me.