Skip to main content

Investigate: Architecture Diagram Display — Collapsible + Zoomable

IMPLEMENTATION RULES: Before implementing this plan, read and follow:

Status: Decided — ready for plan (2026-04-15)

Goal: Restructure the auto-generated ## Architecture section so it's discoverable (headings visible as signposts so readers know diagrams exist) but not imposing (each individual diagram collapsed behind a dropdown so readers who just want to run the template aren't confronted with a wall of SVGs). Also add click-to-zoom so diagrams remain readable when a developer DOES open one. Also design the data model now so adding a third or fourth diagram per sub-section later is additive, not a rewrite.

Last Updated: 2026-04-15

Related (same arc of Environment-card work):


Background

User ask, across two rounds of discussion:

Round 1: "We now display the Architecture mermaid diagrams. This should also be optional to see as it is too much for developers that just want it to work and don't need to see how it works. Can we have something similar that we have on the drop downs? It is also important that the user can click on the mermaid diagram to see it better/focused/zoomed."

Round 2 (refinement): "We now have 2 diagrams for local development and for deployment. We need to think that there in the future can be more diagrams and therefore plan for that now. What about displaying Architecture, and below that have the two Local development and Deployment. Then for local deployment have dropdown/expand/open for local deployment Components and local deployment Flow. This way the user can see that there are diagrams that document how it works, and he can choose to open the diagram he wants."

Three concerns, all worth solving:

  1. Cognitive load by default. The current E1 page (python-basic-webserver-database) renders four mermaid diagrams under a single ## Architecture heading — two flowcharts and two sequence diagrams. That's a lot of screen real estate for a developer whose immediate goal is "scaffold the template and run it".

  2. Discoverability. A reader should know that diagrams exist for each sub-section even if they haven't clicked yet. Round-2 ask: keep the section headings (### Local development, ### Deployment) visible as signposts, and collapse only the individual diagrams.

  3. Future-proofing. Today there are exactly 2 diagrams per sub-section (flowchart + sequence). In the future there may be 3, 4, or more — e.g. an error/failure flow, a data-flow view, a network-topology view, a security/trust-boundary diagram. The data model and renderer should handle N diagrams per sub-section from the start.

  4. Readability when opened. Mermaid SVGs render at a fixed size inside the page's content column. On wide diagrams or small screens the text gets cramped. Developers who DO open a diagram need a way to enlarge it without leaving the page.

This investigation picks an approach for all four axes and defers implementation to a downstream PLAN-*.md.


Current state

How the architecture section renders today

Generated by scripts/lib/build-architecture-mermaid.ts and pasted verbatim into the MDX page by scripts/generate-docs-markdown.sh. On the E1 template (python-basic-webserver-database) the structure is:

## Architecture

### Local development

(mermaid flowchart)

(mermaid sequence diagram)

### Deployment

(mermaid flowchart)

(mermaid sequence diagram)

Four fenced ```mermaid blocks total. Each one becomes an inline <svg> element at build time via @docusaurus/theme-mermaid. No wrapping element, no collapse mechanism, no zoom affordance.

E2 templates (app without services) render only the ### Deployment sub-section (2 diagrams). E3 stack templates render a single ### Overview sub-section (2 diagrams). E4 overlays render nothing. Numbers of diagrams per archetype:

ArchetypeExampleDiagrams
E1 — app + services + manifestpython-basic-webserver-database4
E2 — app + manifest, no servicespython-basic-webserver2
E3 — stack templatepostgresql-demo2
E4 — overlayplan-based-workflow0 (section suppressed)

What's already in place for zoom

  • docusaurus-plugin-image-zoom@^3.0.1 is listed as a dependency and registered in docusaurus.config.ts line 65 as a plugin entry
  • BUT: no themeConfig.zoom block configures it. The plugin is loaded but has no selector, no background, no options — it's effectively a no-op today
  • Also: mermaid renders as inline <svg>, not as <img>. docusaurus-plugin-image-zoom wraps the medium-zoom library, which by default targets .markdown img. Even a configured image-zoom plugin wouldn't catch mermaid SVGs without a custom selector — and medium-zoom's ability to handle non-<img> elements is not its sweet spot

So the zoom story starts from scratch, not from "finish configuring what's there".

What's already in place for collapsibility

The Environment card already uses <details> + the shared .detailsBlock CSS class (from Phase 4 of the environment-card plan) for three sub-dropdowns: init-SQL files, template-info.yaml, and Expected output. The CSS supports dark mode and sits nicely inside the card's visual language.

This class is reusable verbatim for architecture diagrams. The visual consistency argument favours using it.

Out of scope but flagged

The generated MDX page currently has a duplicate ## Prerequisites heading (line 47 from the generator + line 195 from the README being appended). This investigation is not the place to fix it, but worth filing as a trivial follow-up.


Options for collapsibility (axis A)

A1 — ✅ Per-diagram dropdowns, headings visible (user's Round-2 direction)

The structural headings stay visible so readers discover what's available. Each individual diagram sits behind its own <details> summary.

## Architecture

Short prose (one sentence) telling readers what to expect.

### Local development

▶ Components (collapsed <details>, shows the flowchart)
▶ Flow (collapsed <details>, shows the sequence diagram)

### Deployment

▶ Components (collapsed flowchart)
▶ Flow (collapsed sequence diagram)

Pros:

  • Discoverable — the reader sees ### Local development and ### Deployment headings even when everything is collapsed, so they know there's documentation about both phases
  • Granular — a reader who only cares about deployment can open just that diagram, leaving local-dev collapsed
  • Per-diagram naming creates vocabulary (Components / Flow) that future diagrams can extend (Components / Flow / Errors / Data flow / …)
  • Matches the existing .detailsBlock visual vocabulary from the Environment card
  • Scales naturally to N diagrams: adding a third diagram to a sub-section is just appending one more <details> block, no structural rework

Cons:

  • 4 dropdowns per E1 page by default — more visual elements than A2/A3 below. Mitigation: compact summary row styling (small font, tight padding) so four collapsed dropdowns take up ~80 px vertical space, not 200+.
  • The reader has to click twice to see both diagrams in a sub-section (once per dropdown). For a developer who wants to read everything, that's more friction than a single unified toggle.

A2 — Wrap the whole ## Architecture section in one <details> (REJECTED in Round 2)

Originally my tentative recommendation from Round 1. Single dropdown, single click to reveal everything. Rejected in Round 2 because it hides the existence of the ### Local development and ### Deployment sub-sections — the reader doesn't know what's behind the toggle until they click it.

A3 — Wrap each sub-section (### Local development, ### Deployment) in its own <details> (REJECTED)

Two dropdowns, one per sub-section. Rejected because: (a) still hides the per-diagram vocabulary (Components vs Flow), (b) adding a third diagram later would require rework since this level of grouping doesn't know about individual diagrams, and (c) it doesn't give the user the per-diagram granularity they asked for in Round 2.

A4 — Single expand/collapse button at the top of the section (REJECTED)

Heavier implementation (custom React component), less consistent with the existing <details> vocabulary, doesn't match the per-diagram granularity.

Decision (collapsibility)

A1 — per-diagram dropdowns with section headings visible, collapsed by default, matching the user's Round-2 direction. The four dropdowns on an E1 page are the right tradeoff: more visual elements than a single toggle, but each one named meaningfully so readers can target exactly what they want.


Options for click-to-zoom (axis B)

B1. Fullscreen modal on click (native <dialog> element)

Click the SVG → opens a native HTML <dialog> element overlaying the viewport with the same SVG rendered larger. Browser's backdrop + close-on-Escape work out of the box.

Pros:

  • Zero dependencies (native browser API, supported everywhere)
  • Accessibility is built in (focus trapping, Escape key, aria-modal semantics via the native element)
  • Works on mobile via the device's native pinch-zoom once the modal is open
  • The SVG just scales up to fill the viewport — mermaid SVGs are vector so they stay crisp at any size

Cons:

  • Need a small React component to wrap each mermaid diagram with an on-click handler that opens the dialog
  • Need to swizzle Docusaurus's mermaid theme component, OR post-process the rendered SVG with a small client-side script
  • <dialog> styling can be finicky (backdrop, centering, responsive sizing)

B2. medium-zoom with a custom selector targeting mermaid SVGs

Configure the already-present docusaurus-plugin-image-zoom plugin (or import medium-zoom directly) with a selector like .docusaurus-mermaid-container svg.

Pros:

  • Leverages the plugin we already have
  • medium-zoom is a tiny library with a polished fade-and-scale animation — most developers have seen it on Medium articles
  • One-line config change if the plugin works on SVG

Cons:

  • Unverified: medium-zoom is designed around <img> elements. It may or may not work cleanly with inline SVG. The library supports a selector option that accepts any DOM element, and it reads the element's getBoundingClientRect — in theory SVG works, but we'd need to test
  • If it doesn't work cleanly, the fallback is B1 anyway, so we spike-test this first and fall through

B3. svg-pan-zoom library — in-place pan and zoom

Wrap each rendered SVG with event listeners that let the user drag and pinch-zoom the diagram while it stays in its original place on the page.

Pros:

  • No modal — the reader stays in context
  • Powerful for really complex diagrams where a static enlarged view still isn't enough

Cons:

  • Adds a runtime library (~3 KB minified)
  • Overkill for our diagrams (5–12 nodes, nothing needs fine-grained pan/zoom interaction)
  • Mobile interaction competes with browser scrolling — can feel janky
  • No single "ah-I-can-see-it-now" moment; pan/zoom is more exploratory than focused

Each diagram gets a small "Open in mermaid.live" link below it. The link encodes the diagram source into a mermaid.live URL where the reader has full pan/zoom/edit.

Pros:

  • Zero runtime code in our site
  • mermaid.live is the canonical mermaid editor; developers who want to play with the diagram can do so

Cons:

  • External dependency on a third-party site
  • Doesn't solve the "I want to see it bigger right now" flow — it takes the reader out of the docs
  • Not what the user described ("click on the mermaid diagram to see it better/focused/zoomed")

Recommendation (zoom)

Spike B2 first, fall back to B1 if it doesn't work cleanly on inline SVG. The plugin is already installed; if it just needs a one-line config change to target mermaid SVGs, the whole zoom story collapses into that one line. If medium-zoom can't cleanly handle SVG targets, bite the bullet and write a small custom <dialog>-based modal component. Both paths converge on the same UX ("click to enlarge in an overlay"), which is the pattern the user described.


Extensibility — planning for N diagrams per sub-section (axis C)

Today's hardcoded shape in scripts/lib/build-architecture-mermaid.ts:

interface ArchitectureResult {
mdx: string | null; // pre-composed MDX string, all 4 diagrams baked in
}

The builder concatenates exactly 2 diagrams per sub-section (flowchart + sequence) into one monolithic MDX string. Adding a third diagram today means: add a new builder function, call it from buildArchitectureMdx, glue the output into the MDX string between the existing ones, update the generator + docs-markdown emitter + every unit-test fixture. High-friction.

Target data-model shape — a list of named diagrams per sub-section:

interface ArchitectureDiagram {
name: string; // "Components", "Flow", future: "Errors", "Data flow", ...
summary?: string; // optional short description under the summary line
mermaid: string; // the mermaid source, without the fence
}

interface ArchitectureSection {
title: string; // "Local development", "Deployment", future: "Operations", ...
intro?: string; // optional one-line intro below the heading
diagrams: ArchitectureDiagram[]; // 1..N diagrams, in render order
}

interface ArchitectureResult {
intro?: string; // optional top-level intro below the ## Architecture heading
sections: ArchitectureSection[]; // 0..N sub-sections
}

Rendered output becomes a renderer loop, not a concatenation:

for section of result.sections:
emit "### {section.title}"
emit section.intro (if present)
for diagram of section.diagrams:
emit <details className={detailsBlock}>
emit <summary>{diagram.name}</summary>
emit ```mermaid
emit {diagram.mermaid}
emit ```
emit </details>

Adding a third diagram type is then a pure data change: push a new ArchitectureDiagram onto the right section's diagrams array. The emitter, the component, and the unit tests all work unchanged.

What changes in the builder

The current buildLocalDevFlowchart, buildLocalDevSequence, buildDeployFlowchart, buildDeploySequence functions each return a mermaid string. They stay — only their composition changes. buildArchitectureMdx becomes buildArchitectureModel and returns the structured ArchitectureResult object. A new emitter (either in generate-docs-markdown.sh via jq, or more likely a new TS helper called during registry generation) walks the model and produces the final MDX block with the per-diagram <details> wrappers.

Implementation surface

FileChange
scripts/lib/build-architecture-mermaid.tsRename buildArchitectureMdxbuildArchitectureModel; return the structured model instead of a pre-composed MDX string
scripts/lib/build-architecture-mdx.ts (new)Emitter that walks the model and produces the MDX block with <details> wrappers per diagram
scripts/generate-registry.tsCall the new emitter; store the MDX output on the entry same way as today
scripts/test/build-architecture-mermaid.test.tsUpdate fixtures to assert the structured model shape; add a separate test file build-architecture-mdx.test.ts for the emitter
website/docs/contributors/...Short note for contributors: "adding a new diagram to an existing section is a one-line change in buildArchitectureModel"

Rejected alternative: yaml-authored diagrams

One tempting option is to let template authors declare diagrams in template-info.yaml:

architecture:
local_development:
- name: Components
mermaid: |
flowchart LR
...

Rejected because it contradicts the "auto-generate from existing data" principle from the completed architecture-diagram-v2 plan. Authors should not hand-write mermaid; the generator should produce it from registry data (services, manifest, init files, etc.). Yaml authoring would re-introduce exactly the drift risk that the v2 plan eliminated.

Decision (extensibility)

Refactor the builder to return a structured ArchitectureResult model (sections with N diagrams each). Adopt this in the same downstream plan as the collapsibility refactor — the MDX rendering shape has to change anyway for the per-diagram <details> wrappers, and doing both refactors in one pass is cheaper than sequencing them.


Prior art the user vaguely remembered

Patterns seen in the wild that match the user's description:

  • GitHub README mermaid rendering (launched mid-2022): diagrams render inline; click-to-zoom was added later via an expand button in the diagram's top-right corner that opens a fullscreen overlay with pan/zoom
  • mermaid.live editor: the target of the "open in mermaid.live" option (B4)
  • Notion (and similar wiki tools): mermaid blocks render inline; click opens a modal with the source code beside the rendered diagram
  • Medium articles: medium-zoom — the exact library that docusaurus-plugin-image-zoom wraps. Click an image, it fades/scales to fullscreen. Pressing Escape or scrolling closes it. This is almost certainly what the user half-remembered.
  • StackEdit, HackMD: inline mermaid with no zoom — not what we want
  • Confluence + draw.io: click an embedded diagram → opens the full editor. Heavy, not what we want

The user's description ("I have seen this on the net, but I can't remember where") is most consistent with medium-zoom — a smooth fade-to-fullscreen click that many developers have seen on Medium articles without necessarily knowing the library name.


Open Questions

Q1. Names for the two current diagram types (per Round 2 ask)

The user asked: "local deployment architecture and local deployment <what is the name of the flow diagram>". The two diagram types need human-readable names that will become the dropdown summaries and also the keys in the structured data model.

Current mermaid kinds:

  • Flowchart (flowchart LR): shows the nodes and edges — the steady-state "what are the pieces and how are they wired" view
  • Sequence diagram (sequenceDiagram): shows the ordered steps — the "what happens when you run the configure command" view

Candidate name pairs (flowchart / sequence):

OptionFlowchart nameSequence nameNotes
AComponentsFlowClear vocabulary; "flow" matches the user's word; future diagrams extend naturally ("Errors", "Data flow", "Network")
BStructureSequenceSlightly more technical; "sequence" matches the mermaid kind name
CLayoutTimelineLess common vocabulary
DWhat it isWhat happensPlain English; no jargon; slightly less crisp as dropdown labels
EDiagramSequenceUses the generic "diagram" for the flowchart — weak, leaves room for ambiguity

Tentative recommendation: Option A — Components / Flow. Crisp, matches the user's vocabulary, and the word "Components" has the useful side-effect that it primes the reader to think about the named boxes (Developer, DCT, UIS, K8s, app, browser) rather than the arrows. Future diagrams can slot in with their own nouns: Errors, Data flow, Network, Security.

Decision (2026-04-15): Option A — Components / Flow. ✅

Q2. Default state: collapsed or expanded?

Under the new A1 per-diagram dropdown structure, "collapsed by default" means every <details> starts closed but the ### Local development and ### Deployment headings stay visible. Readers always see that diagrams exist — they just don't see the content until they click.

  • A: Collapsed by default (matches user's framing; optimizes for "I just want to run it")
  • B: Expanded by default (shows off the auto-generated content)
  • C: First diagram in each sub-section expanded, the rest collapsed (a compromise — the reader sees one diagram per sub-section immediately, knows there's more if they want it)

Tentative recommendation: Option A (all collapsed by default) — matches the user's stated framing. The sub-section headings and dropdown summary rows provide enough discoverability; you don't need a rendered diagram to know the diagram exists.

Decision (2026-04-15): Option A — all collapsed by default. ✅

Q3. Dropdown summary text style

Given the per-diagram dropdown structure, each summary row needs a label. Options for the format:

  • Just the diagram name: ▶ Components / ▶ Flow
  • Prefixed by what it is: ▶ Components — how the pieces are wired / ▶ Flow — step-by-step sequence
  • Prefixed by mermaid kind: ▶ Flowchart — components / ▶ Sequence — flow

Tentative recommendation: just the diagram name (▶ Components / ▶ Flow). Short, scannable, low visual weight when all four are stacked on an E1 page. Optional short descriptions can be added inside the <details> body above the mermaid block if needed.

Decision (2026-04-15): just the diagram name. ✅

Q4. Top-level ## Architecture intro sentence

With the sub-section headings visible, the top of the section could include a one-sentence intro to set expectations. Options:

  • No intro — the heading alone is enough
  • One sentence: "These diagrams describe how the template works. They are auto-generated from the template's metadata. Click any diagram to enlarge."
  • One sentence + extensibility hint: "These diagrams are auto-generated from the template's metadata. Today there are two views per phase (Components and Flow); more may be added over time."

Tentative recommendation: one short sentence to explain the auto-generation and prompt the click-to-zoom affordance. Don't mention future diagrams — the reader doesn't care about roadmap, they care about what's there today.

Decision (2026-04-15): one short sentence. Exact wording: "These diagrams are auto-generated from the template's metadata. Click any diagram to enlarge."

Q5. Does medium-zoom work on inline SVG, or do we need a custom modal?

This is the biggest unknown. Needs a 30-minute spike before the downstream plan can be scoped. The spike is: configure the existing plugin with a selector that targets mermaid SVGs (e.g. .docusaurus-mermaid-container svg or similar), build, open a template page, click a diagram, observe.

  • If it just works: the entire zoom story is a one-line config change
  • If it kind-of works (e.g. mouse click opens the zoom but touch doesn't, or the SVG doesn't scale correctly): document the gap and choose between patching medium-zoom, switching to B1 (native <dialog>), or accepting the limitation
  • If it doesn't work at all: go with B1 (native <dialog> modal) and write a small React component

Recommendation: time-box the spike to 30 minutes. If we can't get it working in that window, switch to B1.

Decision (2026-04-15): spike B2 first, fall back to B1 if medium-zoom can't cleanly handle inline SVG. ✅

Q6. Where does the section live on the page?

The current ## Architecture is a top-level heading between the Environment card and the README content. Options:

  • A: Keep it as a top-level section at its current position (below Environment card, above README)
  • B: Move it inside the Environment card as a new numbered sub-section
  • C: Move it below the README

Tentative recommendation: Option A — keep it where it is. The Environment card is already dense; adding a fifth numbered sub-section for architecture would bloat it. Putting it below the README means readers who don't scroll to the end miss it.

Decision (2026-04-15): Option A — keep current position (top-level section between Environment card and README). ✅

Q7. Zoom interaction on mobile

  • A: Same click-to-enlarge flow; touch events map to click events; native pinch-zoom works inside the fullscreen modal
  • B: Tap to open mermaid.live in a new tab (leverages mobile browser's native pan/zoom on that page)
  • C: Hide the Architecture section entirely on narrow screens (media query)

Tentative recommendation: Option A — same component, same interaction. Don't hide content from mobile readers.

Decision (2026-04-15): Option A — same click-to-enlarge component across desktop and mobile. ✅

Q8. Apply universally across all 10 templates?

  • E1 (python-basic-webserver-database) has 4 diagrams → benefits the most
  • E2 (6 app templates, no services) has 2 diagrams → mild benefit
  • E3 (postgresql-demo) has 2 diagrams → mild benefit
  • E4 (plan-based-workflow overlay) has 0 diagrams → no section at all

Tentative recommendation: apply universally — consistency across the catalog matters more than micro-optimising per archetype.

Decision (2026-04-15): apply universally across all 10 templates. ✅


Decisions locked in (2026-04-15)

All axes and questions decided.

Collapsibility (axis A): ✅ Option A1 — per-diagram dropdowns with section headings visible. Each mermaid diagram wrapped in its own <details className={detailsBlock}>. Collapsed by default. Applied universally across all 10 templates.

Zoom (axis B): ✅ Spike Option B2 first (configure docusaurus-plugin-image-zoom with a selector that targets mermaid SVGs). If the spike succeeds, one config change covers it. If it fails, fall back to Option B1 (native <dialog>-based React component that opens a fullscreen overlay).

Extensibility (axis C): ✅ Refactor buildArchitectureMdxbuildArchitectureModel returning a structured ArchitectureResult { sections: Array<{ title, diagrams: Array<{ name, mermaid }> }> }. Emitter walks the model. Adding a third or fourth diagram later is a one-line change to the builder, not a structural refactor. Done in the same downstream plan as axis A.

Naming: ✅ Components (flowchart) and Flow (sequence diagram), per Q1 Option A. Locked into the data-model names, the dropdown summary rows, and the contributor docs that describe the generator.

Intro sentence: "These diagrams are auto-generated from the template's metadata. Click any diagram to enlarge."

Page shape on E1 templates post-implementation:

## Architecture

These diagrams are auto-generated from the template's metadata.
Click any diagram to enlarge.

### Local development

▶ Components
▶ Flow

### Deployment

▶ Components
▶ Flow

On E2 (app, no services): only ### Deployment with its two dropdowns. On E3 (stack): a single ### Overview with its two dropdowns. On E4 (overlay): the section is suppressed entirely, same as today.

Future follow-ups (deferred, not in the downstream plan)

These are explicitly deferred so they don't bloat the immediate plan. File as separate investigations or small PRs after the main plan ships.

Once the in-page zoom (B2 or B1) is working, add a small text link below each mermaid diagram pointing at mermaid.live with the diagram source pre-loaded via the URL hash. Developers who want full pan/zoom, editing, or to copy-paste into their own docs can click through to the canonical mermaid editor.

Why deferred: not needed for the core "I want to see this bigger" use case the user described. Nice-to-have for power users. File after B2/B1 ships and has been used in anger.

Implementation note: mermaid.live accepts a base64-encoded JSON payload in the URL hash (https://mermaid.live/edit#pako:...). The emitter would need to encode the diagram source at build time and emit a link next to each dropdown summary. Small, independent change.

F2. Duplicate ## Prerequisites heading on generated pages

The E1 template page currently has two ## Prerequisites headings (line 47 from the generator, line 195 from the appended README content). Trivial fix in generate-docs-markdown.sh — detect that the registry already emitted a prerequisites section and skip the README-derived one, or vice versa. Out of scope for this investigation but worth a small follow-up PR.


Next Steps

  • User answers Q1–Q8 — all decided 2026-04-15
  • 30-minute spike on Q5 (does medium-zoom work on inline SVG?) — report back with findings. Happens as Phase 1 of the downstream plan.
  • Draft PLAN-architecture-diagram-display.md in backlog/ based on the locked decisions
  • Implement the plan once approved
  • Move this investigation to completed/ alongside the downstream plan
  • After the plan ships and B2/B1 is in production: file a small follow-up PR or mini-investigation for F1 (mermaid.live link)
  • File a separate tiny follow-up for the duplicate ## Prerequisites heading (F2)