Skip to content
GRPNR.

Options — showcase website candidates

Four genuinely different shapes for the internal showcase site (program overview + 5 factory product pages), all sourced from the existing markdown corpus in plans/ + research/ (86 files, ~13.9k lines, GFM tables + 43 mermaid fences, zero Obsidian-specific syntax — so GFM + mermaid fidelity is the requirement, Obsidian fidelity is not). Common frame shared by every candidate:

  • Content plane — the existing md files, never modified for the site’s sake.
  • Presentation plane — a new site/ directory holding everything the candidate installs or builds.
  • Curation layer — explicit include/exclude config enforcing the confidential exclusions (analysis/monorepo-development/, research/11, research/14, repos/ never).

A is the do-less vault-publish lane; B is the bespoke curated lane; C is the house-stack lane; D is the markdown-native lane. Cost estimates are DESIGN-gated throughout: “per new page” means a page that has passed the impeccable/anti-template review, not a first draft.

Option A — Quartz v5 sidecar (vault-publish, do-less lane)

Essence: site/ is a pinned clone of jackyzha0/quartz (v5 branch, 12.8k stars, MIT). content/ holds symlinks to ../plans and ../research (plus analysis/legacy/SYNTHESIS.md and docs/llm-runs.md); ignorePatterns / ExplicitPublish handle the confidential excludes. The whole wiki chrome — full-text search, graph view, backlinks, file explorer — comes free. Product pages are custom Preact components / page types written against the new v5 API. Serve: npx quartz build --serve on :8080. Known friction: v5 shipped in 2026, post-training-data, so agents write against an API they have not seen; and the corpus uses none of Quartz’s Obsidian superpowers (no wikilinks, no callouts), so the tool’s core value proposition is partially unused.

flowchart LR
  subgraph CP[content plane - untouched]
    P[plans/]; R[research/]; S[analysis/legacy/SYNTHESIS.md]; L[docs/llm-runs.md]
  end
  subgraph SITE[site/ - pinned quartz v5 clone]
    SYM[content/ symlinks]; IG[ignorePatterns +<br/>ExplicitPublish excludes]
    Q[quartz build<br/>md -> Preact SSG]; PP[custom Preact<br/>product page types]
    WC[free wiki chrome:<br/>search / graph / backlinks / explorer]
  end
  CP --> SYM --> IG --> Q --> PP & WC --> D[(public/ static)]
  D --> SV[quartz --serve :8080]

Boundary map

  • Content plane: untouched — symlinks only, nothing copied or rewritten.
  • Presentation plane: the entire (near-forked) Quartz clone; upstream upgrades arrive as git merges against a pinned base.
  • Curation layer: ignorePatterns / ExplicitPublish inside quartz.config.ts — excludes live in one site-config file, one place to audit.

Test seams

  • Build-as-test: quartz build fails on broken markdown; the build is the first gate.
  • Link check: Quartz’s own broken-link handling, plus a small crawl script over public/ for anchors.
  • Mermaid: renders natively client-side — a real render check needs a headless page-load pass, not just a green build.
  • Visual gate: impeccable skill against served pages; caveat — the post-cutoff Preact/v5 component model is the least familiar surface of the four for agents iterating on design.

Evolution path / exit cost

  • Evolution: lean into wiki features (backlinks, graph) if the corpus ever grows wikilinks; ceiling = fighting Quartz’s docs-site opinions when product pages need fully bespoke design.
  • Exit: cheap — content was never touched; delete site/, keep nothing.

Rough cost (estimates, design-gated)

  • Install-to-first-page: ~1–2 h — clone, pin, symlinks, excludes, first build; the wiki chrome means the library view is done at that point.
  • Per new product page: ~2–4 h — the page itself is fast, but clearing the anti-template bar inside an unfamiliar post-cutoff Preact API is where agent time goes; budget extra impeccable-gate iterations.

Option B — Astro 7 + Tailwind v4 bespoke (curated product pages)

Essence: site/ is an Astro 7.1 app. Content Layer glob() loaders with base: ../plans and ../research — out-of-tree content is documented first-class, no symlinks needed. Markdown pipeline pinned to @astrojs/markdown-remark (restores the remark/rehype ecosystem, avoids Satteri’s newness) + astro-mermaid + Tailwind v4 via @tailwindcss/vite, with design tokens locked in a DESIGN.md. Pages: program overview, /products/<x> as hand-crafted .astro pages composing collection entries, /library/* auto-rendering the full included corpus. Output = static dist/; authoring loop = astro dev --background (7.0 shipped this explicitly for AI agents); serve via python http.server or a systemd –user unit. Known agent failure modes — the deprecated @astrojs/tailwind reflex, Satteri/remark confusion, the legacy collections API — are all pinnable in CLAUDE.md.

flowchart LR
  subgraph CP[content plane - untouched]
    P[plans/]; R[research/]
  end
  subgraph SITE[site/ - Astro 7.1 app]
    GL[Content Layer glob loaders<br/>base: ../ + exclude patterns]
    MR[markdown-remark pinned +<br/>astro-mermaid + Tailwind v4 vite]
    DT[DESIGN.md-locked tokens]
    PR[/products/x hand-crafted .astro/]; LB[/library/* auto-rendered corpus/]
  end
  CP --> GL --> MR --> PR & LB --> D[(dist/ static)]
  DT -.constrains.-> PR
  D --> SV[http.server or systemd-user unit :8080]

Boundary map

  • Content plane: untouched — no symlinks; loader base points out of tree, documented first-class.
  • Presentation plane: site/ with DESIGN.md-locked tokens; product pages are composed .astro files, library pages are one dynamic route.
  • Curation layer: glob include/exclude patterns in content.config.ts, colocated with the loaders that consume them.

Test seams

  • Build-as-test: astro build fails loudly on bad frontmatter or collection misuse — good failure legibility for agents.
  • Link check: rehype plugin in the pinned pipeline, or a dist crawl script.
  • Mermaid: astro-mermaid — checkable at build if pre-rendered, else one headless pass over dist/.
  • Visual gate: impeccable against the dev server; .astro + Tailwind is a surface agents iterate quickly, and the token lockfile gives the anti-template rule teeth.

Evolution path / exit cost

  • Evolution: islands/SSR adapters if interactivity is ever needed; each product page hardens into a reusable pattern library for the next one.
  • Exit: delete site/; content and DESIGN.md survive as plain files. Sunk cost = the .astro pages themselves.

Rough cost (estimates, design-gated)

  • Install-to-first-page: ~2–4 h — scaffold, pin the pipeline, loaders + excludes, DESIGN.md, first overview page through the gate.
  • Per new product page: ~1–2 h once tokens and the first exemplar page exist; the known failure modes must be pinned in CLAUDE.md or agents burn the savings on the deprecated-integration reflex.

Option C — Next.js 16 static export (house stack)

Essence: site/ is a Next 16.2 app with output: 'export'. Content via the content-collections library, or a ~100-line fs+remark pipeline. Product pages are React components — the one candidate with possible component sharing with velin (house stack is Next; the Groupon monorepo is Next). Everything markdown is DIY: mermaid, GFM pipeline, link handling all assembled by hand. Footprint ~300–500 MB node_modules; Next’s monthly security-patch cadence applies even to a static internal site. Evolution is the headline: flip output: 'export' off and it becomes a full app with zero migration.

flowchart LR
  subgraph CP[content plane - untouched]
    P[plans/]; R[research/]
  end
  subgraph SITE[site/ - Next 16.2, output: export]
    CC[content-collections lib or<br/>~100-line fs+remark pipeline<br/>+ hand-rolled exclude list]
    MM[DIY md assembly:<br/>GFM + mermaid + links]
    RP[React product pages<br/>possible velin component sharing]
  end
  CP --> CC --> MM --> RP --> D[(out/ static)]
  D --> SV[http.server :8080]

Boundary map

  • Content plane: untouched — read by the pipeline at build time.
  • Presentation plane: site/ React components, sharing design language (and possibly components) with the rest of the house stack.
  • Curation layer: the exclude list inside the DIY content pipeline — hand-rolled code, so it must be tested, not just configured.

Test seams

  • Build-as-test: the export fails on bad pages, though Next build errors are the least legible of the four candidates.
  • Link + mermaid checks: fully DIY — the hand-rolled pipeline needs its own small test suite.
  • Confidentiality check: mandatory here — one assert that no excluded path ever reaches out/, because the fence is bespoke code rather than a framework config key.
  • Visual gate: impeccable against next dev; React is maximum agent familiarity, the fastest design-iteration loop of the four.

Evolution path / exit cost

  • Evolution: best-in-class — flip export off → full app, zero migration; components portable to velin.
  • Exit: delete site/, but sunk cost is the highest (the DIY pipeline is owned bespoke code), and staying costs a monthly patch cadence + the heaviest install.

Rough cost (estimates, design-gated)

  • Install-to-first-page: ~4–8 h — the md/mermaid pipeline is built, not installed, and it gates everything downstream.
  • Per new product page: ~1–2 h once the pipeline exists — house-stack React makes this the cheapest per-page iteration loop.

Option D — VitePress 1.6.4 custom theme (markdown-native lane)

Essence: site/ is VitePress pinned at 1.6.4 (2.0 is alpha — do not chase it). Markdown-it pipeline: GFM alerts native, mermaid via vitepress-plugin-mermaid in one config block. Content enters via symlinked src dirs. A custom theme with its own Layout.vue kills the default docs chrome; layout: page gives a blank canvas for product pages, polished with Vue SFCs. The off-stack fact: the house is React, so Vue SFC polish is the one place agents work off the home stack. Builds in seconds; ~100–150 MB footprint.

flowchart LR
  subgraph CP[content plane - untouched]
    P[plans/]; R[research/]
  end
  subgraph SITE[site/ - VitePress 1.6.4 pinned]
    SYM[symlinked src dirs<br/>+ srcExclude patterns]
    MI[markdown-it: GFM alerts native +<br/>vitepress-plugin-mermaid one block]
    TH[custom theme Layout.vue<br/>kills docs chrome]
    VS[layout: page blank canvas<br/>Vue SFC product pages]
  end
  CP --> SYM --> MI --> TH --> VS --> D[(dist/ static)]
  D --> SV[vitepress preview / http.server :8080]

Boundary map

  • Content plane: untouched behind symlinks.
  • Presentation plane: the custom theme (Layout.vue) + SFC product pages.
  • Curation layer: srcExclude patterns in config.ts — one array, easy to audit; but with symlinks in place that array is the only fence, so it deserves its own check.

Test seams

  • Build-as-test: VitePress fails the build on dead links by default — the strongest free link check of the four.
  • Mermaid: rendered via the plugin at build time; a green build covers the 43 fences.
  • Loop speed: seconds-fast builds make the whole check loop the cheapest here.
  • Visual gate: impeccable against vitepress dev; caveat — every design iteration happens in Vue, off the house stack.

Evolution path / exit cost

  • Evolution: stays a content site — that is what it is; interactivity beyond islands of Vue means replatforming.
  • Exit: delete site/; content untouched, theme CSS partially portable, Vue components are not.

Rough cost (estimates, design-gated)

  • Install-to-first-page: ~1–3 h — install, pin, symlinks, srcExclude, kill the chrome via custom Layout.vue.
  • Per new product page: ~2–3 h — the blank canvas is real, but agents pay a Vue tax on every polish pass, and the impeccable gate multiplies exactly that iteration count.