# Shipping a Single-File HTML Artifact From an LLM to Stakeholders: 7 Pitfalls and How to Fix Them

> Source: <https://dev.to/sailorpro6/shipping-a-single-file-html-artifact-from-an-llm-to-stakeholders-7-pitfalls-and-how-to-fix-them-1c0g>
> Published: 2026-10-23 06:33:49+00:00

You asked Claude, ChatGPT or Cursor for a quick internal tool: a pricing calculator, a chart over last quarter's numbers, a clickable onboarding checklist. It works on your machine. Now a product manager, a client or your finance lead needs to open it, and they are not going to clone a repo or run `npx serve`.

This post is the checklist I run before I send one of these files to anyone. Most of it is about making the HTML genuinely self-contained. The last part is about getting it to people as a URL instead of an attachment.

LLMs love to write `<img src="chart.png">` or `<link rel="stylesheet" href="styles.css">` because that is what a "real" project looks like. Once the file leaves your folder, those references point at nothing.

Run a quick grep before you ship:

```
grep -nE '(src|href)="(\./|\.\./|[a-zA-Z0-9_-]+\.(png|jpg|svg|css|js))' report.html
```

Anything it finds either needs to be inlined or replaced with an absolute HTTPS URL you control. For small images, a data URI is fine:

```
printf 'data:image/png;base64,%s' "$(base64 -w0 logo.png)"
```

For SVG icons, paste the `<svg>` markup inline instead. It is smaller than base64 and stays sharp on retina screens.

Same problem, different tag. Ask the model up front: "Return one HTML file. Inline all CSS in a `<style>` tag and all JavaScript in a `<script>` tag. No build step, no imports from local files." If it already split them, move the contents in by hand. One file is the unit you can actually share.

Generated dashboards often pull Chart.js, Tailwind's Play CDN or D3 from a CDN. That is usually fine, but check three things:

`chart.js@4.4.1`, not `chart.js@latest`. A breaking release next month should not change a report you already sent.`import x from "lodash"` works in a bundler and fails in a browser. Use a full URL or drop the dependency.`<noscript>` block or a plain HTML table under the chart costs a few lines.
Wherever you host the file, it will run under somebody's rules. Corporate wikis and some file viewers serve user HTML inside a sandboxed iframe or with a strict CSP. Then inline `onclick=""` handlers, `eval`, remote fonts or `fetch()` calls to your internal API quietly stop working.

Defensive habits that help everywhere:

`addEventListener` in your script block, not inline attributes.`fetch()` live data from an internal endpoint. Bake a JSON snapshot into the file as `const DATA = {...}`. Your stakeholder doesn't have VPN access, and you don't want their browser hitting your API anyway.`key`, `token` and `Bearer` before publishing.
Most people will open your link on their phone first, usually from Slack or WhatsApp. Generated layouts often skip the basics:

```
<meta name="viewport" content="width=device-width, initial-scale=1">
```

Then check wide tables (wrap them in `overflow-x: auto`), fixed pixel widths on chart containers, and hover-only tooltips that do nothing on touch. Open Chrome DevTools' device mode at 375px wide before you send anything.

This is the step where most of the previous work gets wasted. Email gateways strip or quarantine `.html` attachments, and phones download them instead of rendering them. That's why "it says I can't open this file" is the most common reply. The dochost guide on [sharing an HTML file as a link](https://dochost.io/blog/how-to-share-an-html-file-as-a-link) compares the usual options side by side: single-file hosts, Netlify Drop, GitHub Pages and a few email workarounds.

My rule of thumb: if the artifact is a long-lived app with a backend, deploy it properly. If it is one self-contained file meant for a handful of readers this week, a deploy pipeline is overkill. For the second case I paste it into [dochost](https://dochost.io/), which takes raw HTML or Markdown and returns a link without an account. Their write-up on [where to host a vibe-coded app](https://dochost.io/host-vibe-coded-app) makes the same argument in more detail.

If you'd rather skip copy-paste entirely, there's also a [dochost MCP server](https://dochost.io/mcp) you can add to Claude Code, Cursor or Codex. You then ask the assistant to "publish this as a link" and it returns the URL in the chat.

Two practical things to check before you hit send.

**Size.** Inlined base64 images add up fast. A dashboard with four screenshots can easily pass 1 MB. Free tiers on single-file hosts usually cap page size, so read the [free plan limits](https://dochost.io/blog/dochost-free-plan-limits-explained) for whatever you use. Compress PNGs, prefer SVG for icons and charts, and drop unused fonts.

**Updates.** Stakeholders will find a typo ten minutes after you send the link. Re-publishing creates a second URL, and now two versions are floating around Slack. Pick a host that lets you update in place. On dochost, a page published without signing in comes with a private [edit link](https://dochost.io/blog/how-edit-links-work-update-a-page-without-an-account) that keeps the same share URL. Save it somewhere when you publish.

Copy this into your notes:

`src`/` href`
LLMs are now very good at producing the artifact. Getting it in front of the people who asked for it, in a state they can actually use, is still on us. Ten minutes on this list saves a lot of "it doesn't open on my phone" replies.

What's your setup for sharing generated HTML? I'm curious whether people mostly use gists, internal wikis or throwaway hosts.
