HTML Explainer
An explainer is documentation that teaches, and it teaches from the outside in. The reader meets the thing the way its users meet it — what they ask of it, what they get back, how it behaves — before they meet how it is built. This keeps the explanation product-focused: it describes outcomes for the caller, not the internal machinery, even when the subject is the machinery.
This skill owns the perspective discipline (below) and a set of visual
diagram patterns (diagrams.md). It bundles its own styling so it works in any
project, but defers to a project's own house style when one exists.
The one load-bearing rule
The caller's perspective always comes first. Internals always come after.
Everything else here is guidance you can adapt per subject. This rule is not. If you catch yourself opening with a data structure, a class diagram, or "the system is composed of…", stop — you have started inside. Back up to the boundary.
Who "the user" is, by subject
The skill explains many kinds of things. Identify the caller first:
| Subject | "The user" is… | Lead with… | |---|---|---| | A UI | the person clicking | what they see, do, and get — screen by screen | | A library / package | the developer writing code against its surface | the exported functions, the call, the return | | A service / API | the consumer making requests | the endpoint, the request, the response, the errors | | An implementation | whoever calls into this code | the contract it honors and the outcome it produces | | A protocol / format | the party producing or consuming it | a real message and what each side does with it |
Even when the requested topic is internal (e.g. "explain the state machine inside the packfile assembler"), open with what the caller hands in and what comes back out — then descend into the internal states. The internals are framed as how the promised outcome is kept, never as the starting point.
Input
The user describes the thing to explain. You do not autonomously reverse- engineer a subsystem to write this — the framing comes from their description.
- If they point you at code, a spec, or an
openapi.yaml, read it only to make examples concrete and correct (real signatures, real request/response shapes). - Ask clarifying questions only when the user-first framing is genuinely unclear — specifically: who the caller is, what outcome they care about, or the audience's level. One or two questions, then write. Do not run a full interview.
Drafting, outside in
- Fix the perspective. Name the caller (table above) and the single outcome
they care about most. This becomes the
<p class="lead">. - Open with a picture. The first visual should be a diagram of the boundary —
what the caller sends in / gets back — not internal structure. See
diagrams.md(.boundary,.flow). - The user-first explanation. Walk the caller's experience: the call/click,
the result, the common variations, the errors they can hit. Make it concrete
with annotated examples (
<pre>request/response, real signatures). This section must stand on its own — a reader who stops here understands how to use the thing. Load thewriting-proseskill before drafting this body copy — the reader is meeting the subject for the first time, the same reader that skill writes for. - Then internals, if relevant. Only after the above, descend. Frame every internal detail as how the promised outcome is kept. Internal state walks, sequence diagrams, and data structures live here — never above. If the request was specifically about internals, this is where the depth goes, but it still follows the caller-facing section.
- Color-code the boundary. Convention: blue (
--accent) marks what the caller touches (the surface); muted/green marks what is internal. Carry this through diagrams and pills so "outside vs inside" is visible at a glance.
Visuals
Lead with diagrams; prose supports them, not the reverse. The explanation is carried by:
- Diagrams — flow, state-machine, and sequence diagrams render through
Mermaid (the template already loads and themes it); boundary and tree
diagrams are plain HTML/CSS. Copy patterns from
diagrams.md, which defines them in terms of the bundled template's design tokens. Keep only the branches/nodes relevant to the point being made — an overstuffed diagram teaches less than a small one. - Annotated examples — real request/response bodies, function signatures,
before/after blocks. Use the template's
<pre><code>with<span class="cmd">and<span class="muted">for emphasis.
Mermaid is the one JavaScript dependency the template carries, loaded from
cdn.jsdelivr.net — this means the explainer needs network access to render,
and is no longer usable fully offline. No other interactivity or animation
libraries; a state machine is drawn, not animated.
Producing the file
- Pick the styling source:
- If the project has an
html-docsskill or adocs/design.md, follow it — copy itstemplate.htmland keep its tokens; this skill's diagram patterns still apply (map the colors to the local token names). If that template doesn't already load Mermaid, carry over this template's<script type="module">block and theme itsthemeVariablesto the local tokens. - Otherwise use the bundled template:
cp ~/.claude/skills/html-explainer/template.html <target>.html.
- If the project has an
- Keep the
<style>block verbatim — it is the design system. No CSS framework, no web fonts. The bundled template already loads and themes Mermaid; the only diagram CSS to append is the boundary pattern fromdiagrams.md(additive, built only on existingvar(--…)tokens). - Write the body following the outside-in order above, using the template's
component vocabulary (
.lead,.grid2/.card,.callout,.pill,.layers,<pre>,<table>) plus the diagram snippets. Single centred column, no sidebar; navigation is the heading structure. - Footer: note what the explainer was generated from.
- Host for review (the template is a single self-contained file — just serve
its directory):
Run it in the background and confirm withcd <dir with the .html> peep -p 8090 # then open http://localhost:8090/<file>.htmlcurl -s -o /dev/null -w "%{http_code}" http://localhost:8090/<file>.html(expect 200). Ifpeepisn't installed, tell the user the file path so they can open it directly. - Publish it. Once it loads clean, publish the file as a Claude Artifact
(the
Artifacttool,action: publish) so the user gets a shareable link — do this by default, every time, unless the user has said not to. Give it a title and a favicon that fit the subject.
Default target: write beside the source it explains (e.g.
docs/<thing>-explainer.html), or a scratch/temp dir for a quick throwaway.
Confirm the path if it isn't obvious.
Smell test (you have drifted inside if…)
- The first heading or first diagram is about architecture, not about what the caller gets.
- You describe a struct/table/class before describing the outcome it produces.
- The reader has to understand the implementation to understand how to use the thing.
- The word "internally" appears before the reader has seen a single call, request, or screen.
Any of these → back up to the boundary and lead with the caller.