html-report
The html-report skill generates self-contained, styled HTML documents saved to the results folder that users can download, share, or export to PDF. Use this when delivering a polished, permanent research artifact such as an earnings summary, equity analysis, or screen writeup that combines narrative text, embedded data, interactive charts, and theme-aware styling designed to resemble professional research desk output.
git clone --depth 1 https://github.com/ginlix-ai/LangAlpha /tmp/html-report && cp -r /tmp/html-report/skills/html-report ~/.claude/skills/html-reportSKILL.md
# HTML Report
Author a styled, self-contained HTML **document** and write it to `results/` (e.g. `results/report.html`). The file panel renders it with full browser semantics — JavaScript runs, CDN libraries load, relative assets resolve, and the user can view it fullscreen, open it in a new tab, download it, or export it to PDF.
This is the right output when the user wants a **deliverable they can keep, share, or print** — an equity research note, an earnings recap, a screen writeup — not a throwaway answer.
> **Read `.agents/skills/ui-design/SKILL.md` before authoring.** It defines the typography, color, and composition standards that keep the report looking like a research desk artifact rather than a generic AI page. This skill covers the mechanics; that one covers the taste.
> **User preferences override these defaults.** Anything the user has told you — in this conversation, in your long-term memory, or in their saved preferences/memos — outranks every rule in this skill. If they want a different structure, no charts, a specific set of sections, or a particular file layout, do that. (Visual taste — fonts, color, accent, light/dark — is `.agents/skills/ui-design/SKILL.md`'s domain; that skill defers to the user's stated style.) Treat the rules here as sensible defaults for when the user hasn't specified.
## Decide: Which Output?
A report from this skill **can be interactive** (sortable tables, tab/filter controls, hover- and zoomable charts — see **Interactivity**, below). So interactivity is *not* what separates it from a dashboard. The real divide is **self-contained snapshot file vs. live served app**:
| Want | Use | Why |
|---|---|---|
| A document the user keeps, shares, or exports to PDF — even one that's interactive within itself | **html-report** (this skill) — `.html` in `results/` | One file on disk, served with real semantics, PDF-exportable. Interactivity runs client-side over an embedded data snapshot. |
| A quick visualization *inside the chat* (one chart, a metric row, a table) | **inline-widget** (`ShowWidget`) | Appears inline between text; no file, no panel |
| A **live served app** — refreshing data, server-side compute, multi-page routing, or a dataset too large to embed | **interactive-dashboard** (`GetPreviewUrl`) | A running app with a backend, not a static file. Needed when the data must be fetched live, not embedded. |
| A simple, short answer | **plain markdown** | A styled HTML document is overkill for a one-paragraph reply |
## Self-Contained by Default
Write **one** complete HTML file. Everything inline — no external CSS/JS files, no build step.
```python
import json
data = {"labels": ["Q1", "Q2", "Q3", "Q4"], "revenue": [2.1, 2.4, 2.6, 3.0]}
html = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Acme Q4 Revenue Review</title>
<style>/* all CSS inline here */</style>
</head>
<body>
<main>...</main>
<script>const DATA = {json.dumps(data, ensure_ascii=False)};</script>
<script>/* render charts from DATA */</script>
</body>
</html>"""
with open("results/report.html", "w", encoding="utf-8") as f:
f.write(html)
```
Rules:
- Full `<!DOCTYPE html>` document with `<head>`/`<body>` (unlike inline-widget, which is a bare fragment).
- **All CSS in a `<style>` block, all JS in `<script>` blocks** — nothing external except allowlisted CDN libraries.
- **Embed data via `<script>const DATA = {json.dumps(data, ensure_ascii=False)};</script>`** — never inline raw Python dicts, never `fetch()` a local file. `ensure_ascii=False` keeps non-ASCII (names, currencies, CJK) readable and correctly encoded.
- **Sample or aggregate large datasets** before embedding. A report doesn't need every tick — downsample to a sensible resolution, aggregate to the reporting period. Keep the embedded payload lean (target well under ~1MB).
## Multi-File When Warranted
The viewer serves files with **real relative-path semantics**, so a report can reference sibling assets and they resolve correctly:
```
results/
report.html # references charts/revenue.png as a relative path
charts/
revenue.png
margins.png
```
```html
<img src="charts/revenue.png" alt="Quarterly revenue" style="width:100%;max-width:720px;">
```
Use multi-file for **image-heavy reports** — e.g. when you've generated high-quality static charts with matplotlib/plotly `savefig` and want to embed them rather than redraw client-side.
Rules:
- Keep all asset paths **relative** (`charts/revenue.png`, not `/results/...` and not absolute filesystem paths).
- Keep every asset **inside the workspace** and under `results/` (or a subdir of it). Do not reference files outside the workspace.
- Prefer self-contained when the charts can reasonably be drawn client-side from embedded `DATA`; reach for multi-file when raster images give materially better output.
## CDN Allowlist
Only these origins are reachable from the rendered document. Anything else (including arbitrary `fetch()`) is blocked.
- `cdnjs.cloudflare.com`
- `cdn.jsdelivr.net`
- `unpkg.com`
- `esm.sh`
- Google Fonts: `fonts.googleapis.com` + `fonts.gstatic.com`
Load chart libraries, fonts, and helpers from these only. Do not call out to data APIs from the document — embed the data instead.
## Theme Variables (Defensive Fallback Form)
The viewer can inject app `--color-*` variables so the report themes with light/dark mode. **Always author colors in the fallback form** so the document also renders correctly standalone, in a downloaded file, and in print:
```css
color: var(--color-text-primary, #1a1a1a);
background: var(--color-bg-card, #ffffff);
border: 1px solid var(--color-border-muted, #e4e1dc);
```
The literal fallback is what shows when no app vars are injected (downloaded file, PDF, plain open). Never write a bare `var(--color-x)` without a fallback, and never hardcode a color with no variable — both break one of theIntegrated 3-statement financial model: linked income statement, balance sheet, and cash flow
Create and manage scheduled and price-triggered automations.
Event tracker: earnings dates, economic releases, conferences, regulatory events
Investment deck QC: number consistency, data-narrative alignment, IB language, formatting audit
Financial model audit: structural checks, formula validation, integrity testing
Competitive landscape analysis: positioning, scorecards, moat assessment, market share trends
Comparable company analysis: operating metrics, valuation multiples, peer benchmarking
DCF valuation: free cash flow projections, WACC, terminal value, sensitivity analysis