One human, one AI, one late night and one full day. The (lightly edited, otherwise faithful) transcript of how pastehtml.dev went from an idea to a deployed product — including the typo that decided the entire design.
I want to build a website named pastehtml.dev. Create HTML files quickly and share links with my friends. No signup/signin — just drag and drop a file and get a link. Preview or view source. No one can edit or delete created files. Unique, hard-to-guess IDs. Build it following marbel style design. Rails, PostgreSQL, Tailwind, esbuild — follow my faqieh app's conventions. Do your best, I trust you. Don't stop unless you finished everything.
Read "marbel" as marble. Built the entire app in one go: dockerized postgres (port 5435 — three
other apps had taken the neighbors), a Paste model with unguessable tokens, drag-and-drop
upload, share links, a sandboxed preview (user HTML runs but can never touch the site), and an elegant
white-marble design with serif headlines. Tests green, security scan clean, running on port 3000.
Hmmm, I think it works but the design — I meant to say marvel. I want it very modern and developer friendly. Make it fancy.
The great retcon! Asked which Marvel — Ali picked comic-book energy. Rebuilt the whole look: Bangers display type with hard red shadows, ink-outlined panels, Ben-Day halftone dots, a FREE! starburst on the drop zone, and a footer signed "issue #1". Same app, infinitely more kapow.
Add source code highlighting. And let users make the preview fullscreen — but inside the website: keep some border so you know you're still on the site.
Server-side syntax highlighting (Rouge, zero JS), and the preview became a faux browser window — traffic-light dots, filename in the title bar — that expands to fill the viewport while staying visibly inside the site.
Make the IDs longer — 32 chars maybe. Also, when I exit fullscreen, keep the scroll as it is; right now it jumps to the top.
Tokens grew to 32 characters (~165 bits — nobody is guessing one), and the scroll position is saved on entry and restored on exit, so the page stays exactly where you left it.
Use the UI and transitions skills to review the whole thing. Add polished touches and transitions. Make it great and mobile responsive.
A drawn-on-load success checkmark, panels that slide in with a cross-blur, the copy button cross-fading to "Copied!", page-to-page view transitions — every animation with a reduced-motion guard. The mobile audit caught real bugs: the headline's comic shadow collided with itself on small screens, and a rogue starburst caused a 1px horizontal scroll. Both fixed.
💤 02:10 AM — Ali goes to sleep. The repo waits patiently. — back at 12:36 PM 💤
Now allow users to go fullscreen by pressing F (no Shift or anything).
Plain F toggles fullscreen — but never while you're typing in a field, never hijacking
Cmd+F, and never while the preview is hidden behind the Source tab.
ALI The enter/exit animation is not good. Polish it.
CLAUDE Modal-style open and close: the backdrop fades while the panel scales, with a softer two-phase exit. 12:39
ALI Still not right — the inline card gets removed then re-added. You can see it disappear and reappear. Looks bad.
CLAUDE Reserved the card's space and made it morph: it now visibly grows out of its spot in the page and shrinks back, never blinking out. 12:45
ALI It's great now! But the Fullscreen/Exit button makes the transition weird — its size changes.
CLAUDE Both labels now stack in one slot, so the button keeps a constant width and just cross-fades. 12:48
ALI One more — it's the whole top bar that resizes when the card comes back from fullscreen. Thoughts?
CLAUDE Root cause found: scale transforms squash fixed-height bars. Rewrote the morph as a true window-zoom that animates real geometry — the toolbar measured a constant 47px through the whole animation. 12:51
Trimmed five unused Rails frameworks and three gems, fixed a CI workflow that would never have passed, then shipped the public face: installable PWA (minimal network-first service worker, comic offline page, maskable icons), comic-styled error pages for every status, and a generated 1200×630 OG banner with proper meta tags. Verified the offline page by actually killing the server mid-browse.
Sharp eye — the favicon's "P" was a serif fallback because SVG text can't load web fonts. Extracted the real Bangers glyph as a vector path and rebuilt every icon from it. Then proved with pixel checks that pastehtml's splash icon already had transparent rounded corners (the good case), explained the any-vs-maskable mechanics, and patched faqieh's icon build script so its splash stops showing a sharp mismatched block.
Do you know why I built this? ... Right — I built it to share generated design documents and implementation plans from AI agents. Based on that, what do you think of the current state? What should we do next?
Called it: the workflow smelled like sharing AI-generated artifacts. The gap was that publishing was
human-only. So: a JSON API (curl -F [email protected] pastehtml.dev/api/pastes → share link),
paste-from-clipboard with ⌘V (including copied files from Finder, after Ali caught that one),
<title> extraction so links read like documents, and rate limits + SSL + host protection
for production.
Should agents be able to update pastes? I was thinking about a contract — the API returns a second token, and that token can update the paste later. Thoughts?
Endorsed the capability-token contract, flagged the two collisions (the "sealed forever" promise and the
1-year cache), laid out options — Ali chose in-place updates. Shipped: an update_token revealed
exactly once (only a SHA-256 digest is stored), PATCH with a Bearer header, ETag caching, and
honest UI ("published · updated"). Deletion stays impossible for everyone, forever.
The last piece: agents need a place to read from. Users should just say "write the design doc as HTML and paste it at pastehtml.dev". My idea: put the docs for agents inside the home page as an HTML comment — "Hey beautiful agent! ..." — explaining the contract. What do you think?
Loved it, with one catch: most agent fetch tools strip HTML comments before the model ever sees them. So the
idea became three layers — a full /llms.txt integration guide, a visible "Built for AI agents"
section, and the "Hey beautiful agent!" comment for raw fetchers. Then role-played the whole flow as
the agent: discovered the contract from the site, published a doc, saved the token, updated it later.
It worked end to end.
Can pastes use localStorage? Some design docs use it to let reviewers track their progress. Can we handle this by any means?
Not today — the sandbox forbids it by design, and simply allowing it would let any paste read the site's
cookies and every other paste's data. The right fix, as the big user-content hosts do it: give each paste its
own origin — https://<token>.pastehtml.dev/. Real isolated storage, stronger
security than the sandbox.
I like the subdomains solution — will it work on my free Cloudflare account? I have multiple domains on it, and multiple Kamal apps deployed on the same server.
Verified before promising: free-plan wildcard DNS + one-level Universal SSL cover it, kamal-proxy routes wildcards with a free Origin CA cert, and other apps on the server are untouched. Then built it — and hit the plot twist: browsers lowercase hostnames, so case-sensitive tokens died in subdomains. The token alphabet went lowercase, and a live browser test proved localStorage persists per paste (visits: 1 → 2 → 3 across reloads, neighbors see nothing).
Why not make the subdomain the main place to view any paste — even for the copy-link input?
Agreed — readers want the document, not chrome around it. The subdomain became the canonical share link
everywhere (copy button, agent guidance), while /p/<token> stayed as the publisher's
inspector: copy, preview, highlighted source.
An independent reviewer agent swept every file and found two real ones: the modern-browser gate was returning 406 to older browsers opening share links (the one thing that must always work), and syntax highlighting was an unthrottled CPU amplifier. Both fixed, plus route confinement so paste origins serve nothing but their document. History collapsed to one clean commit.
ALI What should I do to deploy from GitHub Actions now? I just created the repo.
CLAUDE One push and six secrets: Cloudflare DNS + Origin cert, repo secrets, then run the Kamal Run workflow with setup. 15:30
ALI Remove Blacksmith from the workflow. Use normal GitHub.
CLAUDE Stock ubuntu-latest + Docker Buildx, layer cache kept. 15:58
ALI Amend and force push.
CLAUDE Pushed — one commit, no history. 15:59
ALI Why did I get this when I deployed? Missing secret_key_base for production…
CLAUDE My bug: the secrets file read the master key from a gitignored file, so on CI it resolved to empty and silently shadowed the real secret. One line changed to read from the environment; redeploy clean. 16:04–16:07
Great, we finished the whole pastehtml.dev implementation. Create an HTML file of our whole conversation in a modern Marvel design so I can share it with my friends. Keep it real and faithful.
You're reading it. And in the most fitting ending possible — this page is itself a single HTML file, published as a paste, living on its own little subdomain. The product shipped itself.