Files
blueprints/DESIGN.md
Julien Calixte 03804b10dc feat: gallery + generic blueprint viewer, add Grid blueprint
Refactor the List-specific screen into a data-driven, reusable viewer:
- generic Blueprint type + shared LoadState machine + registry
- vue-router: / (gallery) and /b/:slug (illustration)
- BlueprintViewer renders any blueprint; specimens stay bespoke
- add Grid blueprint (6 functions incl. Position) + GridSpecimen
2026-07-02 18:34:49 +02:00

4.0 KiB

Design — blueprints

Decisions for building blueprints out from a single List illustration into a gallery of many. Terminology: see CONTEXT.md.

D1 · Content sourcing: hand-authored typed data + bespoke specimen

Each blueprint is a typed TS data module (src/data/<name>Blueprint.ts), transcribed by hand from its ontology README, paired with a bespoke Specimen component. The generic Viewer renders everything else (Readout, composition map, state machine) from that data.

  • Why not parse the ontology at build time? The Specimen must be hand-built for every blueprint regardless (the ontology only provides an ASCII sketch), so parsing would automate only the cheap, structured text — at the cost of fragile markdown/mermaid parsing and a build-time coupling to the ontology repo's exact format. Not worth it.
  • Source of truth stays the blueprint-ontology repo; the data modules are a faithful transcription, cited in each module's header.

Structural split this implies:

Part Generic (data-driven) Bespoke (per blueprint)
Chrome (title block, tabs, legend)
Readout (dossier per function)
Composition map ✓ (from extends + composes data)
State machine ✓ (from nodes/edges data)
Specimen ✓ component slotted into the Viewer

D2 · Routing: vue-router, URL per blueprint

Add vue-router. Routes: / → Gallery, /b/:slug → the blueprint's illustration (e.g. /b/list). Deep-linkable and shareable; browser back/forward works. The nginx SPA fallback (try_files … /index.html) already serves client routes, so no server change is needed. A blueprint registry (src/data/blueprints.ts) maps slug → { data module, specimen component, meta } and is the single source both the router and the Gallery read from.

The Gallery lists only blueprints that have an illustration; it grows as we add them. No greyed "planned" cards. Rationale: keeps the landing clean and truthful, and avoids maintaining metadata for 45 not-yet-built entries. A blueprint appears in the Gallery precisely when it is registered in src/data/blueprints.ts.

D4 · Build-out slice #1: foundation + Grid

Foundation (refactor, no UX change to List):

  • pnpm add vue-router; App.vue → thin shell with a header (link home) + <RouterView/>.
  • src/views/GalleryView.vue (/) — cards from the registry.
  • src/views/BlueprintView.vue (/b/:slug) — resolves the registry entry, renders the Viewer.
  • src/components/BlueprintViewer.vue — the generic Viewer, generalized from the current List-specific App.vue: title block, legend, function tabs + full view, two panes, optional composition map + state machine, footer. Props: a Blueprint object + the blueprint's Specimen component (injected via <component :is>).
  • Generic Blueprint type in src/data/blueprint.ts (signature, functions, coreInvariants, optional composition, optional stateMachine, meta). listBlueprint.ts conforms to it. Specimens move to src/specimens/.
  • src/data/blueprints.ts — registry: slug → { meta, blueprint, specimen }.

Content: gridBlueprint.ts + src/specimens/GridSpecimen.vue (2D tile grid).

Ships: Gallery listing List + Grid; /b/list (same UX, refactored) and /b/grid.

Gates before push: pnpm build clean · pnpm lint · pnpm fmt; then commit → push (auto-deploys) → verify https://blueprints.apoena.dev.

Subsequent slices add one blueprint each (Table, Feed, …).