005 — Showcase Website: Phase-1 Deep Dive
plan: 005-showcase-website
type: deep-dive
status: phase-1-complete
created: 2026-07-19
owner: Robert
Consolidates research packets R-C1 (content inventory), R-D1 (Astro), R-D2 (Quartz), R-D3 (Next.js/VitePress), R-H1 (serving+repo), R-R1 (rules port). All facts dated 2026-07-19; VERIFIED = checked today (filesystem, web fetch, npm registry), ASSUMPTION = training knowledge or judgment, not re-verified.
1. Question & Scope
Question: Which stack and markdown→site pipeline should power an internal showcase website for the Groupon rebuild program and its 5 factory products, sourced from the existing markdown in plans/ + research/?
Optimization target: speed at which Claude Code agents author NEW awesome-looking product pages, under the anti-template design rule (§5) — not raw serving performance, not SEO, not scale.
In scope: SSG/stack choice, md-source pipeline (content outside src/), mermaid + GFM rendering, localhost serving + persistence, repo/git setup, rules port per stack.
Out of scope: the products themselves (they have their own plans folders); auth; cloud hosting beyond a forward path — one paragraph: if Tomas needs access later, the two candidates are Cloudflare Pages/Workers static assets gated by CF Access (free ≤50 users, creds already in ~/s/.env.master) or Tailscale into the WSL node (strongest confidentiality, zero pipeline change, Tomas installs Tailscale). Both consume the same static dist/; decision deferred until the need is real. grpn.site domain: unverified, ASSUMPTION only — confirm ownership before planning around it. [R-H1]
2. Corpus Ground Truth (load-bearing)
Direct filesystem inspection of /home/rob/groupon/refactor, 2026-07-19. All VERIFIED unless noted.
2.1 Markdown corpus
| Folder | .md files | Lines | Notes |
|---|---|---|---|
| plans/001-factory-apps-validation | 6 | 588 | SYNTHESIS, deep-dive, case-studies, options, steelman |
| plans/002-dual-run-parity-harness | 16 | 3,338 | full product pack (prd, architecture, ux-ui, pre-mortem, north-star…) |
| plans/002-work-ledger-product | 12 | 2,428 | numbered pack 01–11 (duplicate 002- prefix) |
| plans/003-atlas-intelligence-layer | 20 | 5,154 | product pack + evidence/ (memos r1–r8) |
| plans/004-fleet-monitor | 9 | 1,244 | 00-SYNTHESIS, prd, architecture, ux-ui, pre-mortem |
| plans/ total | 63 | 12,752 | |
| research/ | 19 | 976 | short memos ~30–80 lines; + 2 raw .json |
| docs/ | 1 | 11 | llm-runs.md |
| analysis/ subdirs | 3 | 190 | legacy/SYNTHESIS+census, monorepo-development/ASSESSMENT; rest JSON |
Total ≈ 86 md files, ~13.9k lines. Small — any SSG, or even a single-file renderer, handles it.
2.2 Obsidian-syntax reality: the corpus is plain CommonMark + GFM + mermaid
| Folder | [[ wikilinks |
> [! callouts |
```mermaid |
YAML frontmatter | images |
|---|---|---|---|---|---|
| plans/ | 2* | 0 | 41 | 10/63 files | 0 |
| research/ | 0 | 0 | 2 | 0/19 | 0 |
| docs/, analysis/ | 0 | 0 | 0 | 0 | 0 |
* Both [[ hits are mermaid node syntax in plans/002-dual-run-parity-harness/architecture.md (lines 218, 321). True wikilink count: 0. Callouts: 0. Embeds/images: 0. Frontmatter where present is trivial (plan/status/owner/created/type).
Conclusion: Obsidian-syntax fidelity does NOT matter. The hard pipeline requirement is GFM tables (heavy — decision matrices, scorecards throughout) + 43 mermaid fences + trivial YAML frontmatter. Any candidate scored on wikilink/callout support is being scored on a non-requirement.
2.3 Confidentiality map
Never publish / never leave localhost or reach any public remote:
repos/(12G) — cloned confidential Groupon repos. Exclude from site AND gitignore before anygit init(no.gitexists yet, VERIFIED).analysis/monorepo-development/ASSESSMENT.md— self-declares CONFIDENTIAL (unannounced org plans, compensation, named-person scoring). Excluded even from the internal site unless Robert opts in.research/14-answer-draft-tomas.md,research/11-monorepo-development-assessment-plan.md— person-directed drafts (ASSUMPTION: exclude from curated site).analysis/legacy/quotes confidential repo internals — fine for localhost, not for anything beyond Robert/Tomas.
Curated INCLUDE set: plans/00* product packs, research/00–10 + 12–13, analysis/legacy/SYNTHESIS.md, docs/llm-runs.md.
2.4 Source docs per product page
| Page | Primary sources |
|---|---|
| Program overview | plans/001.../00-SYNTHESIS.md; research/00-executive-summary.md; research/06-six-app-blueprint.md |
| Fleet monitor | plans/004-fleet-monitor/ 00-SYNTHESIS, 04-prd, 06-architecture, 05-ux-ui; research/12 |
| Work-ledger | plans/002-work-ledger-product/ 01, 10-architecture, 09-north-star, 07-ux-ui |
| Dual-run harness | plans/002-dual-run-parity-harness/ prd, architecture (mermaid-heavy), north-star, made-to-stick |
| Triage inbox | folded into Atlas: plans/003.../ 01, 02, 09; research/08 |
| Atlas | plans/003.../ 01, 10-architecture, 09-north-star, evidence/r1–r8 |
| (bonus) Legacy estate | analysis/legacy/SYNTHESIS.md + graph/graph.mmd |
2.5 Tooling on box (VERIFIED)
node v24.18.0, npm 12.0.1, pnpm 11.9.0 (store warm), bun 1.3.14 — no installs needed for any mainstream SSG.
3. Candidate Technology Facts
3.1 Astro 7 [R-D1]
- Astro 7.1 current (2026-07-16); 7.0 released 2026-06-22. Rust compiler, Vite 8 + Rolldown, builds 15–61% faster. VERIFIED — astro.build/blog, Astro 7.0 post.
- Content from arbitrary folders is first-class: Content Layer
glob({ pattern, base: "../plans" })documented as loading “from anywhere on the filesystem”. VERIFIED — Content Loader API. Dev-server watching of out-of-src dirs: ASSUMPTION (worked in v5, not re-verified for v7). - ⚠ Key decision point — v7 markdown pipeline changed: default processor is now Sätteri (Rust; npm
satteri0.9.5, 2026-07-08), which does not run remark/rehype plugins. Official escape hatch: install@astrojs/markdown-remark→ oldremarkPlugins/rehypePluginsconfig works as before. At ~100 files the lost Rust speed is irrelevant. VERIFIED — first-party blog, byteiota analysis. Sätteri builds in GFM, heading IDs, smart punctuation natively — with zero wikilinks/callouts in the corpus (§2.2), the stock Sätteri pipeline may already suffice. - Mermaid:
astro-mermaid2.1.0 (2026-06-24, active, client-side, auto theme-switch) — simplest. Build-timerehype-mermaid3.0.0 needs Playwright headless + unified pipeline; viable (bundled Chromium exists) but two extra moving parts. VERIFIED (npm). Verdict: client-side for 2 viewers. - Tailwind v4:
npx astro add tailwind→@tailwindcss/vite; old@astrojs/tailwinddeprecated. VERIFIED — tailwindcss.com Astro guide. - Agentic DX:
astro dev --backgroundshipped in 7.0 explicitly “for AI agent compatibility” + JSON structured logging. VERIFIED. Training data is heavy but at Astro 4/5 level — predictable agent failure modes to pin in CLAUDE.md (ASSUMPTION, high confidence): deprecated@astrojs/tailwind; assuming remark plugins run by default; legacysrc/content/collections; v7 strict-HTML build errors (fail-loud — actually good). - Starlight: docs chrome (sidebar/search); workable but you fight its skin for a showcase. Verdict: skip — plain Astro + Tailwind v4 + one layout file. VERIFIED — starlight docs.
3.2 Quartz v5 [R-D2]
- Mid v4→v5 transition: default branch is
v5, homepage announces v5.0.0, active commits through 2026-06-16, but last tagged release is v4.0.8 (2023). v5 shipped via branch flip in 2026 — post-dates every current model’s training data. 12.8k stars, MIT. VERIFIED — github.com/jackyzha0/quartz, quartz.jzhao.xyz. - Full Obsidian syntax (wikilinks, callouts, mermaid, graph view, backlinks, search) — VERIFIED, but per §2.2 this is capability the corpus doesn’t need.
- Fork-as-app model: you clone the Quartz repo and put content in its fixed
content/dir; subset publishing via symlinks (content/plans → ../../plans) is a standard community pattern. Node ≥22. VERIFIED + low-risk ASSUMPTION on the two-symlink setup. - Customization ceiling: Preact JSX + SCSS components, v5 pushes toward external plugin packages. ASSUMPTION: “excellent knowledge garden, mediocre product/marketing pages” — bespoke pages mean custom Preact emitters against a brand-new v5 API.
- Agentic risk (the real one): agents know v4 cold; v5 config (YAML), plugin registry, and page types have zero training presence → expect v4/v5 API hallucination on any site-customization task. ASSUMPTION, high confidence.
- Sidebar alternative:
obsidian-export(Rust, v25.3.0, active) converts Obsidian md → CommonMark as a decoupling shim — not a site generator. VERIFIED — github.com/zoni/obsidian-export.
3.3 Next.js 16 static export [R-D3]
- Stable 16.2.10 (2026-07-01); monthly security-patch cadence. VERIFIED — releasebot.io.
output: 'export'→ plain staticout/; no ISR/Server Actions/default image loader in export mode. VERIFIED — static-exports guide.- No first-class content layer for md outside
app/: choices arecontent-collections(active successor to unmaintained Contentlayer; Dub migrated — VERIFIED dub.co/blog) or ~100 hand-rolled lines (ASSUMPTION, standard pattern). Mermaid: DIY (ASSUMPTION). Heavy install (300–500 MB), 20–60 s builds (ASSUMPTION). - Nextra 4 escape hatch exists but is docs-shaped chrome. VERIFIED — nextra.site.
- Verdict [ASSUMPTION/judgment]: house-stack familiarity real (Groupon monorepo + velin are Next), React page ceiling highest — but right call only if the showcase shares components with velin or graduates into an app. Evolution: flip off
output: 'export'→ full app, zero migration.
3.4 VitePress [R-D3]
- Stable 1.6.4; 2.0.0-alpha.18 (2026-07-06) not production-ready — pin 1.6.4. VERIFIED — vitepress releases.
- markdown-it pipeline; GitHub alerts (
> [!NOTE], 5 types) built in; mermaid viavitepress-plugin-mermaid(maintained, one config block). VERIFIED — vitepress.dev/guide/markdown, plugin docs. - Custom themes fully supported (
layout: page= blank canvas; Vue SFCs inline in md). VERIFIED — custom-theme guide. But polish lives in Vue — off-stack for this house (Next/React everywhere else) and less agent muscle memory than React (ASSUMPTION/judgment). - Light (~100–150 MB, seconds-fast builds — ASSUMPTION, widely reported). Massive 1.x training-data presence.
- Net [ASSUMPTION/synthesis]: wins “markdown in, good page out, minutes not hours”; ceiling for bespoke showcase pages = writing Vue.
4. Serving + Repo Facts [R-H1]
- ui-bridge (:1337) CAN serve a static build —
GET /p/<project>/<subpath>resolves sibling files; registry persists. Caveats: noindex.htmlauto-resolution on directory URLs, thin MIME map (no woff2/webp), no traversal guard,/p/<project>/prefix requires base-prefixed URLs. Currently not running. VERIFIED (source read). - Plain static serving:
python3 -m http.server -d dist(zero-install) ornpx serve(proper MIME + index + SPA fallback). No caddy/pm2/serve installed. Dev-server mode (astro dev/vite) equally viable for 2 viewers. VERIFIED. - Persistence:
systemctl --userresponds (state degraded but functional) → user-scoped systemd unit is the boring persistent option, same unit for dev-server or static-server ExecStart. VERIFIED + ASSUMPTION on WSL2 session survival. - Repo: no
.gitat/home/rob/groupon/refactor(VERIFIED).repos/is 12G of confidential checkouts — must be gitignored before init. Suggested.gitignoreseed:repos/,.playwright-cli/,.claude/scheduled_tasks.lock,node_modules/,dist/. Git author configured (Robert/robert@soulfire.cz); nothing blocksgit init+ first commit today. Main-branch-only, no public remote (confidentiality map §2.3).
5. Rules Port + Anti-Template Design Rule [R-R1]
Vault: /mnt/f/OH/Notes/Global Code Settings/Coding Rules/ → port to refactor/rules/ (frontmatter carries applies-to, copy as-is). Vault has 1 Astro rule, 6 Next.js rules, 0 Quartz rules.
| Rule group (vault path) | Astro | Quartz | Next |
|---|---|---|---|
web/design-quality.md (anti-template — see below) |
x | x | x |
astro/framework-conventions.md |
x | — | — |
nextjs/ app-router, server-client-components, layouts-and-metadata, data-fetching |
— | — | x |
nextjs/ api-routes, opennext-cloudflare |
— | — | opt (skip for local static) |
typescript/ strict-typing, type-inference, nullability, enums-alternatives, module-structure |
x | x | x |
typescript/ rest (generics, branded types…) |
opt | opt | opt |
react/ component-structure, props-design, design-tokens (Tailwind v4 @theme) |
islands only | — | x |
seo/ meta-tags, performance (json-ld/lighthouse skipped — internal, 2 viewers) |
x | x | x |
accessibility/ keyboard-nav, screen-readers |
x | x | x |
animation/ entry-animations, scroll-reveals, performance-and-a11y |
x | x | x |
testing/trophy-model.md; tools/ plans, git-commit-workflow |
x | x | x |
clean-code/ subset (DRY, design-twice, obvious-design, readability, component-size, general-purpose, mobile-optimization, ts-patterns) |
x | x | x |
architecture/project-file-organization.md only (rest is backend-scale, YAGNI) |
x | x | x |
Port burden: Quartz lightest (~20 generic files), Astro +1, Next +4–6 plus react/ subset (~25–28). Quartz column mappings + skip judgments are ASSUMPTION; applies-to values verbatim (VERIFIED).
Always-pinned (via @rules/... imports in repo CLAUDE.md): File Headers (actual location Agent Rules/File Headers.md — crossroads.md’s root link is broken, VERIFIED; fix reference when porting), security/owasp-compliance.md, security/security-testing.md.
Anti-template design rule (web/design-quality.md, read fully, VERIFIED): frontend must look “intentional, opinionated, and specific to the product.” Bans: uniform card grids, stock centered-headline + gradient-blob heroes, unmodified Tailwind/shadcn defaults, flat no-depth layouts, uniform radius/spacing/shadow, gray-on-white + one accent, dashboard-by-numbers, default font stacks. Every meaningful surface needs ≥4 of 10 qualities (scale-contrast hierarchy, spacing rhythm, depth/layering, real type pairing, semantic color, designed interaction states, grid-breaking composition, texture/atmosphere, clarifying motion, dataviz as design-system citizen). Before coding: pick a specific style direction, define palette + typography deliberately, gather references, don’t default to dark mode. The rule names the impeccable skill as the live gate when available — it IS available in this environment, so it (plus frontend-design) is the enforcement mechanism for every new product page.