sk-doc-visual — Styled HTML Diagram Generator
Converts complex terminal output and technical concepts into styled, self-contained HTML pages with diagrams, tables, and visualizations. Uses a 4-phase Think > Structure > Style > Deliver workflow with strict validation and deterministic library pinning.
<!-- ANCHOR:when-to-use -->
1. WHEN TO USE
Activation Commands
| Command | Purpose | Example Trigger |
|---------|---------|----------------|
| /create:visual_html --mode generate | Generate a visual diagram or styled page from any topic | "generate an architecture diagram for this service" |
| /create:visual_html --mode diff-review | Visual review of git diffs, PRs, or commit ranges | "visual diff review of this PR" |
| /create:visual_html --mode plan-review | Visual analysis of any planning or SpecKit artifact document | "visually review specs/007-auth/plan.md" |
| /create:visual_html --mode recap | Visual recap of recent work or progress | "generate a visual recap of the last 2 weeks" |
| /create:visual_html --mode fact-check | Verify accuracy of an existing HTML output | "fact-check this visual output against the spec" |
Keyword Triggers (Auto-Activate)
Activate this skill when the user's message contains: visual, diagram, HTML page, generate HTML, flowchart, architecture diagram, mermaid, chart, sequence diagram, timeline, dashboard, render, visualization, styled page, table render, data table, speckit, traceability, spec.md, plan.md, tasks.md, checklist.md, implementation-summary.md, research.md, decision-record.md, README, install guide.
Proactive Trigger
Auto-render a styled HTML table when responding with data that has:
- 4 or more rows, OR
- 3 or more columns
Announce: "I'm rendering this as a styled HTML page for readability."
When NOT to Use
- Plain text is sufficient (< 4-row tables, simple lists, short explanations)
- Output must be a React, Vue, or Svelte component
- Server-side rendering required (live data, authentication, database queries)
- User explicitly requests plain Markdown output
<!-- ANCHOR:smart-routing -->
2. SMART ROUTING
Resource Domains
The router discovers markdown resources recursively from references/ and assets/ and then applies intent scoring from RESOURCE_MAP.
references/for generation patterns, CSS/layout standards, library guidance, navigation, quality checks, and SpecKit artifact profiles.assets/templates/for reusable HTML starter templates.assets/library_versions.jsonas machine-readable version source-of-truth (used by drift checks, not markdown routing).scripts/for validation and drift enforcement scripts.
Resource Loading Levels
| Level | When to Load | Resources | | ----------- | ------------------------ | ----------------------------------------- | | ALWAYS | Every skill invocation | Quick reference baseline | | CONDITIONAL | If intent signals match | CSS/library/checklist + SpecKit profile references | | ON_DEMAND | Only on explicit request | Navigation patterns and template deep-dive |
Smart Router Pseudocode
The authoritative routing logic for scoped loading, weighted intent scoring, ambiguity handling, and unknown fallback guidance.
from pathlib import Path
SKILL_ROOT = Path(__file__).resolve().parent
REFERENCE_BASE = SKILL_ROOT / "references"
TEMPLATE_BASE = SKILL_ROOT / "assets" / "templates"
DEFAULT_RESOURCE = "references/quick_reference.md"
INTENT_SIGNALS = {
"GENERATE": {"weight": 4, "keywords": ["generate", "diagram", "visual", "architecture", "flowchart", "mermaid", "chart", "table", "timeline", "dashboard"]},
"DIFF_REVIEW": {"weight": 4, "keywords": ["diff", "review diff", "pr review", "commit", "changes"]},
"PLAN_REVIEW": {"weight": 4, "keywords": ["plan review", "plan analysis", "analyze plan"]},
"RECAP": {"weight": 4, "keywords": ["recap", "summary", "progress", "what happened"]},
"FACT_CHECK": {"weight": 4, "keywords": ["fact check", "verify", "accuracy", "correctness"]},
"SPECKIT_ARTIFACT_REVIEW": {"weight": 5, "keywords": ["speckit", "spec.md", "plan.md", "tasks.md", "checklist.md", "implementation-summary.md", "research.md", "decision-record.md", "artifact profile"]},
"SPECKIT_TRACEABILITY": {"weight": 5, "keywords": ["traceability", "cross-reference", "cross doc", "--traceability", "doc graph", "matrix"]},
"USER_GUIDE_REVIEW": {"weight": 4, "keywords": ["readme", "install guide", "installation guide", "user guide", "getting started"]},
"AESTHETIC": {"weight": 3, "keywords": ["style", "aesthetic", "theme", "visual direction"]},
"DIAGRAM_TYPE": {"weight": 3, "keywords": ["diagram type", "which diagram", "state machine", "mind map", "er diagram"]},
}
COMMAND_BOOSTS = {
"/create:visual_html --mode generate": "GENERATE",
"/create:visual_html --mode diff-review": "DIFF_REVIEW",
"/create:visual_html --mode plan-review": "PLAN_REVIEW",
"/create:visual_html --mode recap": "RECAP",
"/create:visual_html --mode fact-check": "FACT_CHECK",
"/create:visual_html": "GENERATE",
}
RESOURCE_MAP = {
"GENERATE": ["references/css_patterns.md", "references/library_guide.md"],
"DIFF_REVIEW": ["references/css_patterns.md", "references/library_guide.md"],
"PLAN_REVIEW": ["references/css_patterns.md", "references/quality_checklist.md"],
"RECAP": ["references/css_patterns.md", "references/navigation_patterns.md"],
"FACT_CHECK": ["references/quality_checklist.md"],
"SPECKIT_ARTIFACT_REVIEW": ["references/artifact_profiles.md", "references/quality_checklist.md"],
"SPECKIT_TRACEABILITY": ["references/artifact_profiles.md", "references/navigation_patterns.md", "references/library_guide.md"],
"USER_GUIDE_REVIEW": ["references/user_guide_profiles.md", "references/quality_checklist.md", "references/css_patterns.md"],
"AESTHETIC": ["references/css_patterns.md"],
"DIAGRAM_TYPE": ["references/library_guide.md"],
}
LOADING_LEVELS = {
"ALWAYS": [DEFAULT_RESOURCE],
"ON_DEMAND_KEYWORDS": ["full checklist", "full template", "deep dive", "navigation pattern", "traceability template", "artifact dashboard"],
"ON_DEMAND": [
"references/navigation_patterns.md",
"assets/templates/architecture.html",
"assets/templates/mermaid-flowchart.html",
"assets/templates/data-table.html",
"assets/templates/artifact-dashboard.html",
"assets/templates/traceability-board.html",
"assets/templates/readme-guide.html",
"assets/templates/implementation-summary.html",
],
}
UNKNOWN_FALLBACK_CHECKLIST = [
"Confirm desired visual artifact type (architecture, flowchart, data table, dashboard, timeline)",
"Confirm document artifact type (spec, plan, tasks, checklist, implementation-summary, research, decision-record, readme, install-guide)",
"Confirm view mode (artifact-dashboard vs traceability-board)",
"Confirm audience (developer, reviewer, stakeholder)",
"Provide the source of truth (spec, diff, notes, dataset)",
"Confirm delivery constraints (single-page vs split pages, static HTML only)",
]
def _task_text(task) -> str:
parts = [
str(getattr(task, "text", "")),
str(getattr(task, "query", "")),
str(getattr(task, "description", "")),
" ".join(getattr(task, "keywords", []) or []),
str(getattr(task, "command", "")),
]
return " ".join(parts).lower()
def _guard_in_skill(relative_path: str) -> str:
resolved = (SKILL_ROOT / relative_path).resolve()
resolved.relative_to(SKILL_ROOT)
if resolved.suffix.lower() not in {".md", ".html"}:
raise ValueError(f"Only markdown or html resources are routable: {relative_path}")
return resolved.relative_to(SKILL_ROOT).as_posix()
def discover_routable_resources() -> set[str]:
docs = []
if REFERENCE_BASE.exists():
docs.extend(path for path in REFERENCE_BASE.rglob("*.md") if path.is_file())
if TEMPLATE_BASE.exists():
docs.extend(path for path in TEMPLATE_BASE.rglob("*.html") if path.is_file())
return {doc.relative_to(SKILL_ROOT).as_posix() for doc in docs}
def score_intents(task) -> dict[str, float]:
text = _task_text(task)
scores = {intent: 0.0 for intent in INTENT_SIGNALS}
for intent, cfg in INTENT_SIGNALS.items():
for keyword in cfg["keywords"]:
if keyword in text:
scores[intent] += cfg["weight"]
command = str(getattr(task, "command", "")).lower()
for prefix, intent in COMMAND_BOOSTS.items():
if command.startswith(prefix):
scores[intent] += 6
if getattr(task, "has_tabular_data", False):
scores["GENERATE"] += 2
return scores
def select_intents(scores: dict[str, float], task_text: str, ambiguity_delta: float = 1.0, base_max_intents: int = 2, adaptive_max_intents: int = 3) -> list[str]:
ranked = sorted(scores.items(), key=lambda item: item[1], reverse=True)
if not ranked or ranked[0][1] <= 0:
return ["GENERATE"]
noisy_hits = sum(1 for term in ["visual", "diagram", "plan", "review", "fact check", "traceability", "speckit"] if term in task_text)
max_intents = adaptive_max_intents if noisy_hits >= 3 else base_max_intents
selected = [ranked[0][0]]
for intent, score in ranked[1:]:
if score <= 0:
continue
if (ranked[0][1] - score) <= ambiguity_delta:
selected.append(intent)
if len(selected) >= max_intents:
break
return selected[:max_intents]
def route_visual_explainer_resources(task):
inventory = discover_routable_resources()
task_text = _task_text(task)
scores = score_intents(task)
intents = select_intents(scores, task_text, ambiguity_delta=1.0)
loaded = []
seen = set()
def load_if_available(relative_path: str) -> None:
guarded = _guard_in_skill(relative_path)
if guarded in inventory and guarded not in seen:
load(guarded)
loaded.append(guarded)
seen.add(guarded)
for relative_path in LOADING_LEVELS["ALWAYS"]:
load_if_available(relative_path)
if sum(scores.values()) < 0.5:
load_if_available("references/library_guide.md")
return {
"intents": ["GENERATE"],
"intent_scores": scores,
"load_level": "UNKNOWN_FALLBACK",
"needs_disambiguation": True,
"disambiguation_checklist": UNKNOWN_FALLBACK_CHECKLIST,
"resources": loaded,
}
for intent in intents:
for relative_path in RESOURCE_MAP.get(intent, []):
load_if_available(relative_path)
if any(keyword in task_text for keyword in LOADING_LEVELS["ON_DEMAND_KEYWORDS"]):
for relative_path in LOADING_LEVELS["ON_DEMAND"]:
load_if_available(relative_path)
if not loaded:
load_if_available(DEFAULT_RESOURCE)
return {"intents": intents, "intent_scores": scores, "resources": loaded}
<!-- /ANCHOR:smart-routing -->
<!-- ANCHOR:how-it-works -->
3. HOW IT WORKS
The skill executes a strict 4-phase workflow. Do not skip phases.
Phase 1 — Think
- Analyze audience: developer, stakeholder, or technical reviewer.
- Identify artifact type: architecture, flowchart, table, dashboard, timeline.
- If input is doc-driven, map to artifact profile (
spec,plan,tasks,checklist,implementation-summary,research,decision-record,readme,install-guide). - If confidence on diagram type is <80%, present 2-3 options and ask.
Phase 2 — Structure
- Read templates from
assets/templates/before composing output. - Prefer template adaptation over blank-page HTML.
- Select rendering approach: Mermaid | Chart.js | semantic table | CSS grid/timeline.
- Select view mode:
artifact-dashboard(default) ortraceability-board(--traceability). - Build semantic layout with landmarks (
header,main,section,figure,figcaption).
Phase 3 — Style
- Use README Ledger tokens (
--bg,--surface,--text,--accent,--muted,--border) as default. - Keep
--ve-*aliases only as compatibility shims for legacy snippets. - Typography default for README Ledger is
Inter+JetBrains Mono. - Outside README Ledger profile, do not use Inter/Roboto/Arial as primary display/body fonts.
- Keep CSS-first motion with reduced-motion fallback.
- Provide both light and dark themes.
- Include contrast and forced-color resilience (
prefers-contrast,forced-colors).
README Ledger Profile (Default)
- Required primitives: terminal header, active-dot TOC, glass card, ledger divider, flow-step, viz bar/fill, scanline.
- Layout shell: desktop
260pxsidebar + content; hide sidebar on mobile (<1024px). - JS bootstrap: initialize on
DOMContentLoaded; include reveal observer + nav observer; add viz-fill observer when bars are present.
Phase 4 — Deliver
- Save output to
.opencode/output/visual/{command}-{description}-{timestamp}.html. - Run
scripts/validate-html-output.shand fix all errors. - For library updates, run
scripts/check-version-drift.sh. - Report artifact path, file size, and validator status.
<!-- ANCHOR:rules -->
4. RULES
✅ ALWAYS
- Self-contained HTML with inline CSS/JS or pinned CDN dependencies.
- README Ledger token contract (
--bg,--surface,--text,--accent,--muted,--border) or--ve-*compatibility aliases. prefers-reduced-motionmedia query for all animation paths.prefers-color-schemesupport and<meta name="color-scheme" content="light dark">.- Contrast-aware behavior via
prefers-contrastandforced-colorsfallback blocks. - Mermaid
theme: 'base'with explicitthemeVariables. - Mermaid hardened defaults when Mermaid is used:
securityLevel: 'strict',deterministicIds: true, boundedmaxTextSize, boundedmaxEdges. - Google Fonts with
display=swapwhen web fonts are used. - Mermaid zoom controls (+/-/reset, Ctrl+scroll, drag-to-pan) on every
.mermaid-wrap. - For SpecKit-aligned outputs, include metadata tags:
ve-artifact-type,ve-source-doc,ve-speckit-level,ve-view-mode.
❌ NEVER
- Build-step frameworks (React, Vue, Svelte) for generated output.
- Hardcoded local absolute paths in output HTML.
- Roboto or Arial as primary display/body font variables.
- Inter as primary display/body font variables outside README Ledger profile.
color:in MermaidclassDefdeclarations.- Opaque light fills in Mermaid
classDefwhere alpha transparency is required. - Background polling loops (
fetch, storage watchers, hidden timers) in static outputs. - Any
setIntervalusage except a visible#clockUTC updater at 1-second cadence.
⚠️ ESCALATE IF
- Content exceeds single-page capacity (> 15 sections).
- User requires runtime server-side data fetch.
- Requested artifact must be framework-native component output.
- Diagram type confidence remains <80% after clarification.
5. RELATED RESOURCES
references/artifact_profiles.mdfor artifact detector precedence and profile rules.references/user_guide_profiles.mdfor README/install-guide mapping.assets/templates/artifact-dashboard.htmlfor artifact dashboard output mode.assets/templates/traceability-board.htmlfor traceability board output mode.assets/templates/readme-guide.htmlfor interactive README-style artifact rendering.assets/templates/implementation-summary.htmlfor implementation-summary artifact rendering with side TOC.scripts/validate-html-output.shfor contract enforcement and final delivery checks.
<!-- ANCHOR:references -->
6. REFERENCES
Internal References
- quick_reference.md
- css_patterns.md
- library_guide.md
- navigation_patterns.md
- quality_checklist.md
- artifact_profiles.md
- user_guide_profiles.md
- library_versions.json
Template Assets
- architecture.html
- mermaid-flowchart.html
- data-table.html
- artifact-dashboard.html
- traceability-board.html
- readme-guide.html
- implementation-summary.html
Enforcement Scripts
scripts/validate-html-output.shscripts/check-version-drift.sh
<!-- ANCHOR:success-criteria -->
7. SUCCESS CRITERIA
- Squint test: hierarchy is clear under blur.
- Swap test: style is content-specific, not generic.
- Light/dark both appear intentional.
- Information completeness: source content is represented accurately.
- No overflow across 320px-2560px.
- Mermaid zoom controls work on every Mermaid artifact.
- File opens cleanly on
file://with no console errors. - Accessibility baseline is met (contrast, non-color-only signals, control labels).
- Reduced-motion mode is fully usable.
meta[name="color-scheme"]is present.- Mermaid hardened config signals are present when Mermaid is used.
- Version drift check passes against
assets/library_versions.json. - SpecKit outputs include all four metadata contract tags.
- Traceability-board outputs include graph and cross-reference matrix sections.
<!-- ANCHOR:integration-points -->
8. INTEGRATION POINTS
Canonical Library Versions
| Library | Version | Use Case |
|---------|---------|---------|
| Mermaid.js | 11.12.3 (ESM) | Flowcharts, sequences, ER, state, mindmap |
| Chart.js | 4.5.1 | Dashboards, metrics, bar/line/pie |
| anime.js | 4.3.6 (optional) | Advanced stagger/shape animation |
| Google Fonts | pinned families + display=swap | Typography |
Output Convention
.opencode/output/visual/{command}-{description}-{timestamp}.html
Cross-Skill Integration
| Skill | When to Call |
|-------|-------------|
| system-spec-kit memory | /create:visual_html --mode recap and --mode plan-review context retrieval |
| sk-git | /create:visual_html --mode diff-review evidence gathering |
| mcp-chrome-devtools | post-delivery console/layout verification |
Resource Loading Contract
| Resource | Loading |
|----------|---------|
| references/quick_reference.md | ALWAYS |
| references/css_patterns.md | CONDITIONAL |
| references/library_guide.md | CONDITIONAL |
| references/quality_checklist.md | CONDITIONAL |
| references/artifact_profiles.md | CONDITIONAL |
| references/user_guide_profiles.md | CONDITIONAL |
| references/navigation_patterns.md | ON_DEMAND |
| assets/templates/*.html | ON_DEMAND |