Guide
From an HTML export to sign-off
You exported a page. Your client needs to look at it and say yes. Sending a zip means talking somebody through unzipping it; sending a screenshot means they cannot click anything. Publish the export as one link instead: it renders as a real page, your client opens it without an account, and their feedback lands pinned to the spot on the page it is about.
This works with exports from Relume, Claude Design and Claude Code — anything that hands you HTML. HaveTML renders the file; it is not part of those tools and they are not part of it.
01
If your export is one file
A single self-contained .html file — styles in a <style> tag, scripts inline — is the short path. This is what Claude Design and Claude Code usually give you. Two calls:
upload_artifact({ filename: "homepage.html", content: "<!doctype html>…",
title: "Homepage v1", visibility: "unlisted" })
get_artifact({ slug: "a1b2c3d4" })The first publishes it. The second reads the artifact back so you can see visibility: "unlisted" on it before you send the link to anyone — uploads start private, so a link you have not checked may simply not open for your client.
Unlisted means anyone with the link can read it and it stays out of search and off your profile. That is the right level for work in progress: no account needed to look, no chance of it being found by someone you did not send it to.
02
If your export is several files
Many exports are not one file. A site builder hands you markup whose styling lives somewhere else — a stylesheet next to it, a CSS framework loaded from a CDN, images as separate assets. Relume's exports are shaped this way. Published as-is, that markup arrives at your client as an unstyled page, or a blank one.
So inline it first. Ask your agent for one document: the stylesheet copied into a <style> tag, small images as data: URIs, any script inline. Then publish exactly as above.
# to your agent
Inline every stylesheet, script and image into one HTML file,
then upload it to HaveTML as unlisted and give me the link.Two things break a page in a way that is hard to diagnose from the outside, and HaveTML's linter names both on upload:
cross-origin-module— a script loaded from another host. If that host is down or blocks the request, the page renders blank with nothing on it to explain why.insecure-subresource— anhttp://asset on anhttpspage. It is blocked as mixed content, so it never loads for the reader even though it loads for you.
Lint findings come back with the upload and never block it, so you get the link and the warnings together. A CDN tag over https works; it is a dependency on that CDN staying up, which is a trade worth making knowingly.
Size: HaveTML stores up to 50 MB, but publishing over MCP or the REST API hops a serverless function that rejects bodies over 4.5 MB. Inlining large images is what usually crosses that line. Above it, upload from the dashboard instead.
03
Getting the yes
Send the link. A signed-in reader can pin a comment to the part of the page it is about, which is the difference between "the spacing is off" and a note attached to the thing that is off.
When there is an actual question to settle — one hero or three, launch now or after copy review — record it as a decision, so the answer is on the artifact rather than in a thread somebody has to find later.
add_comment({ slug: "a1b2c3d4", body: "Client wants the testimonials above the pricing table." })
create_decision({ slug: "a1b2c3d4", title: "Ship this layout, or revise the hero first?",
context_md: "Client approved the layout. The hero copy is still in review." })Re-upload under the same title when you revise: the link stays the same and the old version stays in the history, so the person you sent it to never needs a second URL.
If you want your agent to do all of this without you reading this page, the same sequence is in the HaveTML agent skill as a worked example.
Publish your next export
Free to start. Unlisted links, pinned comments and version history are on every plan.
Create a free accountRelume is a trademark of its owners; no endorsement implied. Claude and Claude Code are trademarks of Anthropic; no endorsement implied.