diff --git a/.changeset/visual-html-report.md b/.changeset/visual-html-report.md
new file mode 100644
index 00000000..8c2c94ac
--- /dev/null
+++ b/.changeset/visual-html-report.md
@@ -0,0 +1,10 @@
+---
+'@svelte-vitals/core': minor
+'svelte-vitals': minor
+---
+
+Add a visual HTML report: `svelte-vitals --reporter html` writes a self-contained,
+styled HTML page (Health score, per-category and per-route scores, findings with
+fixes) you can open in a browser. Output path defaults to `svelte-vitals-report.html`;
+override with `--out-file ` or `--out-file -` for stdout. The core gains
+`buildHtmlDocument` / `formatHtmlReport` for reuse by other surfaces.
diff --git a/.gitignore b/.gitignore
index 7d68bd40..0f674e62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,5 @@ dist/
.svelte-vitals/
coverage/
.pnpm-store
-.superpowers
\ No newline at end of file
+# subagent-driven-development scratch (ledger, briefs, reports)
+.superpowers/
diff --git a/docs/src/content/docs/guides/cli.md b/docs/src/content/docs/guides/cli.md
index 895d9a6c..687301c0 100644
--- a/docs/src/content/docs/guides/cli.md
+++ b/docs/src/content/docs/guides/cli.md
@@ -24,6 +24,9 @@ Select the output format.
| `agent` | Markdown remediation document for AI coding agents |
| `sarif` | SARIF v2.1 (compatible with GitHub Code Scanning and other SAST tools) |
| `github` | GitHub Actions annotation format |
+| `html` | Self-contained HTML report, open in a browser |
+
+Accepted values: `console, json, agent, sarif, github, or html`
**Auto-selection:** when run inside a known AI-agent environment (e.g. Claude Code sets `CLAUDECODE`), the `agent` reporter is selected automatically. When run inside GitHub Actions (`GITHUB_ACTIONS=true`), the `github` reporter is selected automatically. An explicit `--reporter` flag always overrides auto-selection. You can also override via the `SVELTE_VITALS_REPORTER` environment variable.
@@ -31,6 +34,10 @@ Select the output format.
Alias for `--reporter=json`.
+### `--out-file `
+
+Output path for `--reporter html` (default `svelte-vitals-report.html`; `-` for stdout).
+
### `--fail-on `
Exit with code `1` when any finding reaches the given severity threshold.
diff --git a/docs/src/content/docs/guides/reporters.md b/docs/src/content/docs/guides/reporters.md
index 923ee42d..d1e7442c 100644
--- a/docs/src/content/docs/guides/reporters.md
+++ b/docs/src/content/docs/guides/reporters.md
@@ -3,7 +3,7 @@ title: Reporters
description: Choose how svelte-vitals formats and outputs its findings.
---
-svelte-vitals supports five output reporters. Select one with `--reporter `, or let auto-selection pick the right one for your environment.
+svelte-vitals supports six output reporters. Select one with `--reporter `, or let auto-selection pick the right one for your environment.
## Available reporters
@@ -63,6 +63,18 @@ The `github` reporter is auto-selected when `GITHUB_ACTIONS=true` is set (which
svelte-vitals --reporter github
```
+## HTML report
+
+`--reporter html` writes a self-contained HTML report — Health score, per-category and per-route scores, and every finding with its fix — that you open in a browser. The file inlines all its CSS and JS, so it works offline and is easy to attach to a CI run or share.
+
+```bash
+svelte-vitals --reporter html # writes svelte-vitals-report.html
+svelte-vitals --reporter html --out-file report.html
+svelte-vitals --reporter html --out-file - # write to stdout instead of a file
+```
+
+By default it writes `svelte-vitals-report.html` in the current directory and prints the path to stderr. Use `--out-file ` to change the location, or `--out-file -` to stream it to stdout (for piping or CI artifacts).
+
## Auto-selection priority
1. **Explicit `--reporter `** — always wins.
diff --git a/docs/src/content/docs/ja/guides/cli.md b/docs/src/content/docs/ja/guides/cli.md
index cce97491..b55dd303 100644
--- a/docs/src/content/docs/ja/guides/cli.md
+++ b/docs/src/content/docs/ja/guides/cli.md
@@ -24,6 +24,9 @@ svelte-vitals [path] [options]
| `agent` | AI コーディングエージェント向け Markdown 修正ドキュメント |
| `sarif` | SARIF v2.1(GitHub Code Scanning などの SAST ツールに対応) |
| `github` | GitHub Actions アノテーション形式 |
+| `html` | ブラウザで開く自己完結の HTML レポート |
+
+指定できる値:`console, json, agent, sarif, github, html のいずれか`
**自動選択:** 既知の AI エージェント環境(例:Claude Code が `CLAUDECODE` を設定)で実行された場合、`agent` レポーターが自動的に選択されます。GitHub Actions(`GITHUB_ACTIONS=true`)で実行された場合は `github` レポーターが自動選択されます。明示的な `--reporter` フラグは常に自動選択よりも優先されます。`SVELTE_VITALS_REPORTER` 環境変数でも上書きできます。
@@ -31,6 +34,10 @@ svelte-vitals [path] [options]
`--reporter=json` のエイリアスです。
+### `--out-file `
+
+`--reporter html` の出力先パス(既定 `svelte-vitals-report.html`、`-` で標準出力)。
+
### `--fail-on `
指定した重大度の閾値に達した検出結果が存在する場合、終了コード `1` で終了します。
diff --git a/docs/src/content/docs/ja/guides/reporters.md b/docs/src/content/docs/ja/guides/reporters.md
index 87790721..4a6f82b8 100644
--- a/docs/src/content/docs/ja/guides/reporters.md
+++ b/docs/src/content/docs/ja/guides/reporters.md
@@ -3,7 +3,7 @@ title: レポーター
description: svelte-vitals が検出結果をフォーマットして出力する方法を選択します。
---
-svelte-vitals は 5 つの出力レポーターをサポートしています。`--reporter ` で選択するか、環境に適したものを自動選択に任せてください。
+svelte-vitals は 6 つの出力レポーターをサポートしています。`--reporter ` で選択するか、環境に適したものを自動選択に任せてください。
## 利用可能なレポーター
@@ -63,6 +63,18 @@ GitHub Actions の [ワークフローコマンド](https://docs.github.com/en/a
svelte-vitals --reporter github
```
+## HTML レポート
+
+`--reporter html` は自己完結の HTML レポート(Health スコア・カテゴリ別/ルート別スコア・各検出結果と修正)を出力し、ブラウザで開けます。CSS と JS をすべてインライン化しているためオフラインで動作し、CI 成果物として添付したり共有したりするのも簡単です。
+
+```bash
+svelte-vitals --reporter html # svelte-vitals-report.html を出力
+svelte-vitals --reporter html --out-file report.html
+svelte-vitals --reporter html --out-file - # ファイルではなく標準出力へ
+```
+
+既定ではカレントディレクトリに `svelte-vitals-report.html` を書き出し、パスを stderr に表示します。`--out-file ` で出力先を変更でき、`--out-file -` で標準出力にストリームします(パイプや CI 成果物向け)。
+
## 自動選択の優先順位
1. **明示的な `--reporter `** — 常に最優先。
diff --git a/docs/superpowers/plans/2026-06-23-visual-html-report.md b/docs/superpowers/plans/2026-06-23-visual-html-report.md
new file mode 100644
index 00000000..ef548c5a
--- /dev/null
+++ b/docs/superpowers/plans/2026-06-23-visual-html-report.md
@@ -0,0 +1,973 @@
+# Visual HTML Report Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Add a self-contained visual HTML report — `svelte-vitals --reporter html` writes a single styled `.html` file showing the Health score, per-category and per-route scores, and findings with fixes.
+
+**Architecture:** A runtime-agnostic renderer in `@svelte-vitals/core` turns the existing `JsonReport` into a full self-contained HTML string (server-side templating: data is rendered into the markup; inline `` and `` placeholders are filled in Tasks 2 and 3.
+
+**Files:**
+
+- Create: `packages/core/src/reporter/html.ts`
+- Modify: `packages/core/src/index.ts` (export the new functions)
+- Test: `packages/core/test/html-report.test.ts`
+
+**Interfaces:**
+
+- Consumes: `buildJsonReport(results, config, meta): JsonReport` and `type JsonReport` from `./json.js`; `Category, Config, Result` from `../types.js`.
+- Produces:
+ - `escapeHtml(s: string): string`
+ - `scoreBand(score: number): 'good' | 'warn' | 'poor'`
+ - `BAND_COLOR: Record<'good' | 'warn' | 'poor', string>`
+ - `buildHtmlDocument(report: JsonReport, meta: { version: string }): string`
+ - `formatHtmlReport(results: Result[], config: Config, meta: { version: string }): string`
+ - Internal (same file, not exported): `STYLE: string` (empty in T1), `SCRIPT: string` (empty in T1), and section helpers `renderTopbar`, `renderHero`, `renderRoutes`, `renderSiteChecks`, `renderFinding`.
+
+- [ ] **Step 1: Write the failing test**
+
+Create `packages/core/test/html-report.test.ts`:
+
+```ts
+import { describe, it, expect } from 'vitest';
+import { buildHtmlDocument, formatHtmlReport, escapeHtml, scoreBand } from '../src/index.js';
+import type { JsonReport } from '../src/reporter/json.js';
+
+const report: JsonReport = {
+ version: '9.9.9',
+ score: 82,
+ weights: { seo: 1, performance: 1 },
+ categories: {
+ seo: { score: 91, scoreModel: { mode: 'weighted' } as never },
+ performance: { score: 68, scoreModel: {} as never }
+ },
+ summary: { critical: 1, warning: 2, info: 1, passed: 37, dynamic: 3 },
+ routes: [
+ { route: '/', score: 100, issues: [] },
+ {
+ route: '/products/[id]',
+ score: 40,
+ issues: [
+ {
+ id: 'SEO001',
+ category: 'seo',
+ title: 'Missing ',
+ detection: { presence: 'none', value: 'absent' },
+ location: 'src/routes/products/[id]/+page.svelte',
+ recommendation: 'Add a in .',
+ docsUrl: 'https://oekazuma.github.io/svelte-vitals/rules/seo001',
+ fix: {
+ description: 'Add a .',
+ snippet: '\n {data.title}\n',
+ lang: 'svelte'
+ },
+ severity: 'critical'
+ }
+ ]
+ }
+ ],
+ siteIssues: [
+ {
+ id: 'SEO007',
+ category: 'seo',
+ title: 'No sitemap',
+ detection: { presence: 'none', value: 'absent' },
+ location: 'project',
+ recommendation: 'Add a sitemap.',
+ severity: 'info'
+ }
+ ]
+};
+
+describe('buildHtmlDocument', () => {
+ const html = buildHtmlDocument(report, { version: '9.9.9' });
+
+ it('is a full self-contained HTML document with a title', () => {
+ expect(html.startsWith('')).toBe(true);
+ expect(html).toContain('svelte-vitals report');
+ expect(html).toContain('