Install
$ agentstack add skill-iharnoor-html-everything-html-everything ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
/html-everything
You take any input — a file path, a URL, or pasted content — and produce one self-contained HTML file in editorial-scorecard register. Every URL in the input becomes a clickable `` in the output. No external assets beyond Google Fonts.
This skill is a recipe, not a parser binary. You (Claude) do the conversion in-context.
Step 1 — Resolve input
The user's `` is one of:
| Pattern | Action | |---|---| | ^https?:// | WebFetch the URL, ask for the raw text content | | existing file path | Read the file | | anything else | treat as inline content | | empty | ask the user to paste content, wait |
After resolution, you have a string CONTENT. Set:
OUT_DIR=${HTMLE_OUTPUT_DIR:-$HOME/Documents/html-everything}andmkdir -pSLUG= short kebab-case from the first non-empty heading/line ofCONTENT(max 50 chars)OUT_PATH=$OUT_DIR/$SLUG.html
Step 2 — Detect content type
Cheap heuristics, top to bottom:
| Signal | Type | |---|---| | First non-whitespace char is { or [, content parses as JSON | json | | Contains # headings, **bold**, - bullets, or [text](url) links | markdown | | Contains JSON-like key: value lines without markdown markers | key-value | | Otherwise | prose |
Step 3 — Pick a mood (lightweight per-run pick)
Scan the content for topic signal. Pick ONE mood word — derive palette from it. Do not delegate to other skills.
| Topic signal | Mood | Ground | Accent | Notes | |---|---|---|---|---| | AI / dev / tech / agents / coding | editorial | #FFFFFF | #0029FF cobalt | Default. Swiss-print magazine cover. | | finance / markets / earnings / portfolio | bookish | #F5F0E6 plaster | #1A1A2E ink | Book-jacket sobriety. | | sports / playoffs / brackets | signage | #FFFFFF | #FFB300 chrome yellow | Highway-sign bold. | | politics / policy / regulation | mineral | #EDEAE3 limestone | #5C4033 weathered slate | Gravitas without preaching. | | product launch / consumer | highlighter | #FFFFFF | #FFEA00 fluorescent yellow | Buzzy without screaming. | | nightlife / music / entertainment | nocturnal | #1A1A1A wet asphalt | #FF1493 hot pink | Dark mode flips on. | | science / research / data | alpine | #F8FAFC snow | #0F4C5C evergreen | Cold, clear, factual. | | nothing fits | editorial (fall back) | #FFFFFF | #0029FF cobalt | Don't agonize. |
The mood word goes in the eyebrow line of the rendered page (Mood · {mood}). It signals intentionality — the page wasn't templated, it was tuned.
Step 4 — Generate HTML
Write one self-contained file to $OUT_PATH. Use the canonical template below. Substitute {TOKENS}.
Canonical template (single file)
{TITLE} · /html-everything
:root {
--ground: {GROUND};
--ink: {INK};
--accent: {ACCENT};
--mute: {MUTE};
--hair: {HAIR};
--panel: {PANEL};
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--ground); color: var(--ink); }
body { font-family: 'Inter Tight', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
a { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }
.wrap { max-width: 1100px; margin: 0 auto; padding: 80px 64px; display: flex; flex-direction: column; gap: 56px; }
.eyebrow { display: flex; align-items: center; gap: 12px; font-weight: 500; font-size: 11px; letter-spacing: 0.2em; color: var(--mute); text-transform: uppercase; }
.eyebrow .dot { width: 7px; height: 7px; background: var(--accent); border-radius: 50%; display: inline-block; }
h1.display { font-family: 'Archivo Black', system-ui, sans-serif; font-size: 96px; line-height: 92px; letter-spacing: -0.03em; margin: 0; max-width: 18ch; }
h2 { font-family: 'Archivo Black', system-ui, sans-serif; font-size: 36px; line-height: 42px; letter-spacing: -0.02em; margin: 0 0 16px 0; }
h3 { font-family: 'Archivo Black', system-ui, sans-serif; font-size: 22px; line-height: 26px; letter-spacing: -0.01em; margin: 0 0 8px 0; }
p { font-size: 16px; line-height: 24px; margin: 0 0 16px 0; max-width: 70ch; }
ul, ol { padding-left: 24px; }
li { font-size: 16px; line-height: 24px; margin-bottom: 8px; }
code, .mono { font-family: 'JetBrains Mono', monospace; font-size: 14px; }
pre { background: var(--panel); padding: 16px 20px; overflow-x: auto; font-size: 13px; line-height: 20px; }
blockquote { border-left: 4px solid var(--accent); padding: 4px 20px; margin: 16px 0; color: var(--mute); font-style: normal; }
.thesis { display: flex; gap: 0; }
.thesis .strip { width: 6px; background: var(--accent); flex-shrink: 0; }
.thesis .body { padding: 20px 28px; flex: 1; }
.section { padding-top: 24px; border-top: 1px solid var(--hair); }
.card { padding: 24px 0; border-top: 1px solid var(--ink); display: flex; flex-direction: column; gap: 12px; }
.meta-row { display: flex; gap: 24px; align-items: baseline; flex-wrap: wrap; font-family: 'JetBrains Mono', monospace; font-size: 13px; color: var(--mute); }
.grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }
footer { padding-top: 32px; border-top: 2px solid var(--ink); font-size: 13px; color: var(--mute); display: flex; justify-content: space-between; align-items: baseline; gap: 16px; }
@media (max-width: 640px) { .wrap { padding: 40px 24px; gap: 32px; } h1.display { font-size: 56px; line-height: 56px; } .grid { grid-template-columns: 1fr; } }
{EYEBROW}
Mood · {MOOD}
{HEADLINE}
{THESIS_BLOCK}
{BODY_SECTIONS}
Generated by /html-everything · {DATE}
{SOURCE_HINT}
Rendering rules by content type
markdown:
# H1→ `(first one becomes the page headline; subsequent become`)## H2→ `inside a.section`### H3→ `inside a.card`- item/* itemlists → `/`**bold**→ `` (used for headline phrases in lead-in paragraphs)[text](url)→text(preserve exactly)- Raw URLs (lines that ARE just a URL) → wrap in `` and use the domain as link text
> quote→ ``- Code blocks → ``
- Inline `
code→`
json:
- Look for common shapes:
{title, items: [...]},{headline, sections: [...]},{topic, top: [...], clusters: [...]} title/headline/topic→ ``items[]with{title, url, snippet, stats?}→ render as cards in a.gridor vertical stacksections[]with{name, body}→ render as.sectionblocks- Unknown keys: emit as `` definition list under a "Data" section
- Always linkify URL values
key-value / prose:
- First non-empty line → ``
- Subsequent paragraphs → ``
- Bullet-shaped lines → ``
- URLs anywhere → wrap as ``
Link rule (every type)
Anything that matches https?://[^\s)<>"']+ becomes a clickable link. Never emit a bare URL. If the link is in a sentence, link only the URL substring; if the line IS just a URL, replace it with ">domain-and-path-shortened (drop protocol, drop www., keep ~50 chars).
Step 5 — Save + open
# Write the HTML to OUT_PATH (via Write tool, not echo)
# Then:
open "$OUT_PATH" 2>/dev/null || xdg-open "$OUT_PATH" 2>/dev/null || echo "Wrote: $OUT_PATH"
If the user passed --no-open (anywhere in the argument), skip the open.
Step 6 — Reply
Reply with under 150 words:
Rendered →
Mood: · Type:
Sections:
Links: in output>
If links count is zero on input that clearly had URLs, that's a regression — regenerate.
Lightweight rules (non-negotiable)
- Never delegate to
frontend-design,ui-ux-pro-max, or other heavy skills. The template is the design. - Never install packages. No
npm install, nopip install. - Never write a parser script — you (Claude) parse inline.
- One HTML file out per run. No CSS files, no JS files, no images saved separately.
- Don't show the user the raw HTML in chat unless they ask. Just the path + summary.
Secret hygiene
- If
CONTENTcontains anything matching API key shapes (sk_…,xai-…,gho_…,AKIA…,AIza…,-----BEGIN … PRIVATE KEY-----), refuse to render and warn the user. Their input may contain secrets they didn't mean to share. - Never include
.envcontent in output.
Companion skill
If the input is a /last30days or /last72hours raw .md scrape, this skill produces the same shape as iharnoor/last72hours-skill/examples/ai-coding-agents-72h-radar.html. Pipe scrape → render → share.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: iharnoor
- Source: iharnoor/html-everything
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.