How It Works

An architecture tour for developers who read the homepage and asked, prove it. Here's what's actually under the hood — the zero-JS philosophy, the AI development system, the design pipeline, and the toolchain that ships.

The page you're reading is itself a demonstration: zero hydrated JavaScript, scroll-driven animations powered by CSS, and a section-tracking sidebar that uses one Intersection Observer.

Pillar 1 — Performance-First Architecture

Zero-JS by default

Every component in this template compiles to static HTML and CSS. JavaScript ships only when a feature genuinely needs it — and even then, it's an Astro Island, lazy-hydrated only when in view. ADR-001 codifies the rule: no client:load without explicit justification.

What the web platform gives us for free

The browser has caught up to the framework era. Most of what React, Vue, or Angular libraries used to do in user-space JavaScript is now a CSS rule, a media query, or a one-line HTML attribute. Pick a tab to see the swap.

Replaces: AOS · ScrollMagic · GSAP ScrollTrigger

JS approach Bundle cost: kilobytes
component.tsx
// Typical IntersectionObserver setup
import { useEffect, useRef } from "react";
export function FadeIn({ children }) {
const ref = useRef(null);
useEffect(() => {
const io = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) ref.current.classList.add("visible");
}, { threshold: 0.3 });
io.observe(ref.current);
return () => io.disconnect();
}, []);
return <div ref={ref} className="fade-in">{children}</div>;
}
CSS native Bundle cost: 0
component.astro
/* Native scroll-driven animation — zero JS */
.fade-in {
animation: fade-up linear both;
animation-timeline: view();
animation-range: entry 0% entry 30%;
}
@keyframes fade-up {
from { opacity: 0; transform: translateY(2rem); }
to { opacity: 1; transform: translateY(0); }
}

Replaces: Radix Dialog · HeadlessUI · React Modal

JS approach Bundle cost: kilobytes
component.tsx
// React modal with focus trap
import * as Dialog from "@radix-ui/react-dialog";
export function ConfirmModal() {
const [open, setOpen] = useState(false);
return (
<Dialog.Root open={open} onOpenChange={setOpen}>
<Dialog.Portal>
<Dialog.Overlay className="overlay" />
<Dialog.Content className="content">
{/* focus trap, backdrop, escape handling, body scroll lock */}
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
}
CSS native Bundle cost: 0
component.astro
<!-- Native <dialog> — focus trap, backdrop, escape: free -->
<dialog id="confirm">
<h2>Confirm action</h2>
<button onclick="confirm.close()">Close</button>
</dialog>
<button onclick="confirm.showModal()">Open</button>

Replaces: tippy.js · Floating UI · Popper.js

JS approach Bundle cost: kilobytes
component.tsx
// Floating UI tooltip with positioning
import { useFloating, autoUpdate, offset, flip } from "@floating-ui/react";
export function Tooltip({ children, text }) {
const [open, setOpen] = useState(false);
const { refs, floatingStyles } = useFloating({
open, onOpenChange: setOpen,
middleware: [offset(8), flip()],
whileElementsMounted: autoUpdate,
});
// ... handlers, render, escape, dismiss
}
CSS native Bundle cost: 0
component.astro
<!-- Popover API: hint type = auto-dismiss, escape, no JS -->
<button popovertarget="hint" popovertargetaction="show">
Hover me
</button>
<div id="hint" popover="hint">
Helpful information
</div>

Replaces: GSAP · CountUp.js · react-countup

JS approach Bundle cost: kilobytes
component.tsx
// GSAP number counter
import { gsap } from "gsap";
export function Counter({ value }) {
const ref = useRef(null);
useEffect(() => {
const obj = { n: 0 };
gsap.to(obj, {
n: value, duration: 1.5, ease: "power2.out",
onUpdate: () => { ref.current.textContent = Math.round(obj.n); },
});
}, [value]);
return <span ref={ref}>0</span>;
}
CSS native Bundle cost: 0
component.astro
/* CSS @property + counter() — pure CSS interpolation */
@property --num {
syntax: "<integer>";
initial-value: 0;
inherits: false;
}
.counter {
counter-reset: num var(--num);
animation: count 1.5s forwards;
}
.counter::before { content: counter(num); }
@keyframes count { to { --num: 95; } }
The one exception

Preact islands for genuine state

Some interactions actually need client-side reactive state — optimistic UI, complex form validation, signal-driven counters. For those, Astro Islands give us a Preact component that hydrates only when it scrolls into view via client:visible. Everything else stays static.

src/pages/some-page.astro
---
import SignalsCounter from "@/components/islands/SignalsCounter.tsx";
---
<!-- Lazy-hydrated. Zero JS until visible. -->
<SignalsCounter client:visible />

Pillar 2 — Agentic Discipline

Point your agent at the docs and ship

The headline differentiator. Most templates assume a human reads the README and figures out the conventions. This one assumes an AI coding agent will be sitting at the keyboard, and front-loads the context, constraints, and decision history that agent needs to make good calls without supervision.

What an agent sees on day one

When Claude Code (or any AI assistant) opens this repo, the very first thing it loads is CLAUDE.md at the project root — rules of engagement, scope boundaries, and a pointer to every ADR that constrains architectural decisions.

CLAUDE.md (excerpt)
# Astro Performance Starter — Claude Code Context
## Rules of Engagement
1. Check `docs/adr/` before suggesting architectural changes.
2. No `client:load` without ADR justification (ADR-001).
3. Use design tokens from `tokens/` — never hardcode colors.
4. TypeScript strict mode is non-negotiable.
5. Use Biome, not ESLint/Prettier.
6. Use pnpm, not npm or yarn.
7. Prefer CSS solutions over JavaScript.
8. Use Astro Image for all images — no raw <img> tags.
9. Verify with `pnpm run quality` before claiming done.

The AI-context system

CLAUDE.md

Project-root entry point. Conventions, scope boundaries, and rules of engagement an agent must follow.

35+ ADRs in docs/adr/

Every accepted ADR is a constraint. The agent reads them before proposing architectural changes — no rediscovery of past decisions.

docs/ai-context/

Prompt libraries, context-update procedures, and guides for keeping the AI surface area in sync with the code.

Progressive implementation tiers

ADR-033 splits the work into three tiers — natural stopping points the agent can ship to. Each tier is "done enough" to deploy, then the next tier unlocks more capability.

Tier 1

Foundation

Working site skeleton with design system, content schemas, and build pipeline. Done = deployable site, no content yet.

Tier 2

Build

Components, pages, content, and quality assurance. Done = complete, tested site running locally and in CI.

Tier 3

Polish

Performance optimization, monitoring, deeper docs. Done = enterprise-grade deployment.

Pillar 3 — Enterprise-Grade Design System

Tokens flow from JSON to your components

One source of truth in tokens/, automatically built into CSS custom properties and exposed as Tailwind utilities. Change one token; the cascade propagates everywhere — light mode, dark mode, every component.

Step 1

Token JSON

tokens/semantic.json

Step 2

CSS Variables

tokens/dist/tokens.css

Step 3

Tailwind Utilities

@theme inline

Step 4

Components

bg-primary-600

1. Token definition

tokens/semantic.json
{
"semantic": {
"primary": {
"600": { "value": "{color.moonstone.600}" }
},
"background": {
"primary": {
"value": "{color.white.500}",
"dark": "{color.spaceCadet.500}"
}
}
}
}

2. Generated CSS variables

tokens/dist/tokens.css (generated)
:root {
--color-primary-600: 189 61% 32%;
--color-background-primary: 0 0% 100%;
}
.dark {
--color-background-primary: 227 50% 16%;
}

3. Tailwind utility binding

src/styles/global.css
@theme inline {
--color-primary-600: hsl(var(--color-primary-600));
--color-background-primary: hsl(var(--color-background-primary));
}

4. Used in a component

src/components/atoms/Button.astro
<button class="bg-primary-600 text-white">
Save changes
</button>
<!-- Dark mode just works. No dark: variants needed. -->
Automated

Contrast validation in CI

Every semantic foreground/background pair is checked against WCAG-AA at build time. The build fails if any pair drops below 4.5:1.

terminal
pnpm design:validate
# ✅ All semantic foreground/background pairs meet WCAG-AA contrast.

Pillar 4 — Next-Gen Toolchain

One command verifies everything

The toolchain is opinionated and modern. Biome instead of ESLint + Prettier. TypeScript strict by default. Performance budgets enforced in CI. Tests at four layers — and a single pnpm quality runs all of it.

20× faster

Biome

Replaces ESLint + Prettier with one Rust-powered binary. Linting and formatting in a single config, single pass.

Strict mode

TypeScript

Astro's strict preset plus strictNullChecks. Errors surface during astro check, not in production.

CI-enforced

Performance budgets

160 KB JS, 50 KB CSS, 200 KB per image. The build fails if any budget is exceeded. Overrides expire automatically.

4 layers

Test pyramid

Vitest for units, Playwright for e2e across Chromium / Firefox / WebKit, axe-core for a11y, Lighthouse for performance regressions.

Pre-commit

Git hooks

Husky + lint-staged runs Biome on staged files; commitlint enforces conventional commits. No bad code reaches the remote.

Locked

pnpm engine-strict

Package manager and Node version are pinned in package.json. New contributors get the same toolchain on the first install.

The single quality gate

Format → lint → markdown lint → type check. One command, fast feedback, identical in CI and on your laptop.

terminal
pnpm quality
# ✓ format biome format . --write
# ✓ lint biome check .
# ✓ lint:md markdownlint-cli2 **/*.md **/*.mdx
# ✓ check astro check (TypeScript)

Pillar 5 — Robust Page Templates

Real pages, not empty shells

Most starter templates ship a hero page and call it a day. This one ships a full set of reference implementations — each one a working example of how the components, content collections, and conventions fit together.

Home

Marketing pillar grid, Lighthouse metric showcase, tech stack with version display, expandable feature cards.

Components

Live demo of every component in src/components/, with code snippets, a11y notes, and composition examples.

Blog

Content Collections + MDX with Zod schemas. Reading time, tags, scroll-driven progress bar, prefetched links.

Projects

Portfolio / case-study layout with filtering by technology, pagination, and structured outcome metadata.

About

Bio, skills, experience timeline, social links — pulled from content collections so non-engineers can edit it.

Contact

Progressive-enhancement form with native HTML validation first, JS enhancement second (ADR-021).

Want to see the components themselves? The Components page has every atom, molecule, and structural component with a live demo and code.

Browse the Components → Clone the repo →