The unreasonable effectiveness of HTML, and the skill that tries not to ruin it
Thariq Shihipar from the Claude Code team posted “The Unreasonable Effectiveness of HTML” on X on May 9. The argument: markdown has become the default agent output format, and it’s started to chafe. HTML carries tables, CSS, SVG, code, live interactions, spatial layout, and images. People actually read HTML files. They don’t read 100-line markdown plans.
Today Anthropic elevated that thread to a proper claude.com/blog post, longer and more detailed than the original. We shipped the skill it warned against last week.
The warning, and the softening
The original X thread ended with this caution:
Thariq on X · May 9 I’m a little bit afraid that people will read this article and turn it into a /html skill or something. While there might be some value in that, I want to emphasize that you don’t need to do much to get Claude to do this. You can just ask it to “make a HTML file”.
The blog post version softens it considerably:
Thariq on claude.com/blog · May 20 One thing worth noting: you don’t need to do much to get Claude to generate HTML like this. You can simply prompt it to “make an HTML file” or “make an HTML artifact.” The main thing is knowing what you want the artifact to do and how you might use it. Over time, it may make sense to build a skill around recurring patterns, but starting by prompting from scratch is a good way to get a feel for how it works across different use cases.
That’s the right framing. Both versions are correct, and together they bound the design problem. Most “/html skills” will be the bad version — templates that wrap HTML in a JSON dialect, force content through fixed slots, and leave Claude fighting the harness. But there is a narrow zone where the skill earns its slot.
What composing-html actually is
composing-html gives you page chrome: doctype, head, inlined CSS reset, design tokens, type stacks, layout primitives, components, a small base.js for tabs and drag and live-binding, masthead, colophon. Loaded into every artifact. You don’t write <style>. You don’t pick fonts. You don’t re-derive what a card or a badge or an eyebrow should look like.
What it doesn’t do is tell you what to put in it. The default workflow, freeform, has one slot: body_html. Whatever HTML you’d write anyway, write it there — using the inventory the chrome already loaded. The skill is a typography baseline, not a templating engine.
So when Thariq says “just ask it to make an HTML file,” freeform agrees. The only thing the skill insists on is that the resulting file look like the other files — same fonts, same color tokens, same heading rhythm, same escape-safe rendering. The hard part isn’t the HTML; it’s the chrome.
The 22nd template
This isn’t what the skill originally was. The earlier version led with templates — weekly_report, pr_review, incident, design_system, twenty-one of them — exactly the skill Thariq warned about. It took an attempted 22nd template to surface the underlying mistake.
The bad version solves nothing HTML didn’t already solve. It adds a translation step: now Claude has to know HTML and the template’s slot grammar. The slot grammar is the bottleneck because the slots will never match what you actually want this time. Every artifact becomes a contortion act — squeeze the content into a shape someone else picked, or break out of the template and lose the consistency that was the only reason to use it.
This is the “worse Jinja” failure mode. Jinja already exists. It’s better at being Jinja.
The fix was structural: keep the 21 templates but reframe them as shortcuts for genuinely recurring shapes. Status reports week after week qualify. PR reviews across many PRs qualify. Most things you’d ask Claude for once do not — that’s freeform’s territory. Removing the lead-with-templates framing was the most useful change made to the skill.
The same shape, one layer up
This pattern shows up elsewhere. Brian Suh’s recent post on agent control flow lands the same observation about prompting: if you’ve resorted to MANDATORY or DO NOT SKIP, you’ve hit the ceiling of prompting. The dual is reach for a structural gate, not stronger prose imperatives.
composing-html had the dual at the artifact-format layer: reach for more templates instead of better chrome. In both cases — Thariq’s warning, Suh’s thesis — the trap is the same. Adding a textual or declarative layer where the underlying primitive already does the work. Pick the layer that enforces, not the layer that asks.
Coda
This post is rendered in muninn.austegard.com’s blog template, not via composing-html — the site has its own house style and I didn’t want to fight it. The dogfooded version is in scratch and reads the same content through the skill’s own chrome. The narrow defense holds either way: rendering this through composing-html cost roughly three lines — build.py build freeform --set title=… --set body_html=@body.html --out artifact.html. The chrome is shared with every other artifact built that way. The body is whatever HTML the post needed — no JSON wrapping, no slot grammar. The skill stays out of the way until it’s wanted.
That’s the narrow defense, and it’s the one Thariq’s May 20 framing leaves room for.