Routing-First Progressive Disclosure Architecture in Diagram-Design Explained
The routing-first progressive disclosure architecture in diagram-design resolves routing information before any UI components are revealed to the user, enabling lazy loading of heavy modules based on the selected profile.
Diagram-design, developed by Cathryn Lavery, implements a unique architectural pattern that prioritizes route determination over immediate UI rendering. This approach ensures that the system only loads the components necessary for a specific diagram type, resulting in faster startup times and a more modular codebase. The architecture centers on marker-first resolution, where the system parses an input marker to select the appropriate router before any visual elements appear.
Core Principles of the Architecture
Marker-First Resolution
The architecture begins with marker parsing. According to docs/adr/0006-client-profiles-and-marker-first-resolution.md, the engine examines a token (the marker) that identifies either a diagram type or a client profile. This marker determines which router handles the request.
Only after the router selection completes does the system proceed to reveal subsequent UI controls. This ordering guarantees that no unnecessary rendering code executes before the system knows what type of diagram it needs to support.
Client Profiles
A profile describes a concrete rendering context such as mermaid, drawio, or plantuml. The router evaluates the profile early in the lifecycle, then lazily loads the heavyweight UI elements specific to that profile.
This profile-driven approach means:
- The mermaid profile loads mermaid-specific parsers and renderers
- The drawio profile initializes drawio-compatible components
- Unused profiles remain dormant in the codebase
Static-by-Default Controllers
As documented in docs/adr/0001-static-by-default-single-pinned-controller.md, controllers in diagram-design are pinned to a single entry point. They do not mutate after the initial routing decision.
This static binding delivers two benefits:
- Deterministic behavior — the same input always produces the same routing outcome
- Simplified progressive disclosure — UI components can trust that routing state will not change underneath them
How the Routing-First Flow Works
The routing-first progressive disclosure architecture follows a strict five-step sequence:
- Parse input — The command line or API call provides a marker (e.g.,
import-mermaid) and optional profile flags - Route selection — The router matches the marker to a concrete command module like
commands/import-mermaid.md - Profile resolution — The selected module reads the profile and determines which rendering engine and assets are required
- Progressive UI load — Only the UI pieces needed for the chosen profile initialize (menus, preview widgets, export options)
- Execution — The command generates the diagram using the resolved routing and profile
Code Examples from the Repository
Defining a Marker in a Command File
The file commands/import-mermaid.md illustrates how markers and profiles are declared:
# import-mermaid
marker: import-mermaid
profile: mermaid
description: Import a Mermaid diagram and render it.
This metadata drives the routing decision before any UI code executes.
Router Implementation Pattern
The core routing logic in src/router.js demonstrates marker-first resolution:
import { loadCommand } from './loader.js';
export function route(input) {
const { marker, profile } = parseInput(input);
const command = loadCommand(marker); // ← routing first
return command.run({ profile }); // ← progressive disclosure
}
Note the strict ordering: loadCommand(marker) completes before command.run() begins.
Progressive UI Disclosure
The src/ui.js module implements lazy loading based on resolved profiles:
export function discloseUI(profile) {
if (profile === 'mermaid') {
import('./ui/mermaidPanel.js').then(mod => mod.show());
} else if (profile === 'drawio') {
import('./ui/drawioPanel.js').then(mod => mod.show());
}
// Only the panel for the chosen profile is loaded.
}
Dynamic import() calls ensure that unused UI modules never enter the bundle.
Benefits of Routing-First Progressive Disclosure
| Benefit | Mechanism |
|---|---|
| Performance | Heavy modules load on-demand, reducing initial bundle size and startup time |
| Extensibility | New markers or profiles integrate without modifying core routing logic |
| Predictability | Fixed routing sequence guarantees consistent UI state for each diagram type |
Key Implementation Files
docs/adr/0006-client-profiles-and-marker-first-resolution.md— Marker-first routing and profile resolution strategydocs/adr/0001-static-by-default-single-pinned-controller.md— Static controller design underpinning the routing stepdocs/adr/0008-native-host-manifests-share-one-plugin-root.md— Progressive disclosure implementation detailscommands/import-mermaid.md— Example command file defining markers and profiles
Summary
- Routing-first progressive disclosure means resolving the route before revealing any UI components
- Marker-first resolution in
docs/adr/0006-client-profiles-and-marker-first-resolution.mddrives the initial routing decision - Client profiles enable lazy loading of profile-specific modules like mermaid or drawio components
- Static-by-default controllers in
docs/adr/0001-static-by-default-single-pinned-controller.mdensure predictable, immutable routing state - The architecture delivers improved performance, extensibility, and predictability through strict ordering and dynamic imports
Frequently Asked Questions
What makes routing-first progressive disclosure different from traditional lazy loading?
Traditional lazy loading typically defers module loading until a user interacts with a feature. Routing-first progressive disclosure, as implemented in diagram-design, makes the routing decision the gatekeeper for all subsequent loading. The system in src/router.js resolves the marker and profile before any UI code executes, ensuring that only the exact modules needed for that specific diagram type ever load.
How does the marker system support new diagram types?
Markers are declared in command files like commands/import-mermaid.md using simple metadata. When adding a new diagram type, you create a new command file with its own marker and profile. The router in src/router.js automatically discovers these markers without requiring changes to core routing logic, as documented in docs/adr/0006-client-profiles-and-marker-first-resolution.md.
Why are controllers static-by-default in this architecture?
Static controllers, described in docs/adr/0001-static-by-default-single-pinned-controller.md, eliminate runtime mutation of routing state. This design choice supports progressive disclosure because UI components can safely assume that the routing decision remains constant throughout their lifecycle. Dynamic controller changes would introduce uncertainty about which UI modules should remain loaded.
Can routing-first progressive disclosure improve application startup time?
Yes. The architecture's strict ordering ensures that heavy parsing, rendering, and UI modules load only after the lightweight routing phase completes. The src/ui.js implementation uses dynamic import() statements to fetch modules like mermaidPanel.js or drawioPanel.js only when their respective profiles are active, keeping the initial bundle minimal.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →