diagram-scaffolder
Generate new interactive diagram components for tutorial content. Use when adding a visual diagram, creating architectural illustrations, or building interactive flow visualizations. Use for questions like "add a diagram", "create diagram component", "new visual for module X". Produces a React component, registers it in the barrel export and StepCard parser, and provides the markdown reference syntax.
- License 许可
- MIT
- 最近更新
- 2026-10-22
- Stars
- ★ 21
- Forks
- 6
01 前言 Front Matter
- name
- diagram-scaffolder
- description
- Generate new interactive diagram components for tutorial content. Use when adding a visual diagram, creating architectural illustrations, or building interactive flow visualizations. Use for questions like "add a diagram", "create diagram component", "new visual for module X". Produces a React component, registers it in the barrel export and StepCard parser, and provides the markdown reference syntax.
02 资源文件 2
- 脚本scripts/anisotropy_check.py7.4 KB
- 脚本scripts/example_scifact_halves.py2.4 KB
03 SKILL.md 正文
Diagram Scaffolder
This skill generates interactive diagram components that integrate with the tutorial's custom markdown rendering pipeline.
When to Use This Skill
- When adding a new visual diagram to any tutorial content
- When creating architectural illustrations (e.g., system diagrams, flow charts)
- When building interactive visualizations with clickable phases or nodes
- When a
:::diagram <name>block needs a backing React component
Architecture Overview
Adding a diagram requires coordinated changes across 4 files:
1. src/components/diagrams/NewDiagram.tsx ← React component
2. src/components/diagrams/index.ts ← Barrel export
3. src/components/StepCard.tsx ← Parser case + import
4. src/content/**/module-*.md ← Markdown reference
Data Flow
Markdown: :::diagram my-diagram :::
→ StepCard parseContentBlocks() → { type: 'diagram', diagramName: 'my-diagram' }
→ renderBlock() switch case → <MyDiagram />
Existing Diagrams Registry
| Markdown Name | Component | Used In |
|---|---|---|
file-hierarchy |
FileHierarchyDiagram |
Part 3 (Foundation) |
mcp-architecture |
MCPArchitectureDiagram |
Module A (Advanced) |
workflow-comparison |
WorkflowComparisonDiagram |
Module B (Advanced) |
agent-orchestration |
AgentOrchestrationDiagram |
Module C (Advanced) |
ai-testing-flow |
AITestingFlowDiagram |
Module D (Advanced) |
capstone-architecture |
CapstoneArchitectureDiagram |
Module E (Advanced) |
agentic-loop |
AgenticLoopDiagram |
Module G (Terminal) |
provider-abstraction |
ProviderAbstractionDiagram |
Module G (Terminal) |
skill-system-flow |
SkillSystemFlowDiagram |
Module G (Terminal) |
spec-driven-cycle |
SpecDrivenCycleDiagram |
Module G (Terminal) |
Naming Conventions
| Aspect | Convention | Example |
|---|---|---|
| Markdown name | kebab-case |
data-flow-pipeline |
| Component name | PascalCase + Diagram suffix |
DataFlowPipelineDiagram |
| File name | Same as component | DataFlowPipelineDiagram.tsx |
The markdown name and component name must be related by converting kebab-case to PascalCase and appending Diagram.
Component Template
Basic Static Diagram
import { cn } from '@/lib/utils'
import { Card } from '@/components/ui/card'
import { Info } from '@phosphor-icons/react'
interface DiagramNameDiagramProps {
className?: string
}
export function DiagramNameDiagram({ className }: DiagramNameDiagramProps) {
return (
<div
className={cn('my-6 space-y-4', className)}
role="figure"
data-diagram="diagram-name"
aria-label="Description of what this diagram shows."
>
<Card className="p-6 bg-muted/30 border-border">
<div className="flex items-center gap-2 mb-4 pb-3 border-b border-border">
{/* Icon + Title */}
<span className="font-heading font-semibold text-sm text-foreground">
Diagram Title
</span>
</div>
{/* Diagram content */}
<div className="font-mono text-sm">
{/* Visual elements go here */}
</div>
</Card>
{/* Key insight callout */}
<div className="flex items-center gap-3 p-4 rounded-lg bg-primary/5 border border-primary/20">
<Info size={20} className="text-primary shrink-0" />
<p className="text-sm text-foreground">
<strong>Key insight.</strong> Brief explanation of what makes this important.
</p>
</div>
</div>
)
}
Interactive Diagram (with clickable phases)
import { useState } from 'react'
import { Card } from '@/components/ui/card'
import { Info } from '@phosphor-icons/react'
type PhaseId = 'phase-a' | 'phase-b' | 'phase-c'
interface PhaseInfo {
id: PhaseId
label: string
icon: React.ReactNode
color: string
bgColor: string
description: string
}
const phases: PhaseInfo[] = [
{
id: 'phase-a',
label: 'Phase A',
icon: <span>?</span>,
color: 'text-blue-500',
bgColor: 'bg-blue-500/10 border-blue-500/30',
description: 'Explanation of this phase.'
},
// ... more phases
]
export function DiagramNameDiagram() {
const [activePhase, setActivePhase] = useState<PhaseId>('phase-a')
const selected = phases.find(p => p.id === activePhase) || phases[0]
return (
<div
className="my-6 space-y-4"
role="figure"
data-diagram="diagram-name"
aria-label="Description. Click each phase to learn more."
>
{/* Phase nodes */}
<Card className="p-6 bg-muted/30 border-border">
<div className="flex items-center gap-2 mb-4 pb-3 border-b border-border">
<span className="font-heading font-semibold text-sm text-foreground">
Diagram Title
</span>
<span className="ml-auto text-xs text-muted-foreground">
Click a phase to explore
</span>
</div>
<div className="flex items-center justify-center gap-2 py-4 overflow-x-auto">
{phases.map(phase => (
<button
key={phase.id}
onClick={() => setActivePhase(phase.id)}
className={`flex flex-col items-center gap-1.5 p-3 rounded-xl border-2 transition-all duration-200 min-w-[80px]
${activePhase === phase.id
? `${phase.bgColor} border-opacity-100 scale-105 shadow-lg`
: 'bg-muted/30 border-border hover:border-muted-foreground/50'
}`}
>
<div className={`p-2 rounded-lg ${phase.bgColor} ${phase.color}`}>
{phase.icon}
</div>
<div className="font-semibold text-xs text-foreground">{phase.label}</div>
</button>
))}
</div>
</Card>
{/* Phase detail */}
<Card className="p-4 bg-muted/30 border-border">
<div className="flex items-start gap-3">
<div className={`p-2 rounded-lg ${selected.bgColor} ${selected.color} shrink-0`}>
{selected.icon}
</div>
<div>
<h4 className="font-semibold text-foreground">{selected.label}</h4>
<p className="text-sm text-muted-foreground mt-1 leading-relaxed">
{selected.description}
</p>
</div>
</div>
</Card>
{/* Key insight */}
<div className="flex items-center gap-3 p-4 rounded-lg bg-primary/5 border border-primary/20">
<Info size={20} className="text-primary shrink-0" />
<p className="text-sm text-foreground">
<strong>Key insight.</strong> Explanation.
</p>
</div>
</div>
)
}
Design Patterns
Color System
Use Tailwind's color utility classes with opacity modifiers:
Phase backgrounds: bg-{color}-500/10
Phase borders: border-{color}-500/30
Phase text: text-{color}-500
Standard phase colors across diagrams:
- Blue (
blue-500) — input, start, user action - Violet (
violet-500) — thinking, reasoning, AI processing - Amber (
amber-500) — decision points, warnings - Emerald (
emerald-500) — execution, success, output - Cyan (
cyan-500) — data flow, feedback - Rose (
rose-500) — stop, error, terminal state
Icons
Use Phosphor Icons (@phosphor-icons/react) with weight="duotone" and size={22} for phase nodes:
import { Brain, Code, Eye, Wrench, Lightning } from '@phosphor-icons/react'
Accessibility
Every diagram must have:
role="figure"on the root elementdata-diagram="kebab-name"for testingaria-labeldescribing what the diagram shows- Keyboard-accessible interactive elements (use
<button>, not<div onClick>)
Responsive Design
- Use
overflow-x-autoon horizontal flow layouts - Use
flex-wrapor stack vertically on mobile for dense diagrams min-w-[80px]on phase nodes to prevent squishing
Step-by-Step: Adding a New Diagram
Step 1: Create the component
Create src/components/diagrams/YourDiagram.tsx using one of the templates above.
Step 2: Export from barrel file
Add to src/components/diagrams/index.ts:
export { YourDiagram } from './YourDiagram'
Step 3: Register in StepCard.tsx
3a. Add import at top of src/components/StepCard.tsx:
import {
FileHierarchyDiagram,
// ... existing imports ...
YourDiagram
} from './diagrams'
3b. Add case in the renderBlock function's case 'diagram': switch:
case 'diagram':
switch (block.diagramName) {
// ... existing cases ...
case 'your-diagram':
return <YourDiagram key={idx} />
default:
return null
}
Step 4: Reference in markdown
In the tutorial/advanced/terminal content file:
:::diagram your-diagram
:::
Validation
PowerShell: Verify all diagrams are connected
# Find all :::diagram references in content
$diagramRefs = Select-String -Path "src/content/**/*.md" -Pattern "^:::diagram\s+(\S+)" -AllMatches |
ForEach-Object { $_.Matches.Groups[1].Value } | Sort-Object -Unique
# Find all registered cases in StepCard
$stepCard = Get-Content "src/components/StepCard.tsx" -Raw
$registeredCases = [regex]::Matches($stepCard, "case '([^']+)':") |
ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique
# Find all exports in index.ts
$indexExports = Select-String -Path "src/components/diagrams/index.ts" -Pattern "export \{ (\w+) \}" |
ForEach-Object { $_.Matches.Groups[1].Value }
Write-Host "`n=== DIAGRAM AUDIT ===" -ForegroundColor Cyan
Write-Host "`nMarkdown references:" -ForegroundColor Yellow
$diagramRefs | ForEach-Object {
$inSwitch = $registeredCases -contains $_
$status = if ($inSwitch) { "OK" } else { "MISSING CASE" }
$color = if ($inSwitch) { "Green" } else { "Red" }
Write-Host " :::diagram $_ — $status" -ForegroundColor $color
}
Write-Host "`nExported components:" -ForegroundColor Yellow
$indexExports | ForEach-Object { Write-Host " $_" }
Write-Host "`n=== END AUDIT ===" -ForegroundColor Cyan
Build Check
npm run build
A missing import or unregistered diagram will cause a build error or silently render nothing (default: return null). Always verify the diagram renders in the browser after adding it.
Checklist
Before completing a new diagram:
- [ ] Component file created in
src/components/diagrams/ - [ ] Named export (not default export)
- [ ] Exported from
src/components/diagrams/index.ts - [ ] Imported in
src/components/StepCard.tsx - [ ] Switch case added in
renderBlock→case 'diagram': - [ ]
role="figure",data-diagram, andaria-labelpresent - [ ] Interactive elements use
<button>for keyboard access - [ ] Horizontal layouts have
overflow-x-auto - [ ] Renders correctly in both light and dark themes
- [ ] Referenced in markdown with
:::diagram name/::: - [ ]
npm run buildsucceeds
04 同仓库更多 Skills
version-checker
Validate that tutorial content references current tool versions, APIs, CLI commands, and features. Use when reviewing content for outdated information, checking deprecations, verifying feature availability, auditing tool references, or updating stale version numbers. Covers GitHub Copilot (VS Code + CLI), Claude Code, VS Code settings, MCP, and Agent Skills standard.
tutorial-content-qa
Comprehensive quality assurance for AI-Native development tutorials across all tracks (Foundation, Advanced, Terminal). Use when reviewing content for accuracy, clarity, consistency, and completeness. Use for proofreading, checking errors, auditing content, or running QA checks before publishing.
track-generator
Generate new example tracks for the AI-Native tutorial. Use when creating new industry examples, adding a new track, building project templates, or expanding learning paths. Use for questions like "add a track for healthcare", "create new example", "new industry template". Produces consistent ExampleTrack data with all required fields including projectName, requirements, colorCoding, taskExamples, and verification examples matching the TypeScript interface in exampleTracks.ts.
exercise-scaffolder
Generate consistent, high-quality coding exercises for AI-Native development tutorials. Use when creating hands-on exercises, coding challenges, practice problems, quizzes, labs, or skill-building activities. Use for questions like "create an exercise", "add practice activity", "build a challenge for Part X". Includes starter templates, solution patterns, hint progressions, and verification criteria.
docs-sync
Diff src/ and .github/ against docs/ to detect drift between code and design spec. Use when auditing the docs folder, after merging structural changes (adding paths/modules/diagrams/syntax/agents/skills/hooks), or before a release. Use for questions like "is docs in sync?", "what changed since the last docs update?", "find docs drift". Produces a structured report with proposed edits — does not modify docs/ directly.
content-track-scaffolder
Scaffold a complete new content track (like Foundation, Advanced, or Terminal) with all required files — data parser, page components, routes, markdown content, and navigation. Use when adding a new learning path, creating a new track, or expanding the tutorial with a new module series. Use for questions like "add a new track", "create learning path for X", "scaffold track pages".