<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: nullarch</title>
    <description>The latest articles on DEV Community by nullarch (@nullarch).</description>
    <link>https://dev.to/nullarch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3975321%2F7cba23cc-f621-469d-a0b0-3ef1e6829120.png</url>
      <title>DEV Community: nullarch</title>
      <link>https://dev.to/nullarch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nullarch"/>
    <language>en</language>
    <item>
      <title>htmlbook: a shelf for the HTML your AI agent writes</title>
      <dc:creator>nullarch</dc:creator>
      <pubDate>Wed, 10 Jun 2026 13:04:20 +0000</pubDate>
      <link>https://dev.to/nullarch/htmlbook-a-shelf-for-the-html-your-ai-agent-writes-2mip</link>
      <guid>https://dev.to/nullarch/htmlbook-a-shelf-for-the-html-your-ai-agent-writes-2mip</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; — Coding agents (Claude Code, Cursor, Codex) now write genuinely good HTML: reports, dashboards, specs. But that HTML ends up stranded in a project folder — you can't read it on your phone, and sharing it means a screenshot or a print-to-PDF. So I built &lt;a href="https://htmlbook.io" rel="noopener noreferrer"&gt;&lt;strong&gt;htmlbook&lt;/strong&gt;&lt;/a&gt;, an MCP-native shelf where your agent &lt;em&gt;pushes&lt;/em&gt; an HTML doc and it becomes a themed, shareable page. Here's the idea — and how it's built.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem nobody talks about
&lt;/h2&gt;

&lt;p&gt;You ask Claude Code for a "Q3 revenue dashboard," or you have it write up an incident postmortem. It hands you a clean, self-contained HTML file. It looks great in your browser.&lt;/p&gt;

&lt;p&gt;And then it just... sits there.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It lives at &lt;code&gt;~/projects/acme/reports/q3.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can't open it on your phone.&lt;/li&gt;
&lt;li&gt;To show a teammate you screenshot it, print it to PDF, or paste it into Notion — throwing away the layout and the interactivity every single time.&lt;/li&gt;
&lt;li&gt;Next week you can't find it. Or it's gone with the chat session that made it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The HTML is good. The &lt;strong&gt;storage story&lt;/strong&gt; is broken. We got really good at &lt;em&gt;generating&lt;/em&gt; documents with AI and never figured out where they should &lt;em&gt;live&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;htmlbook is a bookshelf for AI-generated HTML. Three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Your agent pushes a doc&lt;/strong&gt; — over MCP (one line) or a REST API key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It lands on a shelf&lt;/strong&gt; — auto-organized by project, re-themed for reading, every version kept.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You read &amp;amp; share it&lt;/strong&gt; — responsive on any device; flip it to public for a short link anyone can open.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjxtqnhpfpv5nzy3ablz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftjxtqnhpfpv5nzy3ablz.png" alt="push to shelf to share — the three-step flow" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The deliberate constraint: &lt;strong&gt;the website is read-only.&lt;/strong&gt; The &lt;em&gt;only&lt;/em&gt; way to create a document is the agent push. You never paste HTML into a web form — authoring stays in your agent, where the work already happens. The web app exists to read, organize, and share.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting is genuinely one line
&lt;/h2&gt;

&lt;p&gt;For an MCP client like Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http htmlbook https://htmlbook.io/api/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you just talk to your agent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Clean up that quarterly report and put it on my shelf."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It calls the &lt;code&gt;publish&lt;/code&gt; tool and hands you back a link. Cursor and Codex connect the same way with an API key; claude.ai and Claude Desktop connect over OAuth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reading trick: documents with no CSS
&lt;/h2&gt;

&lt;p&gt;This is the part I'm happiest with.&lt;/p&gt;

&lt;p&gt;A document you push (an "hb-doc") carries &lt;strong&gt;no CSS of its own&lt;/strong&gt; — it's just semantic HTML. That's the whole trick: because the document has no styles, the reader can re-theme it freely — paper, sepia, dark, adjustable width and font size — the way an e-reader reflows a book. Same document, three skins:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb02lwdi658rhaotd532.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb02lwdi658rhaotd532.png" alt="the same document in paper, sepia, and dark themes" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you push a page that &lt;em&gt;does&lt;/em&gt; ship its own CSS and JS — a custom interactive thing? htmlbook detects that, stores it &lt;strong&gt;verbatim&lt;/strong&gt;, and renders it in a sandboxed iframe so it keeps its exact look without touching the rest of the site. So &lt;em&gt;any&lt;/em&gt; HTML your agent makes has a home: simple docs become themeable, self-contained pages stay pixel-perfect.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it's built (for the curious)
&lt;/h2&gt;

&lt;p&gt;A few decisions other devs might find interesting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remote MCP server&lt;/strong&gt; at &lt;code&gt;/api/mcp&lt;/code&gt; with &lt;strong&gt;two auth modes&lt;/strong&gt;: a static API key (for Claude Code / Cursor / Codex) and a self-hosted &lt;strong&gt;OAuth 2.1&lt;/strong&gt; authorization server (for claude.ai / Claude Desktop, which &lt;em&gt;require&lt;/em&gt; OAuth, not keys). The OAuth side bridges the existing login instead of standing up a second user system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage split&lt;/strong&gt;: metadata in Firestore, document &lt;strong&gt;bodies in Cloudflare R2&lt;/strong&gt;, keyed by version so every version is immutable. Public docs are mirrored to an edge path for fast, egress-free serving.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security is not optional here&lt;/strong&gt;: the reader injects document HTML &lt;em&gt;same-origin&lt;/em&gt;, so every pushed hb-doc is &lt;strong&gt;sanitized on ingest&lt;/strong&gt; (tag/attribute allowlist) and the whole app runs a &lt;strong&gt;nonce-based CSP&lt;/strong&gt; (no &lt;code&gt;unsafe-inline&lt;/code&gt; scripts). Bundles get the opaque-origin sandbox instead, so they can't reach the app's DOM or cookies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack&lt;/strong&gt;: Next.js (App Router) + React 19 on Vercel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is visible to the person using it — they just say "shelve this" and get a link. But that's kind of the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;It's free to start — sign up and you get a library and an API key immediately. Connect your agent and ask it to publish something you made this week.&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;&lt;a href="https://htmlbook.io" rel="noopener noreferrer"&gt;htmlbook.io&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(There's even an &lt;a href="https://htmlbook.io/llms.txt" rel="noopener noreferrer"&gt;llms.txt&lt;/a&gt; if your agent wants to read up on it first. 🙂)&lt;/p&gt;

&lt;p&gt;I'd love feedback from people doing a lot of agent-assisted work: once a doc is &lt;em&gt;on a shelf&lt;/em&gt;, what would you want your AI to be able to &lt;strong&gt;do&lt;/strong&gt; with it next? Drop a comment, or come say hi in &lt;a href="https://discord.gg/hqMkDFPR" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>mcp</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
