skills/generate-html-artifact/SKILL.md
Generate a single-file HTML artefact from the current response (or a specific piece of content under discussion) instead of a long Markdown reply. Use whenever the user asks for a "human-readable version", "an artifact", "a shareable page", "an HTML version", "make it pretty", "save that as a page", or similar phrasing. Auto-detects an llm-wiki vault or any repo/folder and writes to `<root>/artifacts/html/<timestamp>-<slug>.html`. Editorial typography baseline with libraries layered in per the decision tree; opens in the user's default browser. Markdown stays the default chat surface; this skill is the explicit promote-to-artefact step.
npx skillsauth add RonanCodes/ronan-skills generate-html-artifactInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The artefact will always be opened online. Size does not matter. The question to ask before reaching for any library is: does it save real work or does it just add weight without changing the outcome? If it saves real work (diagrams, charts, accessibility-correct components, icons), pull it. Do not optimise for offline-ness or for shaving bytes; optimise for the artefact being good.
The voice lives in the typography and the rhythm. Handcraft those. Libraries handle the visual primitives and the interactive bits where rolling your own would be reinventing wheels.
Snapshot the current response (or a specific piece of content) as a single-file HTML artefact. Markdown stays the chat default. This skill is the explicit "promote this moment to a real artefact" step.
Fire automatically on intent phrases like:
/generate-html-artifact (or whatever alias the user types)Do NOT fire for short factual replies, code-only edits, or one-line answers. The smell test: would the user open this in a browser tab and read it side-by-side with something else? If yes, fire. If no, leave it in the terminal.
The content under discussion. In order of preference:
When ambiguous, ask one clarifying question. Don't guess wrong and waste a render.
Auto-detect, in this order:
vaults/llm-wiki-*/). Root = the vault directory. The skill writes to <vault-root>/artifacts/html/.git rev-parse --show-toplevel. Writes to <repo-root>/artifacts/html/.<cwd>/artifacts/html/.# Detect root
if pwd | grep -q "/vaults/llm-wiki-"; then
ROOT="$(pwd | sed -E 's|(.*/vaults/llm-wiki-[^/]+).*|\1|')"
elif git rev-parse --show-toplevel >/dev/null 2>&1; then
ROOT="$(git rev-parse --show-toplevel)"
else
ROOT="$(pwd)"
fi
OUT_DIR="$ROOT/artifacts/html"
mkdir -p "$OUT_DIR"
Report the chosen root to the user in one short line so they know where the file landed.
YYYY-MM-DD-HHMM in local time.<timestamp>-<slug>.html.TIMESTAMP="$(date +%Y-%m-%d-%H%M)"
SLUG="<derived-from-title>"
FILE="$OUT_DIR/${TIMESTAMP}-${SLUG}.html"
Four variants. Pick by content shape, not by taste. All four share spacing/radius/shadow tokens; only typography, scale, palette, and layout change.
| Variant | Use when content is… | Heading / Body / Mono | Body size | Layout | Palette light / dark |
|---|---|---|---|---|---|
| Editorial (default) | Workshop syntheses, trend scans, AI essays, long-form narrative with diagrams | Newsreader (or Iowan Old Style stack) / Source Serif 4 / JetBrains Mono | 18px, 1.25 scale | Single column, 65ch measure, sticky chapter-only TOC on wide screens, drop cap optional on h1 | Warm paper #FBF7F0 on #1A1714 / #131210 on #E8E2D6 |
| Reference | Specs, PRDs, decision trees, API-style docs, glossaries, plans | Inter / Inter / JetBrains Mono | 15px, 1.2 scale | Left sidebar nav + content (max 65-75ch) + optional right TOC; code blocks span full column; both rails sticky | Near-white #FAFAFA on near-black #0A0A0A, single accent from Radix Indigo 9 |
| Dashboard | KPI reports, stack research with matrices, comparison documents, dense numeric tables | Geist Sans / Geist Sans / Geist Mono | 14px, tight 1.15 scale, tabular-nums on | Multi-column grid (auto-fit minmax 280px), sticky filter/legend bar, summary-detail-source stack | Cool #F7F8FA / #0B0D10, status colours from Radix (green-9 / amber-9 / red-9 / blue-9) plus one brand accent |
| Journal | Personal reflections, capture-mode digests, podcast show-notes, book-style pieces | iA Writer Duo (or Newsreader) / iA Writer Quattro (or Source Serif 4) / iA Writer Mono | 19px, loose 1.7 leading, 1.333 scale | Single column, 60ch measure, generous top/bottom whitespace, breadcrumb-only nav, no sidebar | Cream #F5EFE0 on #2A2520 / #1B1814 on #D8CFBF |
Default to Editorial unless the content is unambiguously dashboard- or reference-shaped. Editorial is the highest-comprehension layout for narrative and the right default for ~60% of artefacts.
rem. Editorial 1.25 (major third). Reference / Dashboard 1.2 (minor third). Journal 1.333 (perfect fourth).font-variant-numeric: tabular-nums on table cells and KPI numbers.font-variant-caps: all-small-caps. Common ligatures on for serif body, off for code blocks.prefers-color-scheme: dark by default, no toggle for read-once artefacts. Dark mode must be a designed pair, not a hue rotation: warm-paper artefacts go to warm near-black, cool dashboards go to cool near-black.Every multi-chapter artefact gets the same navigation shell so readers move through artefacts with consistent muscle memory:
01, 02, … prefixes, highlighting the active chapter via IntersectionObserver (rootMargin -30% 0px -55% 0px).id="ch-<slug>" and scroll-margin-top: 2rem so anchor jumps don't sit under the breadcrumb.This shell is mandatory for any artefact with 3+ chapters. For 1-2 chapter artefacts, breadcrumb + footer is enough.
Every artefact ships with a click-to-zoom lightbox for images and charts. It's baked into the template, so callers do not need to add anything per-artefact; just emit normal <img>, Mermaid <div class="mermaid">, and SVG charts (Observable Plot, D3, hand-rolled), and clicks "just work":
<img> in <article> → fullscreen modal..mermaid diagram or chart <svg> in <article> → fullscreen modal.data-zoom to the element.<dialog> behaviour). Clicking the image or the backdrop also closes.Close · Esc button sits top-right as an affordance for non-keyboard users.Implementation is a native <dialog> plus ~40 lines of vanilla JS in the template, no library. If you build a Tailwind / Dashboard variant from scratch, port the same dialog.lightbox block over so behaviour is consistent across variants.
When an artefact is a single self-contained page, write to artifacts/html/<timestamp>-<slug>.html (the current default). When an artefact will have child pages (sub-topics, drill-downs), write to a folder instead:
artifacts/html/
├── index.html # catalog of all artefacts
├── 2026-05-11-1030-pocock-workflow.html # single-page artefact
└── 2026-05-15-0900-product-spec/ # multi-page artefact
├── index.html # parent page with its own TOC
├── api-reference.html # child page 1
├── data-model.html # child page 2
└── acceptance-criteria.html # child page 3
The folder makes it trivial to zip and share (zip -r product-spec.zip 2026-05-15-0900-product-spec/). All children link back to their parent's index.html, and the parent's TOC includes child-page links at the appropriate chapter.
The recommended stack, locked in 2026-05-11 after side-by-side comparison of five styles. Default to this; deviate only with reason.
| Layer | Library | CDN |
|---|---|---|
| Icons | Lucide (font version) | unpkg.com/lucide-static@latest/font/lucide.css |
| Diagrams (flowchart, sequence, mindmap, gantt, timeline, ER, state) | Mermaid 10 | cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js |
| Charts (line, bar, area, scatter, dot) | Observable Plot 0.6 (declarative grammar built on D3, modern API, better defaults than Chart.js) | cdn.jsdelivr.net/npm/@observablehq/[email protected]/+esm (ES module) |
| If the artefact has… | Pull this | CDN |
|---|---|---|
| Genuinely custom data viz (force graphs, sankey, treemap, geo) that Plot can't do well | D3 7 | cdn.jsdelivr.net/npm/d3@7 |
| Math / equations | KaTeX | cdn.jsdelivr.net/npm/katex |
| Code highlighting (3+ code blocks worth styling) | highlight.js (auto-detect) or Prism | cdn.jsdelivr.net/npm/highlight.js@11 |
| Sortable / filterable tables (10+ rows, user interaction expected) | Tabulator | cdn.jsdelivr.net/npm/tabulator-tables@6 |
| Animations | Motion One (~10KB) | cdn.jsdelivr.net/npm/motion@10 |
| Maps | Leaflet or MapLibre | unpkg.com/[email protected] |
| 3D / WebGL | Three.js | cdn.jsdelivr.net/npm/three@latest |
This is the most important calibration. Do NOT pull Shoelace, DaisyUI, or any component library by default. Their design language fights the editorial typography voice and the primitives are small enough to hand-roll.
| Primitive | Recommendation | Notes |
|---|---|---|
| Tabs | Hand-roll with role="tablist", role="tab", role="tabpanel" + ~25 lines JS for click, arrow-key nav, focus management | Full keyboard accessibility, voice-coherent |
| Disclosure / accordion | Native <details> + <summary> | Zero JS |
| Modal / dialog | Native <dialog> | Zero JS |
| Tooltips (simple, one-line) | Native title="" attribute | Browser handles render and a11y |
| Tooltips / popovers (rich content) | Native popover attribute + popovertarget | Stable in all evergreen browsers |
| Badges | Styled <span> | Zero JS |
| Alerts / callouts | Styled <div> with a Lucide icon | Zero JS |
| Copy buttons | <button> + ~10 lines JS using navigator.clipboard.writeText with class-toggle toast feedback | |
:has(), selectors based on children; sometimes saves JS.popover attribute, covered above; native floating UI.Default to editorial unless the content is unambiguously dashboard-shaped. When in doubt, editorial wins. User has confirmed editorial typography is the preferred voice.
jQuery (legacy), Bootstrap (heavier than Tailwind for the same payoff), full React (build step kills the single-file premise), MUI (build step), real shadcn (build step), Shoelace / Web Awesome (design language fights editorial voice; primitives are 35 lines of JS away), Chart.js as default (use Plot; Chart.js is fine as fallback if Plot doesn't fit).
Start from the editorial baseline at .claude/skills/generate-html-artifact/template.html. Layer the libraries you picked in the decision tree above. The baseline gives you:
prefers-color-schemeRender the content body as semantic HTML. Convert Markdown to proper HTML, preserve code blocks, tables, lists, blockquotes, images. Never paste raw Markdown inside a <pre> block; that defeats the point of promoting to HTML.
If the content has structure cues (multiple H2 sections, lists, tables, sequences, comparisons), use them as visual anchors. Long syntheses get chaptered sections; short reflections get one calm column of prose with a pull quote.
For the Tailwind dashboard variant (when the content is dashboard-shaped), use the Tailwind Play CDN baseline instead. Same content philosophy, different layout primitives.
Write tool with file_path=$FILE and content=<rendered HTML>
After writing the new artefact, check how many .html files (excluding index.html itself) live in $OUT_DIR:
COUNT=$(ls "$OUT_DIR"/*.html 2>/dev/null | grep -v "/index.html$" | wc -l | tr -d ' ')
$OUT_DIR/index.html. The index:
<title> tag.Every artefact must include a back-link to the index in its header and its footer:
<nav><a href="index.html">← Back to index</a></nav>
The index page itself does NOT need a back-link (it is the root).
The index filename is always literally index.html, never timestamped, so its URL stays stable across sessions.
# If an index exists, open the index. Otherwise open the new artefact.
if [ -f "$OUT_DIR/index.html" ]; then
open "$OUT_DIR/index.html"
else
open "$FILE"
fi
One short status block to the user:
Wrote → artifacts/html/<filename>
Opened in browser.
Root: <root path>
That's it. No long summary, no commentary, no "let me know if you'd like changes." The artefact speaks for itself; if the user wants edits they will tell you.
highlight.js when the artefact shows multiple code blocks worth styling.target="_blank" by default (let the user choose).prefers-color-scheme. Both themes must read well.git add.<pre>. Always convert to semantic HTML.artifacts/html/ is intentionally visible. Never use .artifacts/.*.md files on disk. For converting wiki pages or vaults into HTML mini-sites, use /generate-portal or a future /skill-md-to-html.testing
--- name: linear-pipeline description: The Fable orchestrator for a single dispatched Linear ticket. Holds almost no context itself; it receives `--issue <ID> --detached`, decides the stage sequence, and fans out a sub-agent per stage, passing forward only each stage's artifact (never re-derived, never inlined into its own context). Step zero, before any planning or stage routing, is a boundary triage against `canon/security-boundary.md` (#199): a match tags Ronan Connolly and stops the run, no
development
--- name: in-your-face description: Capture a chat-only answer into a durable artifact (markdown + HTML, PDF when cheap) and launch it automatically so the user cannot miss it. Use when user says "in your face", "don't let me lose this", "save that answer", "make that durable", or right after answering a substantive side question (a recipe, comparison, how-to, or generated prompt) that would otherwise die with the context. category: workflow argument-hint: [--no-open] [--vault <short>] [hint of
tools
One-shot headless OpenAI Codex CLI calls for background/admin AI tasks — summaries, classification, extraction, admin glue. The default engine for anything that runs AI constantly in the background (daemon-driven, per-event), because it bills the flat ChatGPT subscription instead of Claude usage or per-token API spend, and it keeps working while Claude is rate-limited. NEVER for coding — coding stays Claude. Use when a skill or daemon needs a cheap always-on AI call, when the user says "use codex", "ask codex", "codex as backup", or when building a background summarizer/classifier into a listener or loop. Reads auth from ~/.codex/auth.json (ChatGPT account, no API key).
research
Turn a warranty rejection, repair quote, or RMA email into a cited decision brief — legal read (NL/EU consumer law), is the part user-serviceable, live part and new-unit prices, repair-vs-DIY-vs-new economics, before-you-send-it checklist, deadlines. Use when the user pastes or screenshots a repair quote, warranty rejection, "not covered" email, onderzoekskosten fee, or asks "should I repair or replace this".