htmlify-v2

Convert any content (markdown, specs, plans, findings) into a polished, self-contained static HTML document with a modern light/muted design. V2 standalone.

jakkaj/tools26 installsMITSynced Aug 26

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI

Agent Skills format with YAML frontmatter. Claude Code reads it as-is.

---
name: "htmlify-v2"
description: "Convert any content (markdown, specs, plans, findings) into a polished, self-contained static HTML document with a modern light/muted design. V2 standalone."
license: "MIT"
---

Please deep think / ultrathink as this is a complex task.

# htmlify-v2

**Static HTML document generator** — takes any content the user points to (markdown files, notes, specs, plans, conversation context) and produces a polished, self-contained HTML file. Zero dependencies, opens directly in a browser, ready to share or print to PDF.

````md
User input:

$ARGUMENTS

Expected usage patterns:
```bash
/htmlify <source>                           # HTMLify a file or path
/htmlify <source> --output path/to/out.html # Specify output path
/htmlify                                    # HTMLify from conversation context
/htmlify --dark                             # Use dark variant
```

Where `<source>` can be:
- A file path (markdown, text, any readable file)
- A directory (concatenates relevant files)
- Omitted — uses the current conversation context or the user's description
````

## Purpose

Produce beautiful, zero-dependency static HTML documents from raw content. The output should look like a polished report you'd share with stakeholders — not a raw markdown render. Think Notion page or Linear changelog — clean, readable, professional.

## Flow

### 1) Parse Arguments

- Determine the **source** content (file path, directory, or conversation context)
- Determine the **output path** (default: same directory as source, with `.html` extension; for context-based, use `./scratch/` or current directory)
- Determine **theme** (default: light; `--dark` for dark variant)

### 2) Load & Analyse Source Content

- Read the source content fully
- Identify the document structure:
  - Title and subtitle
  - Sections and their hierarchy
  - Tables, lists, code blocks
  - Diagrams (mermaid candidates)
  - Key findings, recommendations, callouts
  - Metrics or summary data
- Determine which components best represent each content element

### 3) Generate HTML

**Rules:**
- Use semantic HTML throughout — real HTML elements, NOT markdown rendered at runtime
- **First line** of the output file MUST be: `<!-- Generated by htmlify-v2 -->`
- All CSS is inlined in a `<style>` block — single self-contained file
- Select appropriate accent colours from the palette to visually distinguish sections
- Use callout variants to match tone (see palette below)
- Use tables for structured comparisons — don't force everything into cards
- Add anchor navigation bar if the document has 3+ sections
- Include mermaid diagrams where content describes flows, architectures, or relationships
- Add mermaid.js CDN script ONLY if mermaid diagrams are present
- Preserve the substance and detail of the source — don't summarise or truncate

### 4) Write Output

- Write the HTML file to the determined output path
- Confirm the output path and file size to the user
- Suggest `open <path>` to preview

---

## Built-in Design System

The skill carries its own CSS. No external template files needed.

### Design Principles

- **Light and airy** — generous whitespace, muted backgrounds, subtle borders
- **Typography-first** — Inter/system font stack, clear hierarchy, comfortable reading width
- **Muted accents** — no saturated primaries; use soft, desaturated tones
- **Minimal chrome** — content speaks, UI disappears

### Colour Palette (Light Mode)

```css
:root {
  /* Surface & text */
  --bg:           #FAFAFA;
  --bg-card:      #FFFFFF;
  --bg-nav:       #F5F5F4;
  --text:         #1C1917;
  --text-muted:   #78716C;
  --text-subtle:  #A8A29E;
  --border:       #E7E5E4;
  --border-hover: #D6D3D1;

  /* Accent palette — muted, desaturated */
  --accent-blue:    #6B9BD2;
  --accent-green:   #6BA387;
  --accent-amber:   #C4985A;
  --accent-rose:    #C47A7A;
  --accent-purple:  #9B8EC4;
  --accent-teal:    #5DA3A3;

  /* Semantic callouts */
  --info-bg:      #EFF6FF;   --info-border:    #93C5FD;
  --success-bg:   #F0FDF4;   --success-border: #86EFAC;
  --warning-bg:   #FFFBEB;   --warning-border: #FCD34D;
  --error-bg:     #FEF2F2;   --error-border:   #FCA5A5;
  --insight-bg:   #FAF5FF;   --insight-border: #C4B5FD;
  --neutral-bg:   #F5F5F4;   --neutral-border: #D6D3D1;

  /* Code */
  --code-bg:      #F5F5F4;
  --code-text:    #292524;

  /* Spacing */
  --radius:       8px;
  --space-xs:     0.25rem;
  --space-sm:     0.5rem;
  --space-md:     1rem;
  --space-lg:     1.5rem;
  --space-xl:     2.5rem;
}
```

### Colour Palette (Dark Mode — `--dark` flag)

```css
:root {
  --bg:           #1A1A1A;
  --bg-card:      #242424;
  --bg-nav:       #1E1E1E;
  --text:         #E7E5E4;
  --text-muted:   #A8A29E;
  --text-subtle:  #78716C;
  --border:       #333333;
  --border-hover: #444444;

  --accent-blue:    #7DADE2;
  --accent-green:   #7DB89B;
  --accent-amber:   #D4A86A;
  --accent-rose:    #D48A8A;
  --accent-purple:  #ADA0D4;
  --accent-teal:    #6DB3B3;

  --info-bg:      #1E293B;   --info-border:    #60A5FA;
  --success-bg:   #14291E;   --success-border: #6EE7A0;
  --warning-bg:   #2D2410;   --warning-border: #FBBF24;
  --error-bg:     #2D1414;   --error-border:   #F87171;
  --insight-bg:   #1E1533;   --insight-border: #A78BFA;
  --neutral-bg:   #262626;   --neutral-border: #404040;

  --code-bg:      #2A2A2A;
  --code-text:    #E7E5E4;
}
```

### Core CSS

```css
* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.7;
  max-width: 860px;
  margin: 0 auto;
  padding: var(--space-xl) var(--space-lg);
}

/* Typography */
h1 { font-size: 2rem; font-weight: 700; letter-spacing: -0.02em; margin-bottom: var(--space-xs); }
h2 { font-size: 1.35rem; font-weight: 600; letter-spacing: -0.01em; margin-top: var(--space-xl); margin-bottom: var(--space-md); color: var(--text); }
h3 { font-size: 1.1rem; font-weight: 600; margin-top: var(--space-lg); margin-bottom: var(--space-sm); }
.subtitle { color: var(--text-muted); font-size: 0.95rem; margin-bottom: var(--space-xl); }
p { margin-bottom: var(--space-md); }

/* Navigation */
.nav {
  display: flex; flex-wrap: wrap; gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  background: var(--bg-nav); border-radius: var(--radius);
  margin-bottom: var(--space-xl); border: 1px solid var(--border);
}
.nav a {
  color: var(--text-muted); text-decoration: none; font-size: 0.85rem;
  font-weight: 500; padding: var(--space-xs) var(--space-sm);
  border-radius: 4px; transition: all 0.15s;
}
.nav a:hover { color: var(--text); background: var(--border); }

/* Cards */
.card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: var(--space-lg);
  margin-bottom: var(--space-lg);
}
.card.border-blue   { border-left: 3px solid var(--accent-blue); }
.card.border-green  { border-left: 3px solid var(--accent-green); }
.card.border-amber  { border-left: 3px solid var(--accent-amber); }
.card.border-rose   { border-left: 3px solid var(--accent-rose); }
.card.border-purple { border-left: 3px solid var(--accent-purple); }
.card.border-teal   { border-left: 3px solid var(--accent-teal); }

/* Callouts */
.callout {
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius); margin-bottom: var(--space-md);
  border-left: 3px solid; font-size: 0.92rem;
}
.callout.info    { background: var(--info-bg);    border-color: var(--info-border); }
.callout.success { background: var(--success-bg); border-color: var(--success-border); }
.callout.warning { background: var(--warning-bg); border-color: var(--warning-border); }
.callout.error   { background: var(--error-bg);   border-color: var(--error-border); }
.callout.insight { background: var(--insight-bg); border-color: var(--insight-border); }
.callout.neutral { background: var(--neutral-bg); border-color: var(--neutral-border); }

/* Badges */
.badge {
  display: inline-block; font-size: 0.75rem; font-weight: 600;
  padding: 2px 8px; border-radius: 10px;
  background: var(--neutral-bg); color: var(--text-muted);
}
.badge.blue   { background: var(--info-bg);    color: var(--accent-blue); }
.badge.green  { background: var(--success-bg); color: var(--accent-green); }
.badge.amber  { background: var(--warning-bg); color: var(--accent-amber); }
.badge.rose   { background: var(--error-bg);   color: var(--accent-rose); }
.badge.purple { background: var(--insight-bg); color: var(--accent-purple); }

/* Tables */
table { width: 100%; border-collapse: collapse; margin-bottom: var(--space-md); font-size: 0.9rem; }
th { text-align: left; font-weight: 600; color: var(--text-muted); font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; padding: var(--space-sm) var(--space-md); border-bottom: 2px solid var(--border); }
td { padding: var(--space-sm) var(--space-md); border-bottom: 1px solid var(--border); }
tr:last-child td { border-bottom: none; }

/* Code */
code { font-family: 'JetBrains Mono', 'Fira Code', monospace; font-size: 0.85em; background: var(--code-bg); color: var(--code-text); padding: 2px 6px; border-radius: 4px; }
pre { background: var(--code-bg); padding: var(--space-md); border-radius: var(--radius); overflow-x: auto; margin-bottom: var(--space-md); border: 1px solid var(--border); }
pre code { background: none; padding: 0; }

/* Verdict / summary block */
.verdict {
  background: var(--bg-card); border: 2px solid var(--accent-green);
  border-radius: var(--radius); padding: var(--space-lg);
  margin: var(--space-xl) 0; text-align: center;
}
.verdict h3 { margin-top: 0; color: var(--accent-green); }

/* Flow steps */
.flow-step {
  display: flex; align-items: flex-start; gap: var(--space-md);
  margin-bottom: var(--space-md); padding: var(--space-md);
  background: var(--bg-card); border-radius: var(--radius); border: 1px solid var(--border);
}
.flow-step .step-num {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent-blue); color: white; font-weight: 700;
  font-size: 0.8rem; display: flex; align-items: center; justify-content: center;
}

/* Grid layouts */
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: var(--space-md); }
@media (max-width: 640px) { .grid-2, .grid-3 { grid-template-columns: 1fr; } }

/* Phase labels */
.phase-label {
  display: inline-block; font-size: 0.75rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-muted); margin-bottom: var(--space-sm);
}

/* Lists */
ul, ol { padding-left: var(--space-lg); margin-bottom: var(--space-md); }
li { margin-bottom: var(--space-xs); }

/* Horizontal rule */
hr { border: none; border-top: 1px solid var(--border); margin: var(--space-xl) 0; }

/* Mermaid */
.mermaid { margin: var(--space-md) 0; text-align: center; }

/* Print */
@media print {
  body { max-width: 100%; padding: 1cm; }
  .nav { display: none; }
  .card { break-inside: avoid; }
}
```

### Component Catalogue

| Component | Class | When to Use |
|-----------|-------|-------------|
| **Card** | `.card .border-{colour}` | Wrap sections; vary border colour per section |
| **Callout** | `.callout .{info\|success\|warning\|error\|insight\|neutral}` | Highlight key points, warnings, tips |
| **Badge** | `.badge .{blue\|green\|amber\|rose\|purple}` | Status labels, categories, tags |
| **Table** | `<table>` | Structured data, comparisons |
| **Verdict** | `.verdict` | Key conclusions, final recommendations |
| **Flow Step** | `.flow-step` + `.step-num` | Sequential processes, numbered steps |
| **Grid** | `.grid-2` / `.grid-3` | Side-by-side layouts |
| **Phase Label** | `.phase-label` | Phase markers in phased work |
| **Nav** | `.nav` | Anchor navigation for 3+ sections |
| **Code** | `<pre><code>` | Code blocks |
| **Mermaid** | `.mermaid` | Architecture diagrams, flows |

### Colour Selection Guide

Rotate border colours across sections for visual distinction:

```
Section 1 → border-blue
Section 2 → border-teal
Section 3 → border-purple
Section 4 → border-amber
Section 5 → border-green
Section 6 → border-rose
```

Don't use the same colour for adjacent cards.

---

## Example Output Structure

```html
<!-- Generated by htmlify-v2 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document Title</title>
<style>
/* [full built-in CSS from above] */
</style>
</head>
<body>

<h1>Document Title</h1>
<p class="subtitle">Context · Date</p>

<nav class="nav">
  <a href="#overview">Overview</a>
  <a href="#findings">Findings</a>
  <a href="#recommendations">Recommendations</a>
</nav>

<div id="overview" class="card border-blue">
  <h2>Overview</h2>
  <p>Content goes here...</p>
</div>

<div class="callout info">
  <strong>Note:</strong> Important context the reader should know.
</div>

<div id="findings" class="card border-teal">
  <h2>Key Findings</h2>
  <table>
    <tr><th>Finding</th><th>Impact</th><th>Status</th></tr>
    <tr><td>Finding 1</td><td>High</td><td><span class="badge rose">Critical</span></td></tr>
    <tr><td>Finding 2</td><td>Medium</td><td><span class="badge amber">Review</span></td></tr>
  </table>
</div>

<div id="recommendations" class="card border-purple">
  <h2>Recommendations</h2>
  <div class="flow-step">
    <div class="step-num">1</div>
    <div><strong>First step</strong> — do this thing first.</div>
  </div>
  <div class="flow-step">
    <div class="step-num">2</div>
    <div><strong>Second step</strong> — then do this.</div>
  </div>
</div>

<div class="verdict">
  <h3>Verdict</h3>
  <p>Summary conclusion here.</p>
</div>

</body>
</html>
```

## Quality Standards

- Output must be visually polished — intentionally designed, not auto-generated
- Content hierarchy must be clear — use card borders, headings, and spacing
- Don't over-componentise — plain paragraphs inside cards are fine
- Tables should be used for tabular data; don't convert tables to cards
- Mermaid diagrams must be syntactically correct
- HTML must render correctly when opened directly in a browser (file:// protocol)
- Preserve the substance and detail of the source — don't summarise or truncate

## Anti-Patterns

- Rendering markdown at runtime with a JS library
- Using the same card border colour for every section
- Converting every paragraph into a callout
- Losing content detail during conversion
- Adding build tools, npm, or any dependencies
- Generating broken mermaid syntax
- Forgetting the comment on line 1

More General & Other skills

← All General & Other skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY