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.development
Close the loop on a Linear ticket when its work ships - move the status and post a deploy comment with the PR link, what shipped, and a try-it link, mentioning the collaborator. Used as the tail of /ro:linear-nightshift for every merged mirror, or manually after an ad-hoc build. Triggers on "linear update", "update the linear ticket", "mark NUT-x done", "tell eoin it shipped", "/ro:linear-update".
devops
Run a night-shift against a collaborator's Linear board. Pulls the team's Grilled tickets (/ro:linear-grill moves a ticket to Grilled once its questions are answered), VERIFIES the questions were actually answered (unanswered → bounce the ticket to the "Question for <name>" state), mirrors verified tickets to ephemeral GitHub issues with ready-for-agent, then runs the standard /ro:night-shift machinery on GitHub. Tail-calls /ro:linear-update for everything that merged + deployed. Triggers on "linear nightshift", "nightshift linear", "drain the linear board", "run the shift off linear", "/ro:linear-nightshift".
development
Grill a collaborator's Linear tickets and move every processed ticket to where it belongs. Resolves the board from the repo's .ro-linear.json, reads the collaborator's Backlog / Ready-for-agent issues, then per ticket either posts 3-5 decision-extracting questions (state moves to "Question for <name>") or confirms it build-ready (state moves to "Grilled", the gate /ro:linear-nightshift consumes); shipped-and-confirmed tickets close as Done. The async-collaborator counterpart of /ro:day-shift for people who never touch GitHub. Triggers on "grill linear", "grill eoin's tickets", "linear grill", "add questions to the linear tickets", "/ro:linear-grill".
development
--- name: about-page description: Add a standard About page to any web app, what it is, the tech stack, and an FAQ, wired into a footer link with a sticky footer. Built with Spartan + Tailwind (the canonical component layer) and falls back to semantic HTML so it ships reliably. Use whenever building, polishing, or shipping an app, every app should have one. Triggers on "add an about page", "about page", "footer about link", or as a standard step in app build/polish. category: frontend argument-h