Generates interactive multi-page HTML codebase courses with Mermaid.js diagrams, architecture walkthroughs, module dependency tutorials, data-flow views, and per-module deep dives. Use when asked to teach, map, explain, or visually tour a repository.
Generate a multi-page interactive HTML site that teaches a codebase as scrollable essays — architecture views, default Build-Up walkthroughs, beautiful-mermaid diagrams, typed pedagogical units (concept, quiz, takeaway, diagram, code-walk, code-graph, whoa) carrying the lesson. Zero build tools, zero npm. Each output page links shared CSS, runtime JS, and the beautiful-mermaid browser bundle; diagrams render client-side with Raycast dark theming.
When to Use
"Generate an interactive course for this codebase"
"Create a visual walkthrough of this project's architecture"
"Make an interactive module dependency diagram"
"Build a tutorial page from this codebase"
Output
Directory:
docs/codemermaid/
style.css <- Copied from assets/style.css
runtime.js <- Copied from assets/runtime.js
index.html <- Entry page (perspective + module cards)
architecture.html <- Architecture perspective (essay, always generated)
build-up.html <- Build-Up Walkthrough perspective (essay, always generated)
<perspective>.html <- Other user-requested or auto-inferred perspectives (essays)
module-<name>.html <- Per-module deep dives (essays, optional module-level Build-Up when useful)
Each HTML page links
style.css
,
runtime.js
,
beautiful-mermaid.bundle.js
, and
mermaid-bridge.js
via
<link>
and
<script src>
. Diagrams use Mermaid.js syntax rendered via the beautiful-mermaid browser bundle. The assembly process copies these assets from
assets/
to the output directory alongside the HTML files.
Parallel Generation Mode
If subagents are available and the repo has enough independent modules, read
references/subagent-generation.md
before dispatching work.
The main agent remains coordinator and owns the module registry, filename registry, perspective list, index page, link graph, and final validation. Subagents may only work inside assigned scopes.
Phase 1: Scan
Read the codebase exhaustively. The goal is to discover ALL meaningful modules, not just the obvious ones.
Step 1.1: Structural Scan
Root directory — list all top-level folders and files
Source directories — for each top-level folder, list its contents recursively (2 levels deep)
Entry files —
main.*
,
index.*
,
app.*
,
server.*
,
cmd/
,
src/
,
lib/
,
pkg/
Config files —
package.json
,
go.mod
,
Cargo.toml
,
pyproject.toml
,
Makefile
,
docker-compose.yml
, equivalent
Framework detection — language, framework, runtime from config and imports
Test directories —
test/
,
tests/
,
spec/
,
__tests__/
,
*_test.*
Step 1.2: Deep Module Discovery
For EACH source directory found above, determine if it qualifies as a module:
A module is any directory or file that has a clear single responsibility
Read the first 30 lines of every entry file to understand purpose
Use Grep to find
import
,
require
,
use
,
from
patterns — map dependency edges
Check
exports
,
module.exports
,
pub
,
public
— identify public interfaces
What counts as a module:
Type
Examples
Top-level source dir
src/auth/
,
src/api/
,
src/models/
Standalone config file
tsconfig.json
,
docker-compose.yml
,
.env.example
Utility/helper dir
src/utils/
,
src/helpers/
,
src/lib/
Plugin/extension dir
plugins/
,
extensions/
,
modules/
Data layer
src/db/
,
src/store/
,
src/repositories/
Build/CI config
Makefile
,
Dockerfile
,
.github/workflows/
Skill/command dir
.agents/skills/
,
.opencode/commands/
Single important file
skills-lock.json
,
CLAUDE.md
, routing config
What to skip:
node_modules/
,
vendor/
,
.git/
,
dist/
,
build/
, cache dirs
Generated files, lock files (except
skills-lock.json
if meaningful)
Test fixtures, static assets with no logic
Step 1.3: Dependency Mapping
For every module discovered, trace its imports:
Module A → imports from → Module B, Module C
Module B → imports from → Module D
Module C → imports from → Module D (optional)
This becomes the edge list for Mermaid diagrams. Use Glob and Grep extensively. Read actual code. Do NOT guess.
Phase 2: Analyze
From scan results:
Architecture pattern — MVC, microservices, monolith, event-driven, hexagonal, layered, etc.
Data flow — trace the primary request path entry → response, and secondary flows
Module graph — full dependency graph from Phase 1.3, identify cycles and layers
Key abstractions — interfaces, base classes, core types that define the system's vocabulary
Module categorization — group modules into layers:
Layer
Typical Modules
Entry
HTTP handlers, CLI commands, main entry points
Core
Business logic, domain models, services
Data
Database, repositories, ORM, state management
Infra
Config, logging, middleware, error handling
Output
Templates, serializers, API responses
DevX
Build tools, CI/CD, skills, commands
Prioritization: If the codebase has more than 12 modules, organize into sub-graphs.
Default perspective requirements — Architecture and Build-Up are always included.
architecture.html
gives the finished-system map;
build-up.html
gives the gradual learning route from smallest useful capability to complete system.
User perspective requirements — parse user prompt for explicit perspective requests. User-requested perspectives are mandatory.
Auto-infer perspectives — from project characteristics:
Has HTTP handlers, WebSocket, or event streams → Data Flow perspective
Has database/ORM → Data Model perspective
Has state management → State Machine perspective
10+ modules → Module Dependency perspective
Has CI/CD config → Build Pipeline perspective
Merge perspective list — default + user-specified + auto-inferred, deduplicated. Recommended index order: Architecture Overview, Build-Up Walkthrough, then user-requested and auto-inferred perspectives. Every discovered module must be reachable from at least one perspective page.
Derive Build-Up route — before drafting
build-up.html
, read
references/build-up.md
and choose a reader-comprehension order from discovered modules and dependency evidence.
changes the label and placement, not the color palette.
Voice rules
Before writing generated prose, read
references/voice-examples.md
. Follow that file for voice, signposts, anti-patterns, and rewrite recipes.
Code explanation depth (mandatory — do not skimp)
Every piece of code shown to the reader MUST be thoroughly explained. This is the core value of the course — the reader is here to understand code they couldn't read on their own.
concept units before a code-walk must explain:
What the module/function does and why it exists (its role in the system)
What pattern or tradeoff is at play (why this approach over alternatives)
Any non-obvious context the reader needs before seeing the code
code-walk highlights[].note must explain:
What the highlighted line does (not just restate the code — explain the why)
How it connects to the surrounding logic (data flow, control flow, side effects)
Any implicit behavior not visible in the code (e.g., "this returns null because the upstream function hasn't resolved yet")
Non-trivial API usage (e.g., "Array.from creates a shallow copy — we do this because the NodeList returned by querySelectorAll is live, meaning it updates when the DOM changes")
diagram captions must explain:
What the diagram shows and why that flow/structure matters
Where the interesting part is (not just "this is the architecture")
quiz explanations must explain:
Why the correct answer is correct (with specific code evidence)
Why each wrong answer is wrong (briefly)
ANTI-PATTERN: Lazy notes. The following are banned:
Notes that restate the code:
note: "Calls verify() on line 3"
when the code says
const user = await verify(token)
Notes that say "see above" or "as mentioned earlier" without re-explaining
Concept bodies that say "this module handles X" without explaining how or why
Captions that say "Module dependency diagram" without saying what's interesting about the dependencies
GOOD example:
{ line: 5, note: "verify() is async because it makes a network call to the JWT issuer's .well-known/jwks.json endpoint. The await here means the middleware pauses — no downstream handler runs until this resolves. That's fine for auth, but it means every request pays this latency cost, even for public endpoints that don't need auth." }
BAD example:
{ line: 5, note: "Calls verify() to validate the JWT token." }
Unit quality guidelines (soft limits)
Prefer depth over brevity. These are upper bounds, not targets — write as much as needed to truly explain the code.
Unit
Suggested scope
concept
80–200 words — must explain why, not just what
quiz
question ≤ 2 sentences, 4 options, explanation ≤ 100 words — must reference specific code
takeaway
3–5 sentences — must synthesize, not just repeat
diagram
≤ 8 nodes, caption 20–50 words — must say what's interesting, not just what it shows
code-walk
8–20 lines code + 3–6 annotations — each note must explain the reasoning, not just restate what the code says
code-graph
8–15 lines code + mini SVG (4–6 nodes) — same depth as code-walk for annotations
Rule of thumb: If you can remove an annotation note and the reader loses no understanding, the note wasn't detailed enough — rewrite it, don't remove it.
There is no fixed unit budget. A module page should include as many units as needed to teach its content thoroughly. If a page exceeds ~15 units, consider splitting into sub-modules.
Pedagogy enforcement (mandatory)
Every generated page MUST satisfy these rules:
Every module MUST have a non-empty
learningPromise
.
Every module's
units[]
MUST contain ≥ 1
quiz
.
Every module's
units[]
MUST end with a
takeaway
.
Every perspective's
units[]
MUST start with a
concept
and end with a
takeaway
.
There is no hard cap on unit count; quality of explanation determines the length.
Real code only
All
code
values must be exact, unmodified copies from real source files. This includes:
code-walk.code
code-graph.code
Prohibited:
Inventing code that does not exist in the source
Simplifying logic (e.g., removing a ternary, reordering statements)
Changing prop names, variable names, or function signatures
Adding comments that don't exist in the source
Using
...
ellipsis to hide lines inside a snippet (use
// ...
comment only at the top level to mark elision)
Allowed:
Extracting a contiguous slice of a function with
// ...
at top/bottom to show it's truncated
Removing import statements and surrounding boilerplate to focus on the logic
Normalizing indentation to match the snippet's context
Code presentation rules
Keep teaching snippets tight:
Trim leading and trailing blank lines from every
code
value.
Collapse repeated interior blank lines to one blank line.
Prefer
// ...
or
# ...
elision comments over airy blank rows when skipping irrelevant source.
startLine
is the original source file line used for editor/file actions only;
highlights[].line
remains snippet-local after trimming.
Highlight numbers are 1-based and must match the visible line numbers within the extracted snippet after trimming.
Verification rule: Before finalizing a page, manually count lines in every
code
value. Ensure every
highlights[].line
points to a line that actually exists in that snippet and contains meaningful code.
Common pitfall: When extracting a 15-line function from a 200-line file, the highlights must reference line numbers 1–15 (the snippet), NOT the original file's line numbers 186–200.
Do not highlight blank separator lines; move highlights to the nearest meaningful source line.
Annotation-note alignment: The note text must describe what happens on the highlighted line(s). If the note says "mergeMessage dedupes by id" but the highlighted line is
...state,
, the highlight is on the wrong line.
Code file action controls
When a
code-walk
or
code-graph
unit has a real source file path, render file actions in the
The selected editor option opens immediately. Selecting the already-active option still opens the file, because the menu uses buttons instead of a native
<select>
.
Unit examples
Before drafting unit data, read
references/units-examples.md
for concrete object shapes, unit-specific options, defaults, and interaction bindings.
Keep the unit-level traps in mind: callout concepts use
style: "callout"
, quizzes need exactly one correct answer, code-walk line numbers are snippet-local, and code-graph bindings must match SVG
data-node-id
values.
Phase 4: Build Mermaid Diagrams
Before writing diagrams, read
references/svg-patterns.md
.
Use Mermaid for
diagram
units and raw inline SVG only for
code-graph
mini-graphs that need
data-node-id
click-sync. Keep node IDs consistent across pages, use descriptive labels, and do not inline theme overrides; the Raycast dark theme is configured in
mermaid-bridge.js
.
Phase 5: Generate Page List
File
Skeleton
Condition
index.html
skeleton-index.html
Always
architecture.html
skeleton-essay.html
Always
build-up.html
skeleton-essay.html
Always
<perspective>.html
skeleton-essay.html
One per non-default perspective
module-<name>.html
skeleton-essay.html
One per discovered module
All generated course files go in
docs/codemermaid/
. Filenames are kebab-case except the fixed
index.html
.
Before generating HTML pages, copy shared assets to the output directory:
Copy
assets/style.css
→
docs/codemermaid/style.css
Copy
assets/runtime.js
→
docs/codemermaid/runtime.js
Copy
assets/beautiful-mermaid.bundle.js
→
docs/codemermaid/beautiful-mermaid.bundle.js
Copy
assets/mermaid-bridge.js
→
docs/codemermaid/mermaid-bridge.js
These are linked by every generated HTML page.
Phase 6: Write HTML Pages
For each page in the file list (Phase 5):
Assembly process
Read the skeleton template:
assets/skeleton-essay.html
or
assets/skeleton-index.html
Generate content HTML for each
<!-- SLOT:... -->
marker (see below)
Replace all slots with their content HTML
Pre-flight verification (mandatory — do not skip):
Every
highlights[].line
points to an existing, non-blank line in its snippet
Every code snippet is an exact copy from source (no invented lines, no reordered statements)
No
href="#"
placeholders — all back/next links point to real files
No
**bold**
markdown — use
<strong></strong>
instead
Inside
<pre class="code-block">
,
.line
spans are adjacent with NO whitespace between them
Quiz has exactly 1 option with
data-correct="true"
No double HTML entity escaping — scan for
&#
or
&lt;
or
&gt;
patterns and fix them
Mermaid syntax is valid — no unclosed brackets, no missing quotes in edge labels
index.html
links to
build-up.html
in the Perspectives section
build-up.html
exists, starts with a
concept
, contains at least one
quiz
, and ends with a
takeaway
Build-Up copy describes a learning order, not an unverified implementation chronology
Every Build-Up step explains a capability change; it is not only a module inventory
Every
whoa
unit has
angle
,
title
, and
body
Every
whoa.angle
is
code
,
product
,
ux
, or
architecture
whoa
units use one visual treatment; no angle-specific color classes
Every rendered file action with
data-copy-path
points to a real source file path and includes a line number
Dispatch a subagent reviewer to validate the generated HTML
<navclass="toc"><divclass="toc-label">On this page</div><olclass="toc-list"><li><aclass="toc-item"href="#unit-0"><spanclass="toc-num">1</span>{TITLE}<spanclass="toc-kind">{KIND}</span></a></li><!-- one per unit --></ol></nav>
<!-- SLOT:UNITS -->
: One
<section>
per unit:
html
<sectionclass="unit unit-{KIND}"id="unit-{INDEX}"><!-- unit content HTML --></section>
only when evidence exists. Flatten evidence in this order: files, modules, interactions, constraints. Keep evidence text short enough to fit in a pill; use file basenames or repo-relative paths rather than long absolute paths inside evidence chips.
For evidence chips, repeat one
<divclass="codewalk-split"><!-- Use the Code file action controls header from above when a real source path exists. Otherwise render a simple header with <span class="codewalk-file">{FILE}</span>. --><divclass="codewalk-head"><spanclass="codewalk-file">{FILE}</span><span>{LANG}</span></div><divclass="codewalk-split-body"><preclass="code-block">{LINES}</pre><divclass="codewalk-annotations">{ANNOTATIONS}</div></div></div>
<divclass="codegraph-split"><!-- Use the Code file action controls header from above when a real source path exists. Otherwise render a simple header with <span class="codewalk-file">{FILE}</span>. --><divclass="codewalk-head"><spanclass="codewalk-file">{FILE}</span><span>{LANG}</span></div><divclass="codegraph-split-body"><preclass="code-block">{LINES with data-graph-node}</pre><divclass="codegraph-graph">{SVG}</div></div></div>
Perspective cards should list default perspectives first: Architecture Overview, then Build-Up Walkthrough, followed by user-requested and auto-inferred perspectives. The Build-Up card must link to
build-up.html
and describe the gradual route from smallest useful capability to complete system.
<!-- SLOT:MODULE_CARDS -->
:
html
<divclass="section"><divclass="section-title">Module Deep Dives</div><divclass="card-grid"><aclass="card"href="module-{NAME}.html"><spanclass="card-type">module</span><h3>{TITLE}</h3><p>{DESCRIPTION}</p><divclass="card-meta">{N} units</div></a></div></div>
Design System
Use the bundled Raycast-inspired dark theme in
assets/style.css
. For visual rationale and token guidance, read
DESIGN.md
and
references/design-system.md
.
Important Rules
Read Build-Up reference — before creating
build-up.html
or a module-level Build-Up section, read
references/build-up.md
.
Default perspectives — always generate
architecture.html
and
build-up.html
.
Real code only — never invent, simplify, or modify code snippets.
Cover every module — every module discovered in Phase 1 must appear in at least one perspective page AND have its own
module-<name>.html
.
Linked shared assets — copy
style.css
,
runtime.js
,
beautiful-mermaid.bundle.js
, and
mermaid-bridge.js
to the output directory. Each HTML links them via
<link>
and
<script src>
.
Vanilla JS only — no React, no build tools.
beautiful-mermaid via browser bundle — all
diagram
units use Mermaid syntax rendered by the beautiful-mermaid browser bundle +
mermaid-bridge.js
.
code-graph
mini-graphs use raw SVG for
data-node-id
click-sync.
Build-Up is learning order — describe capability increments in the order that teaches the system, not unverified git or implementation history.
Module-level Build-Up is optional — include it only when the module has a natural internal progression. Do not force it into every module page.
Pre whitespace rule — inside
<pre class="code-block">
,
.line
spans must be adjacent with NO whitespace between them.
Quiz correctness — every quiz must have exactly 1 option with
data-correct="true"
.
Consistent node IDs — same module = same node ID across all pages.
User perspective overrides — user-specified perspectives are mandatory; auto-inferred are supplementary.
Annotation alignment — the runtime's
alignAnnotations()
handles vertical positioning. CSS
gap
on
.codewalk-annotations
must be
0
.
Common Mistakes
Mistake
Fix
Missing
build-up.html
Always generate the required Build-Up Walkthrough perspective and link it from
index.html
.
Build-Up reads like git history
Reframe it as reader learning order unless git history was explicitly inspected and cited.
Build-Up is just a module list
Rewrite each step around a capability change and name the code that makes the change possible.
Forced module-level Build-Up
Remove it when a normal code-walk teaches the module more clearly.
Blank lines between code lines
.line
spans inside
<pre>
must be adjacent — no newlines or spaces between them.
Highlight points to wrong line
Count lines within the extracted snippet, not the original source file.
Code snippet has invented lines
Paste the snippet back into a temp file and run the type checker.
href="#"
in links
Replace with actual relative paths. Never leave placeholder links.
Side-by-side code looks cramped
Ensure
grid-template-columns: minmax(0, 1fr) 300px
is applied.
Quiz has no correct answer
Exactly 1 option must have
data-correct="true"
.
Double HTML entity escaping
Scan output for
&#
,
&lt;
,
&gt;
— these are wrong. The correct forms are
'
,
<
,
>
.
Mermaid edge label missing quotes
Use pipe syntax: `A -->
Annotations not aligned with code
Confirm CSS
.codewalk-annotations { gap: 0 }
and runtime.js
alignAnnotations()
runs on DOMContentLoaded.
beautiful-mermaid not rendering
Ensure
beautiful-mermaid.bundle.js
and
mermaid-bridge.js
are copied to output dir and linked in correct order (bundle in