Astro Build Standards docs

Why this exists#

[principles]Reference

Core principles#

These ten principles are the spine of the system; every section below is an elaboration of one of them.

  1. The starter is the canonical source of truth. When a rule or pattern changes, it changes in the starter first, then propagates to client repos.
  2. Client sites inherit the starter; proven improvements flow back. Client repos start from a clean baseline and don't each carry their own fixes — a fix proven on a build gets ported back here, then pulled forward (structure.git).
  3. Pages stay thin and compose sections. A pages/*.astro file reads like a table of contents: a <Layout> wrapping a short list of sections (components.composition).
  4. Sections own page-specific content and layout. A Section* component encapsulates one chunk of a page — its landmark, content, and markup — so the page file stays readable (components.composition).
  5. Reusable UI lives in typed, open components. Primitives (Button, Card, Field) are fully parameterized (typed props + slots), token-styled, and carry no page-specific content (components).
  6. Semantic tokens only — never raw colors or one-off values. Components reference roles (bg-intent, text-fg-muted), never hex or raw Tailwind neutrals (text-gray-700). Theme swaps "just work" through the cascade (tokens).
  7. Accessibility, keyboard, focus, and reduced motion are authored from day one — never retrofitted. Native semantics first, ARIA only where native falls short (a11y).
  8. Content, SEO, schema, redirects, and site identity are centralized. One source of truth each — site.ts, Seo.astro, lib/schema.ts, _redirects (seo).
  9. Static output is the default; client JS is added only when it earns its cost. Astro ships zero JS by default; interactivity is progressively enhanced and degrades to working HTML when JS fails (components.scripting, perf).
  10. The production deploy is lean; the repo keeps the full toolbox, docs, and examples. Clients receive the full repo — every component, the showcase, and the docs — because their AI agent uses all of it to build pages. "Lean" applies to the production deploy, not the repo: demo/showcase routes are gated out of the live build, never stripped from the codebase (deploy.static).

One way to do a thing. Where two patterns exist, this doc picks one — consistency beats local cleverness. The runbook (runbook) and checklists (checklists) are derived views of these principles and the starter's actual state: when a principle or the starter changes, update checklists/runbook in the same change so they never drift.

How rules are labeled#

  • Required — reviewers gate on it; a violation blocks a PR. A Required rule must be true of the starter, or it appears in conformance with a date.
  • Default — the standard choice; deviate only with a stated reason.
  • Allowed with reason — permitted when justified and scoped.
  • Roadmap — decided but not yet implemented; tracked in roadmap. Never gated on.

Where rules live — no duplication#

A rule is stated once, in exactly one module under docs/rules/. Everything else points at it:

FileJob
docs/rules/*.mdthe rules themselves — the only place a rule is stated
docs/workflow.mdthe router: task → which modules to read → which verification tier
docs/checklists/*.mdwhat a reviewer gates on; cites rules, never restates them
DESIGN.mdthe client's brand decisions and constraints, with their reasoning — never values; those live in global.css (tokens.design-doc)
AGENTS.mdthe vendor-neutral agent contract and entry point; routes, states non-negotiables in one line each
CLAUDE.mda pointer to AGENTS.md, nothing more
.claude/skills/*executable procedures; state what to check and at what severity, never the rule itself (guardrails.skills)

A rule written twice drifts twice. If you find yourself explaining a rule outside docs/rules/, link to it instead.