00 — SYNTHESIS: Showcase Website Stack + Repo Setup
2026-07-19. oh-architecture run (ultra mode: 8-agent research fan-out + 4-candidate adversarial court, 24 agents total). Decision doc — readable standalone; doubles as the ADR.
Decision: Candidate B — Astro 7 + Tailwind v4, bespoke curated product pages over a content-layer view of
plans/+research/. Matrix score 4.10, winner robust under sensitivity shifts. Runner-up: VitePress 1.6.4 (3.40). Quartz v5 (2.90) and Next 16 export (2.75) rejected.
1. Question + scope
Which stack and markdown→site pipeline should the internal showcase website use, optimized for the speed at which Claude Code agents author new, distinctive product pages — and how is this repo set up around it? In scope: stack, content pipeline, curation/confidentiality mechanism, serving, repo conventions. Out of scope: the factory products themselves, auth, cloud hosting (one-paragraph forward path only).
2. The evidence that shaped the decision
- The corpus is not Obsidian-shaped. 86 md files, ~13.9k lines: zero real wikilinks, zero callouts, 43 mermaid fences, heavy GFM tables (01-deep-dive §2). This deleted Quartz’s and VitePress’s headline advantages before the court convened — the fidelity requirement is GFM + mermaid, which everything can meet.
- The best agent-authoring evidence points at exactly one lane. The only detailed field report of the target workload (agent-built showcase site, 85 pages, ~80% agent-carried) is Astro + Tailwind + locked design tokens; Astro 7.0 shipped
astro dev --background+ JSON logs explicitly for AI agents (02-case-studies; first-party). - Slop is a prompting problem, not a stack problem (convergent, 02-case-studies §1) — so the design-ceiling criterion rewards the stack with no theme to fight (Astro bespoke) and penalizes wiki/docs chrome (Quartz, VitePress default).
- Silent failure classes disqualify, loud ones don’t. Next 16:
getServerSidePropssilently ignored + stale caching priors (documented). VitePress: md compiled as Vue templates — a fence-aware scan found 14 bare pseudo-tags in 3 existing corpus files that throw day-one compile errors pointing at generated SFC output, not the source line (04-steelman D-prosecution — empirical, this repo). Astro’s enumerated drift zones all fail at build time; its one silent mode (Sätteri pipeline regression → mermaid renders as code blocks) is closed structurally (§5 risk 1).
3. Decision matrix
Weights per the stated optimization target. Scores 1–5, grounded in 01–04 (citations there).
| Criterion | Wt | A Quartz v5 | B Astro 7 | C Next 16 | D VitePress |
|---|---|---|---|---|---|
| Agent-authoring throughput (new pages) | 20% | 2 | 4 | 3 | 3 |
| Agentic familiarity + failure legibility | 20% | 2 | 4 | 2 | 3 |
| Design ceiling (anti-template rule) | 15% | 2 | 5 | 5 | 3 |
| Simplicity / ops surface | 15% | 2 | 3 | 1 | 4 |
| Time-to-first-value | 15% | 5 | 4 | 2 | 4 |
| Corpus fidelity (GFM + 43 mermaid) | 10% | 5 | 5 | 3 | 4 |
| Evolution path / exit cost | 5% | 5 | 4 | 5 | 3 |
| Weighted | 2.90 | 4.10 | 2.75 | 3.40 |
Score rationales (compressed): A pays the zero-training-data v5 tax exactly on the graded deliverable (bespoke pages) and carries a fork-as-app upstream with no tags; C is maximum ops for a brochure with priors that actively fight export mode; D loses the graded loop to off-stack Vue in the zero-evidence quadrant plus the template-compile hazard; B’s drift zones are enumerated, pinnable, and loud.
Sensitivity. Winner survives: doubling TTFV at throughput’s expense (A→~3.35, B→~4.0); zeroing design ceiling entirely (B still leads on throughput+familiarity); pricing familiarity as raw training mass (C rises but its silent-failure class caps legibility). The only flip is a scope change, not a weight shift: if the site were pure vault-publish with no bespoke product pages, A/D win — Robert already rejected that scope (“awesome webpages for the products”).
4. The winning architecture
flowchart LR
subgraph CONTENT["content plane (untouched masters)"]
P["plans/NNN-*/**.md"]
R["research/*.md"]
X["analysis/legacy/SYNTHESIS.md, docs/llm-runs.md"]
end
subgraph SITE["site/ (Astro 7, presentation plane)"]
CL["Content Layer glob() base ../plans, ../research<br/>ALLOWLIST curation config (fail-closed)"]
MD["@astrojs/markdown-remark pipeline (pinned)<br/>+ remark-gfm + astro-mermaid"]
TW["Tailwind v4 (@tailwindcss/vite)<br/>DESIGN.md-locked tokens"]
PAGES["index (program) · /products/x bespoke .astro<br/>/library/* auto-rendered corpus"]
end
CONTENT --> CL --> MD --> PAGES
TW --> PAGES
PAGES --> DIST["static dist/"]
DIST --> SERVE["python3 -m http.server / systemd --user<br/>later: CF Access or Tailscale for Tomas"]
Boundaries: content plane = existing markdown, never moved, never converted (exit cost = delete site/). Curation layer = explicit allowlist in the collection config — confidential paths (analysis/monorepo-development/, research/11-*, research/14-*, repos/) are simply never included; fail-closed by construction, not by exclude-glob discipline (adopted from A/D prosecutions). Presentation plane = site/, the only throwaway.
Version pins (all VERIFIED active 2026-07-19): astro@7.1, @astrojs/markdown-remark, astro-mermaid@2.1, tailwindcss@4 via npx astro add tailwind. Exact versions in lockfile; upgrades are deliberate events, never side effects.
5. Risk register (winner’s prosecution, absorbed)
| # | Risk | Containment |
|---|---|---|
| 1 | Sätteri silent regression — mermaid fences render as inert code blocks, no error | Structural, not prompt discipline: canary page with a mermaid fence + table; build script = astro build && grep -q '<svg' dist/canary/index.html — pipeline regression becomes a hard build failure. Wired before the first real page. |
| 2 | Astro-7 newness — glob base:'../' dev-watch unverified on v7 |
Verify in hour one; fallback = dev-server restart on md edits (acceptable) or a 5-line copy-sync script. Build path is verified regardless. |
| 3 | Tailwind v4 setup drift (loudest documented 2025 agent failure) | Setup happens once via official astro add tailwind, then frozen in repo + lockfile; executors author pages, never re-scaffold; rules pin in CLAUDE.md. |
| 4 | Agents emit Astro-4/5 idioms (deprecated @astrojs/tailwind, legacy collections) |
All fail loud at build; enumerated as CLAUDE.md pins; main-branch-only means drift can’t hide on a branch. |
| 5 | Annual major churn (documented Astro pattern) | Pin exact versions; upgrade = deliberate maintenance event with the canary build as the gate. |
| 6 | Slop despite stack | DESIGN.md tokens locked BEFORE first page (the field report’s named success factor); every page passes the impeccable/frontend-design gate; anti-template rule ported into rules/. |
6. First implementation steps (test-first)
- Canary first:
site/scaffold (pnpm create astrominimal) + pipeline pins; addsrc/content/canary.md(mermaid fence + GFM table + frontmatter) and the grep-canary build script. Red until the pipeline is right, green forever after — this is the site’s regression test. - Content config: allowlist collections over
../plans+../research;/library/[...slug]renders the corpus. Acceptance: all 86 files render, 43 mermaid fences emit<svg>, zero dead links (link-check script). DESIGN.md: locked tokens (palette, type pairing, spacing, radius, motion) chosen per the anti-template rule — before any product page exists.- First product page:
/products/fleet-monitorcomposed fromplans/004-fleet-monitorentries, through the impeccable gate. This page sets the pattern the other four copy. - Serving:
python3 -m http.server -d site/dist 4173now;systemd --userunit when it becomes daily-driver; CF Access/Tailscale decision deferred until Tomas needs it.
7. Repo setup (executed with this decision)
git repo on main (init 2026-07-19; remote eletrixa/groupon-refactor private, added by a parallel session — push on request only), .gitignore excludes repos/ (confidential clones) + build artifacts; rules/ ported from the vault per the Astro column of 01-deep-dive §5 (~25 files incl. web/design-quality.md anti-template policy, astro/framework-conventions.md, file-headers + security pinned); CLAUDE.md pins required rules via @rules/..., states main-branch-only, the allowlist-curation rule, and the Astro-drift pin list. Plans numbering note: 002- is duplicated by two parallel-session folders — renumbering deferred until those sessions are idle (one-sweep rule, tools/plans.md).
8. Files
| Doc | Content |
|---|---|
| 01-deep-dive.md | Corpus ground truth, candidate tech facts, serving/repo facts, rules-port table |
| 02-case-studies.md | Agentic-era experience + classic case studies + evidence gaps |
| 03-options.md | The 4 candidates with diagrams, boundaries, test seams, costs |
| 04-steelman.md | Full court record: advocate/prosecution/cross-exam per candidate |
Flip status: draft → active in README.md when the decision is accepted.