# Rich Render

> Use when a turn produces a multi-item synthesis (>=5 discrete items that benefit from cross-comparison) — triage, audit, survey, bug-sweep, design-alternatives, research findings, scorecards — and pasting it as raw Markdown in chat would be lower-bandwidth than a glanceable dashboard. Also when the operator says "rich render", "dashboard", "make it a dashboard", or asks to defer a long synthesis out of chat. Produces a single self-contained dark HTML file saved to ~/rich-renders/.

- Skill: `evnchn-agentic/rich-render` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add evnchn-agentic/rich-render`
- Raw SKILL.md: https://api.skillmd.com/api/skills/evnchn-agentic/rich-render/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: evnchn-agentic (https://skillmd.com/u/evnchn-agentic)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/evnchn-agentic/rich-render

---


# Rich Render

## Overview

A **rich render** is a single self-contained dark-themed HTML+CSS dashboard (no external deps, no build step) saved to `~/rich-renders/<topic>-<date>.html` and delivered via SendUserFile. It carries a multi-item synthesis at far higher information-density-per-glance than a Markdown table, while keeping the inline chat reply terse — the heavy artifact is **deferred** so live back-and-forth doesn't burn tokens on chrome the operator isn't reading.

**Operator-validated** (nicegui 3.13 triage: *"splendid, pretty much no need to go back to it"*). This is a proven house format, not an experiment.

## When to Use

Use when a turn yields **≥5 discrete items that benefit from cross-comparison**:
- PR / issue / notification triage
- Dependency or security audit
- Bug sweeps, finding lists, design-alternative comparisons
- Research syntheses, scorecards, "did X work?" verdict write-ups

Also when the operator explicitly says *rich render / dashboard / defer this out of chat*.

**Don't use for:** <5 items, a single linear answer, a code diff (use the editor), or anything the operator needs to act on inline right now. When in doubt for borderline counts, a terse Markdown reply is fine.

## The recipe (don't deviate from the load-bearing parts)

1. **Copy `template.html`** (in this skill dir) as the scaffold. It already contains the canonical palette, card/table/stat components, and the (beta) remote-scroll d-pad.
2. **Replace the content** between the `CONTENT` markers, **and** the `<title>` text in `<head>` (it's the one head element you fill). Keep the `<head>` **CSS** intact (the `#scroller` wrapper + d-pad are a beta affordance — see below; keep by default, fine to drop). Add/remove `<h2>` sections, `.stat` tiles, and table rows freely — the template ships a minimal 2-stat / 2-section example, not a fixed shape; size it to the content. Use a `<details>` block to tuck a plain-language on-ramp, an evidence/diligence trail, or "for agents / the curious" depth out of the main flow (keeps it scannable for a skimmer, complete for a digger).
3. **Lead with the verdict.** Put the one-sentence bottom line in a `.card` at the top, before the supporting sections. Don't bury it.
4. **Save to `~/rich-renders/<topic>-<date>.html`** (create the directory if it doesn't exist — it's the standing home for these). Convention: lowercase-hyphenated slug, then trailing ISO date — `gh-notif-triage-2026-06-22.html`. The shield emoji in the template `<h1>` is a placeholder — swap it for a topic-fitting one or drop it.
5. **Verify, then deliver** (see below). Inline chat reply stays a 1–3 line markdown summary + "rendered: <path>".

## Load-bearing rules

- **No external dependencies.** No CDN CSS/JS, no web fonts, no `<img src=http…>`. Self-contained means it renders offline, forever. Inline any small SVG; base64 small images only if essential.
- **Dark theme, fixed palette.** bg `#0d1117` · card/surface `#161b22` · borders `#30363d`/`#21262d` · body text `#e6edf3` · muted `#8b949e` · headings & links `#79c0ff` · title `#f0f6fc` · verdict green `#7ee787` (accent `#56d364`) / red `#f85149` / amber `#e3b341` / slate `#adbac7`. These literal values are the invariant; hoisting them into `:root` vars is a common, equally-fine variant — the colors stay constant either way. No light theme.

### Remote-scroll d-pad (BETA — situational, kept by default)

The template ships a fixed d-pad + `#scroller` wrapper. **Origin:** Claude Code **remote control over Android** intercepted touch-drag scroll, and a wide body made `position:fixed` mis-resolve off-screen — which could strand a render unscrollable. The fix puts all content in `#scroller` (`body{overflow:hidden}`) and scrolls it via the d-pad in both axes. **Status: beta / unverified** — the **iOS** remote app doesn't have the interception bug, so the author can't currently reproduce or test it. It's invisible on desktop and harmless, so the template keeps it by default; drop it freely if you don't need it. **PRs that verify or refine it are welcome.**

### Component → meaning map (the template's class vocabulary)

| Class | Use for |
|---|---|
| `.card .win` (green border) | positive verdict — pass / ship / resolved |
| `.card .fail` (red border) | negative verdict — fail / blocker / close |
| `.card .hard` (amber border) | caveat / hold / open question / irreducible |
| `.card .info` (blue border) | neutral context / methodology |
| `td.g` `td.r` `td.y` `td.s` | table cell green / red / amber / slate-neutral |
| `b.gg` `b.rr` `b.yy` | inline emphasis green / red / amber |
| `.stat` (`.n` number, `.k` label) | hero stat tile in the `.stats` strip |
| `<details>` / `<summary>` | progressive disclosure — plain-language on-ramp, evidence/diligence trail, or "N hidden / for agents" deep-dive; keeps the main flow scannable |

## Verify before declaring done (seeing-is-believing)

Self-contained HTML can't fail to "build", but layout can. The **always-on** check is that it's genuinely self-contained:
```bash
F=~/rich-renders/<file>.html
ls -l "$F"                                        # exists, non-trivial size
grep -Eqi 'src="https?:|href="https?://[^"]*\.css|cdn|googleapis' "$F" \
  && echo "WARN: possible external dependency" || echo "ok: self-contained"
```
**If you kept the d-pad** (default), confirm its three tokens survived — a combined `grep -c` can pass on a render whose d-pad you broke (e.g. dropped the `<script>` but left a comment mentioning `#scroller`), so assert each independently:
```bash
for t in 'id="scroller"' 'id="scrollnav"' 'function scn'; do
  grep -q "$t" "$F" && echo "ok: $t" || echo "MISSING: $t"; done
```
To actually exercise the d-pad (beta), render at **~390px width** (Playwright/headless Chrome), call `scn(1,0)` / `scn(0,1)`, and confirm `scrollLeft`/`scrollTop` advanced (smooth scroll is async — wait ~500ms).

## Delivery

- **Default = private to the operator.** `SendUserFile` the local path — pass `files` as an **array of strings**: `SendUserFile(files=["~/rich-renders/<file>.html"], caption="…")`. A bare unquoted path is the common first-try mistake and fails `InputValidationError` (the harness retries, but it's a wasted round-trip). Assume not for sharing unless told otherwise.
- **No `SendUserFile` in your toolset** (e.g. running as a subagent)? State the saved path in your final report and let the caller deliver it — don't skip the render.
- **Publishing** (only when asked to share a link): `gh gist create FILE --public --desc "…"`, then the htmlpreview URL `https://htmlpreview.github.io/?https://gist.githubusercontent.com/<user>/<hash>/raw/<file>.html`. Gotchas: `gh gist edit` reads STDIN (`cat f | gh gist edit <id> -f <name>`), `gh gist delete` needs `--yes`. Treat a gist as a single conscious publish — delete & republish rather than edit mid-iteration. Verify `curl -sI <raw_url> | head -1` → `200` before sharing.

## Common mistakes

| Mistake | Fix |
|---|---|
| Treating the d-pad as mandatory | It's a beta Android-remote workaround — keep by default, fine to omit; don't gate "done" on it |
| Pulled in a CDN (Tailwind, Chart.js, a font) | Self-contained only; inline everything |
| Buried the verdict at the bottom | Lead with a `.card` one-liner up top |
| Pasted the full HTML into chat | Defer it — `SendUserFile` + a terse summary line |
| Light theme / random colors | Use the canonical dark palette |
| Saved to cwd or `/tmp` | Always `~/rich-renders/<topic>-<date>.html` |

## Origin

This is a **captured living standard**, not a format invented up front. It was distilled from a large corpus of real rich-renders produced across day-to-day Claude Code use — the format earned its place by repetition. This file just writes the grammar down so an agent can reproduce it in a few hundred tokens instead of re-deriving it from a pile of samples.

