Explainer Site Skill
SkillWeb & browsingCreate "How X Works" deep-dive explainer websites with the curious, technical-but-accessible style of howkeyboardswork.com. Use when asked to explain how something works, create an educational single-page guide, or build an interactive explainer site on any topic.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Explainer Site Skill skill
What this skill tells your AI
The instructions your AI receives, as published by drpedapati/sciclaw in skills/explainer-site/SKILL.md and read by ahel’s review.
Create deep-dive, single-page explainer websites in the style of howkeyboardswork.com — technically rigorous but accessible, personal yet authoritative, with progressive disclosure from overview to implementation details.
Key Insight: The magic is in three things: (1) personal voice that invites exploration, (2) pipeline thinking that shows the journey, and (3) beautiful Mermaid diagrams that explain visually what words struggle to convey.
When to Use This Skill
Trigger phrases:
- "Create a 'How X Works' site"
- "Build an explainer page for..."
- "I want a deep-dive guide on..."
- "Make a site like howkeyboardswork.com but for..."
- "Educational single-page site about..."
The Formula
This pattern works for any technical topic: keyboards, databases, compilers, HTTP, neural networks, coffee machines, refrigerators, etc. The magic is in the combination of personal voice, progressive depth, and pipeline thinking.
Reference Examples
Study these implementations before building your own:
Inspiration
- howkeyboardswork.com — The gold standard. Personal voice, pipeline thinking, interactive toys, beautiful diagrams. Study the opening hook, the section rhythm, and how it balances accessibility with depth.
Working Demo
- how-memory-works — A complete implementation of this skill pattern, explaining how AI memory systems work.
- Stack: Nuxt 4 + TailwindCSS + beautiful-mermaid
- Features: 4 interactive SVG toys (MemoryPipeline, ContextWindow, SearchSequence, HeartbeatState)
- Design: Monochrome by default, substantial figure captions, prose-first
- Clone it, run
npm install && npm run dev, and explore the code
Use the demo as a starting point. Copy the project structure, component patterns, and diagram setup. Replace the content with your topic.
Voice & Tone Guidelines
The Opening Hook
Start with genuine personal curiosity. This establishes credibility through passion, not credentials.
Pattern:
I'm obsessed with [TOPIC] and the [ASPECT] we [USE/ENCOUNTER] every day without thinking twice about.
We [ACTION] [FREQUENCY], yet most of us have no idea what actually happens [BEHIND THE SCENES DESCRIPTION].
I wanted to figure out how all of that worked — [LIST KEY COMPONENTS] — and decided to document what I learned on this site.
It's been a way to deepen my own understanding and hopefully make it easier for others to appreciate the [QUALITY] behind something we all [USE/TAKE FOR GRANTED].
Let's go deep. [RELEVANT EMOJI]
Example for databases:
I'm obsessed with databases and the invisible infrastructure we rely on every day without thinking twice about.
We query data billions of times a day, yet most of us have no idea what actually happens between typing SELECT and seeing results.
I wanted to figure out how all of that worked — the parsing, the query planning, the storage engines, the whole stack — and decided to document what I learned on this site.
It's been a way to deepen my own understanding and hopefully make it easier for others to appreciate the quiet engineering behind something we all depend on.
Let's go deep. 🗄️
Tone Principles
- First-person, conversational — "I wanted to figure out", "Let's explore"
- Invitational, not lecturing — "Let's go deep" not "This guide will teach you"
- Technical precision with plain language — Define jargon on first use
- Genuine curiosity — Share your "aha" moments
- Progressive confidence — Start accessible, get technical
- Practical grounding — Connect abstractions to real-world effects
Sentence Style
- Short sentences for impact
- Longer sentences for explanation, then short for punch
- Use em-dashes for asides (in this style, they work)
- Parenthetical examples: "(e.g., Cherry MX Red)"
- Questions to transition: "But how does the controller know which key?"
Content Structure
1. The Pipeline Overview
Every complex system is a pipeline — a chain of transformations from input to output. Start by showing the full journey, then zoom into each stage.
Pattern:
## The [TOPIC] Pipeline
From [INPUT] to [OUTPUT] — the journey of a [UNIT]
When you [ACTION], it feels instantaneous. But between [START STATE] and [END STATE],
an intricate chain of events unfolds in [TIMEFRAME].
This guide walks you through every step of that journey. We'll explore [COMPONENT 1],
[COMPONENT 2], [COMPONENT 3], and finally [COMPONENT N].
Understanding this pipeline helps you appreciate why [INSIGHT 1], why [INSIGHT 2],
and how [INSIGHT 3].
[OPTIONAL: Interactive visualization description]
The entire journey typically takes [TIME RANGE].
2. Section Template
Each section follows a consistent pattern:
## [Component Name]
[One-line evocative description]
[Opening paragraph: What is this component? Why does it exist? Hook the reader.]
## [Subsection: Core Concept]
[Detailed explanation of the main idea]
## [Subsection: Variations/Types]
[Different implementations or categories]
- **Type A**: [Description] (e.g., [Example])
- **Type B**: [Description] (e.g., [Example])
- **Type C**: [Description] (e.g., [Example])
## [Subsection: The Problem This Solves]
[What would go wrong without this? Real consequences.]
## [Subsection: Real-World Considerations]
[How does this play out in practice? Trade-offs, tuning, edge cases.]
[OPTIONAL: Callout box for important aside]
[OPTIONAL: Source attribution for images/data]
3. Section Ordering
Sections should follow the pipeline flow — the natural order of data/events through the system:
- Physical/Input Layer — Where the journey begins
- Conversion/Translation — How raw input becomes structured
- Processing/Logic — The core transformation
- Communication/Protocol — How information moves between components
- Output/Delivery — How results reach the end user
- Meta Concerns — Latency, measurement, optimization
4. Practical Commands Section (Optional)
For systems/tools that users can configure, add a "Configuring the System" section with:
- File structure — Show the workspace layout in a code block
- Commands table — Natural language triggers and what they do
- Configuration examples — Real config file snippets
- Quick reference table — Summary of files/commands for scanning
<div class="not-prose my-4">
<table class="w-full text-sm border border-slate-200 rounded">
<thead class="bg-slate-50">
<tr>
<th class="text-left p-3 border-b font-medium">Command</th>
<th class="text-left p-3 border-b font-medium">What it does</th>
</tr>
</thead>
<tbody>
<tr class="border-b border-slate-100">
<td class="p-3 font-mono text-xs">"Remember that..."</td>
<td class="p-3">Writes to daily notes</td>
</tr>
</tbody>
</table>
</div>
This section shifts from "how it works" to "how to use it" while maintaining the same voice.
5. The Closing
End with satisfaction and a soft call-to-action (if relevant):
## And That's How [TOPIC] Work[s]!
From [START] through [MIDDLE COMPONENTS] to [END] — every [UNIT] is a small engineering marvel.
[OPTIONAL: Soft CTA to related product/project]
Now that you know the journey each [UNIT] takes, you might start wondering — [RELATED QUESTION]?
[Product/Tool Name] [DOES SOMETHING RELATED], turning [INVISIBLE THING] into [VISIBLE BENEFIT].
It's a [POSITIVE FRAMING] way to [BENEFIT].
[CTA Button Text]
Technical Implementation
Tech Stack
The reference implementation uses:
- Nuxt 3 (Vue.js framework)
- TailwindCSS with
@tailwindcss/typography - @nuxt/content for markdown content
- Static generation (Cloudflare Pages/Workers)
Project Structure
├── assets/css/ # Global styles (tailwind.css)
├── components/
│ ├── base/ # Reusable UI (Button, Card, etc.)
│ ├── content/ # Markdown components (Callout, etc.)
│ └── toys/ # Interactive demos/visualizations
├── content/guide/ # Markdown content files
│ ├── 00-intro.md
│ ├── 01-pipeline.md
│ ├── 02-component-a.md
│ ├── 03-component-b.md
│ └── ...
├── layouts/ # App layouts
├── pages/ # Route pages
│ └── index.vue # Single-page that renders all sections
├── public/ # Static assets (images, og-image.jpg)
├── nuxt.config.ts # Nuxt configuration
├── tailwind.config.ts # Tailwind configuration
└── package.json
Markdown Frontmatter
Each section is a markdown file with frontmatter:
---
title: Section Title
description: Brief evocative description (shown as subtitle)
order: 2
slug: section-slug
---
Sections are automatically sorted by order and rendered sequentially on the homepage.
Tailwind Typography Config
Use @tailwindcss/typography for beautiful prose styling:
// tailwind.config.ts
export default {
theme: {
extend: {
colors: {
primary: {
500: '#0ea5e9', // Main accent
600: '#0284c7', // Links
700: '#0369a1', // Hover
}
},
typography: {
DEFAULT: {
css: {
maxWidth: 'none',
color: '#374151',
a: {
color: '#0284c7',
textDecoration: 'none',
'&:hover': { textDecoration: 'underline' }
},
code: {
backgroundColor: '#f3f4f6',
padding: '0.25rem 0.375rem',
borderRadius: '0.25rem',
fontWeight: '400'
}
}
}
}
}
},
plugins: [require('@tailwindcss/typography')]
}
Custom Components
Create reusable content components for markdown:
Callout Component (components/content/Callout.vue):
<template>
<div :class="['callout', `callout-${type}`]">
<div class="callout-title">{{ title }}</div>
<div class="callout-content">
<slot />
</div>
</div>
</template>
<script setup>
defineProps({
title: String,
type: { type: String, default: 'info' } // info, warning, tip
})
</script>
Usage in markdown:
::Callout{title="Important Note" type="info"}
The actuation point is usually higher than the bottom-out point.
::
Header Design (The Frosted Glass Pattern)
The header should be minimal, functional, and elegant. Study howkeyboardswork.com's header — it's a masterclass in restraint.
The Complete Pattern
<header class="sticky top-0 z-50 bg-white/80 backdrop-blur-sm border-b border-gray-200">
<div class="max-w-6xl mx-auto px-4 py-4 flex items-center justify-between">
<!-- Logo + Title (left) -->
<a href="/" class="flex items-center gap-2 font-semibold text-lg text-gray-900 hover:text-sky-600 transition-colors">
<img src="/favicon.svg" alt="" class="w-auto h-8">
Site Title
</a>
<!-- Utility Link (right) -->
<a href="https://github.com/..."
target="_blank"
rel="noopener noreferrer"
class="text-sm text-gray-600 hover:text-gray-900 transition-colors">
View Source
</a>
</div>
</header>
Key Techniques
| Element | Classes | Purpose |
|---|---|---|
| Frosted glass | bg-white/80 backdrop-blur-sm | 80% white + blur = content visible but unreadable |
| Sticky behavior | sticky top-0 z-50 | Stays on top during scroll |
| Subtle border | border-b border-gray-200 | Definition without heaviness |
| Logo size | h-8 (32px) | Visible but not dominating |
| Logo gap | gap-2 (8px) | Breathing room between icon and text |
| Layout | flex items-center justify-between | Logo left, utility right |
Vue Component
<template>
<header class="sticky top-0 z-50 bg-white/80 backdrop-blur-sm border-b border-gray-200">
<div class="max-w-6xl mx-auto px-4 py-4 flex items-center justify-between">
<NuxtLink to="/" class="flex items-center gap-2 font-semibold text-lg text-gray-900 hover:text-sky-600 transition-colors">
<img src="/favicon.svg" alt="" class="w-auto h-8">
{{ title }}
</NuxtLink>
<a
v-if="sourceUrl"
:href="sourceUrl"
target="_blank"
rel="noopener noreferrer"
class="text-sm text-gray-600 hover:text-gray-900 transition-colors"
>
View Source
</a>
</div>
</header>
</template>
<script setup>
defineProps({
title: { type: String, required: true },
sourceUrl: { type: String, default: null }
})
</script>
What NOT to Put in the Header
- No navigation dropdowns — Single-page explainer uses sidebar TOC
- No social icons — Footer, if anywhere
- No search bar — Cmd+F works for single-page sites
- No heavy shadows — Frosted glass + border is enough
- No large logos —
h-8(32px) is plenty
Dark Mode Variant
<header class="sticky top-0 z-50 bg-slate-900/80 backdrop-blur-sm border-b border-slate-700">
<!-- Same structure, different colors -->
</header>
Beautiful Mermaid Diagrams (Critical!)
Diagrams are not optional. The reference sites use extensive visualizations to explain concepts. Use beautiful-mermaid (not plain mermaid) for professional, themed SVG output.
Why beautiful-mermaid?
- 15 built-in themes (tokyo-night, nord, dracula, github-light, etc.)
- Simple two-color theming system
- Clean SVG output
- Works in browser via CDN
Setup (CDN - Recommended for Nuxt/Vue)
Dynamic imports don't work reliably client-side. Use the CDN approach:
// In your component's script setup
useHead({
script: [
{
src: 'https://unpkg.com/beautiful-mermaid/dist/beautiful-mermaid.browser.global.js',
defer: true
}
]
})
Rendering Diagrams
// Define your diagrams
const diagrams = {
pipeline: `graph LR
A[Input] --> B[Process]
B --> C[Output]`,
// ... more diagrams
}
// Theme that matches your page design
const theme = {
bg: '#f8fafc', // Match page background
fg: '#1e293b', // Match text color
accent: '#3b82f6', // Your primary color
muted: '#64748b', // Secondary text
surface: '#e2e8f0', // Node fills
border: '#cbd5e1' // Node borders
}
onMounted(() => {
// Wait for CDN script to load
const checkAndRender = () => {
if (typeof window.beautifulMermaid !== 'undefined') {
const { renderMermaid } = window.beautifulMermaid
const renderDiagram = async (id, code) => {
try {
const svg = await renderMermaid(code, theme)
const el = document.getElementById(id)
if (el) el.innerHTML = svg
} catch (e) {
console.error(`Error rendering ${id}:`, e)
}
}
// Render all diagrams
renderDiagram('diagram-pipeline', diagrams.pipeline)
// ... render others
} else {
setTimeout(checkAndRender, 100) // Retry until loaded
}
}
checkAndRender()
})
HTML Structure
<div class="not-prose my-10">
<div id="diagram-pipeline"
class="diagram-container bg-slate-50 rounded-2xl p-8 border border-slate-200 flex justify-center min-h-[200px]">
</div>
<p class="text-center text-sm text-slate-500 mt-3">
Fig 1: Description of diagram
</p>
</div>
Critical: Match Theme to Page Design!
Don't use dark themes on light pages. Create a custom theme that matches:
| Page Style | Theme Colors |
|---|---|
| Light page | bg: '#f8fafc', fg: '#1e293b' |
| Dark page | bg: '#1a1b26', fg: '#a9b1d6' |
Or use built-in themes:
import { THEMES } from 'beautiful-mermaid'
const theme = THEMES['github-light'] // For light pages
const theme = THEMES['tokyo-night'] // For dark pages
### Supported Diagram Types
| Type | Use Case | beautiful-mermaid Support |
|------|----------|---------------------------|
| `graph LR/TB` | Pipeline flows, architecture | ✅ Full |
| `sequenceDiagram` | Interactions, API flows | ✅ Full |
| `stateDiagram-v2` | State machines, lifecycle | ✅ Full |
| `classDiagram` | Object relationships | ✅ Full |
| `erDiagram` | Entity relationships | ✅ Full |
| `mindmap` | Concept hierarchies | ⚠️ Use `graph TD` as fallback |
### Diagram Syntax Tips
**Keep it simple.** Complex syntax causes errors. Avoid:
- Emoji in node labels (use plain text)
- Special characters in subgraph names
- Overly nested structures
**Good:**
graph LR A[User Message] --> B[Context Window] B --> C[Daily Notes]
**Problematic:**
graph LR subgraph Input["💬 Input"] A[User Action] end
### Flowchart for Pipelines
```javascript
const pipeline = `graph LR
A[Input] --> B[Process]
B --> C[Transform]
C --> D[Output]`
Sequence Diagram for Interactions
const sequence = `sequenceDiagram
User->>App: Request
App->>Server: API call
Server-->>App: Response
App->>User: Display`
State Diagram for Lifecycles
const state = `stateDiagram-v2
[*] --> Idle
Idle --> Active
Active --> Complete
Complete --> [*]`
Figure Captions (Substantial!)
Captions must be self-explanatory. A reader should understand the diagram from the caption alone, without needing to read the surrounding text. This is academic-style figure captioning.
Bad: Fig 1: The pipeline
Good: Fig 1. User messages enter the volatile context window, then get written to persistent daily notes and long-term memory files. Semantic search retrieves relevant context back into the window for future sessions.
<div class="not-prose my-6">
<div id="diagram-name"
class="bg-white rounded border border-slate-200 p-4 min-h-[100px]">
</div>
<p class="text-center text-sm text-slate-600 mt-3 max-w-md mx-auto">
<strong>Fig 1.</strong> Complete sentence explaining what this diagram shows,
including the key relationships and flow. The caption should communicate
the figure's meaning to someone who hasn't read the section text.
</p>
</div>
Caption formula:
- Start with
<strong>Fig N.</strong> - Describe what the diagram depicts (nouns)
- Explain the relationships/flow (verbs)
- Include key insight if space allows
Common Gotchas
- CDN script must load before rendering — use the polling pattern shown above
- Theme must match page — dark themes on light pages look terrible
- NO HTML in labels —
<br>,<small>will render as literal text. Use simple labels only. - Use
not-proseclass — prevents Tailwind Typography from breaking diagram styles - Avoid dynamic imports — they don't work reliably in browser; use CDN
- Test iteratively with browser — use the browser tool to see actual rendering
- Reduce padding —
p-4notp-10; fat padding draws focus away from diagram - Scale SVGs properly — add CSS for
width: 100%and appropriatemin-height
CSS for Proper Scaling
/* Make diagrams fill container */
#diagram-pipeline :deep(svg) {
width: 100%;
height: auto;
min-height: 80px;
}
#diagram-arch :deep(svg) {
width: 100%;
height: auto;
min-height: 280px;
}
Monochrome Diagrams (Default)
Keep diagrams black and white. Let shapes communicate meaning:
graph LR
A([Input]) --> B[Process]
B --> C[(Storage)]
C --> D{{Tool}}
Semantic shapes (no color needed):
([text])Stadium — terminals, start/end points[text]Rectangle — processes, steps[(text)]Cylinder — storage, databases{{text}}Hexagon — tools, utilities>text]Asymmetric — documents, outputs
Color-Coded Nodes (Use Sparingly)
Only add color when it communicates specific meaning (e.g., error states, before/after comparison):
graph LR
A[Normal]:::default --> B[Warning]:::warn --> C[Error]:::error
classDef default fill:#f8fafc,stroke:#1e293b,color:#1e293b
classDef warn fill:#fef3c7,stroke:#92400e,color:#92400e
classDef error fill:#fee2e2,stroke:#991b1b,color:#991b1b
Writing Each Section
Opening Paragraph Formula
Every section needs a compelling opener that:
- States what this component IS
- Explains WHY it exists
- Hints at what you'll learn
Template:
[COMPONENT] is [SIMPLE DEFINITION] — [FUNCTION/PURPOSE].
[WHY IT MATTERS or WHAT WOULD GO WRONG WITHOUT IT].
Example:
Every key on your keyboard sits atop a switch — a mechanism that converts
your physical press into an electrical signal. The type of switch determines
how your keyboard feels and sounds.
Subsection Formula
For each subsection:
- Hook line — What is this variant/aspect?
- How it works — Technical explanation
- Trade-offs — Pros/cons, when to use
- Example — Concrete instance
Technical Depth Ladder
Progress from accessible to advanced within each section:
- Level 1: Analogy/Overview — "Think of it like..."
- Level 2: How it works — The mechanism
- Level 3: Implementation details — Specifics, numbers, protocols
- Level 4: Edge cases — What can go wrong, advanced considerations
Quantify Where Possible
Numbers make explanations concrete:
- "bounces for 1-5 milliseconds"
- "6 bytes per report"
- "125Hz polling rate (8ms intervals)"
- "The entire journey typically takes 5-25 milliseconds"
Lists & Inline Elements
Prose isn't always the answer. Sometimes a list communicates faster — and sometimes inline styling makes the difference between scannable and sloggable.
Lists vs Prose: When to Use Which
Use bulleted lists when:
- Items are parallel (same structure, comparable weight)
- Readers need to scan quickly
- Each item is short (one line, maybe two)
- You're showing options, features, or trade-offs
Use prose when:
- You're building an argument or narrative
- Items need context to make sense together
- The explanation requires transitions between ideas
- One item naturally leads to the next
The 3-line rule: If each bullet would need 3+ lines of explanation, consider prose with bold lead-ins instead. Lists with fat bullets feel like failed paragraphs.
Bold Lead-In Pattern
The most useful list pattern for explainers. Each item starts with a bolded term or phrase, followed by an em-dash and the explanation:
- **Facts** — Concrete information about the user (location, job, preferences they've stated)
- **Preferences** — Things they like, dislike, or have strong opinions about
- **Context** — Situational awareness (current project, recent events, mood)
- **Patterns** — Behaviors you've noticed over time
This pattern works because:
- Scannable — Readers can skim bold terms to find what they need
- Self-labeling — Each item names itself before explaining
- Consistent — Parallel structure makes comparison easy
- Dense — Packs information tightly without walls of text
When to use: Feature lists, component breakdowns, trade-off comparisons, glossary-style definitions, configuration options.
Inline Code Styling
Use inline code for:
- File names and paths (
nuxt.config.ts,/content/guide/) - Commands and flags (
npm run dev,--host) - Variable names, function names, properties (
isRunning,onClick) - Specific values (
125Hz,8ms,#0ea5e9) - Technical terms on first use when precision matters
Tailwind Typography styles inline code with a subtle gray background (#f3f4f6), rounded corners, and slightly reduced font weight. This works well for most cases — no custom styling needed.
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 88
- Forks
- 17
- Last commit
- Jul 2026
Advanced
- Catalog kind
- skill
- Gateway key
explainer-site- Source
- github.com/drpedapati/sciclaw