Cursor builds projects as folders of linked files, not one shareable artifact. Three reliable ways to collapse a Cursor build into a single self-contained HTML you can drop on a private link — and the one case where you deploy instead.
The page works in Cursor. The preview pane shows it, the form submits, the chart redraws. So you grab the file, send it to the person who asked, and they reply with a screenshot of a blank page and broken styling.
Nothing is wrong with your code. The problem is shape. Cursor, like every serious dev tool, writes a project as a folder of files that point at each other — and "point at each other" only holds while the files sit in the same folder, on a machine with a dev server running. The instant one file travels alone, every pointer dangles. That gap between "renders in my editor" and "renders for them" is the whole subject here.
Getting one shareable artifact out of Cursor isn't a single trick. It depends entirely on which of three shapes your project is in. Figure out the shape first; the route follows from it.
Open your project folder and look at the root.
index.html, maybe a style.css and a script.js, a few image files. No package.json, no node_modules. The browser can already run these files directly.package.json, a node_modules/, a vite.config or next.config or astro.config, source in src/. The browser cannot run this raw — it's JSX, TypeScript, imports — it has to be built first.These aren't subtle distinctions, and they decide everything. Don't guess — look.
This is the easy one, and Cursor's chat does the work. Your files are browser-ready; they're just scattered. You want them folded into a single file that carries its own dependencies.
Open the Cursor chat with your index.html in context and ask for exactly this:
Collapse this into a single self-contained
index.html. Inline the contents of every linked stylesheet into a<style>block, every linked script into a<script>block, and replace any external font or CDN library with an inlined or system-stack equivalent. Base64-embed local images. Hardcode any data that's currently fetched. The output must have zero external references — scan it and confirm none remain.
That last clause matters. Cursor will happily inline the obvious things and leave one CDN <link> or a fetch() to your dev server behind. Asking it to scan and confirm turns a 90%-done file into a done one. When it finishes, do a five-second check yourself: search the file for http, src=, href=, and fetch(. Anything pointing outward is a future broken page on someone else's network.
The result is one .html that opens the same on a flight, on hotel Wi-Fi, or off a phone with the CDN blocked. That's the property you're buying: it works wherever it lands.
.html, one private link. The viewer needs no account, and it's unindexed by default.Vite, Next (static), Astro, SvelteKit — these keep your source in a form the browser can't run. You have to run the build that turns source into plain HTML/CSS/JS.
In Cursor's terminal:
npm install
npm run build
What lands depends on the framework: Vite and Astro write a dist/ folder, a Next static export writes out/. Inside is real, browser-ready output — but it's still modular: a slim index.html linking to hashed assets/ files. Double-click dist/index.html to open it directly and it'll often look broken, because the links are absolute paths expecting a web root, not a desktop. That's normal. This folder is meant to be served, not opened.
From here you have two honest options.
Zip the folder. Compress dist/ (or out/) into a single .zip. A static host unpacks it and serves index.html with every link intact and resolving. This keeps the build's natural structure and is the right call for a heavier app — many routes, lots of assets, a real bundle. You're not fighting the framework; you're shipping exactly what it produced.
Or fold it to one file. If the build is essentially one page, ask Cursor to bundle the entry HTML and its hashed assets into a single inlined .html, same instruction as Shape 1. Lighter to send, and it'll open from a local download too. For a one-page Cursor calculator, dashboard, or report this reads cleaner than a zip.
Rule of thumb: one page leans single-file, a multi-route app leans zipped folder. Both are self-contained; they just carry their weight differently.
If your Cursor project has API routes, a database it writes to, a login flow, or server rendering at request time, stop trying to make it a file. You can't. A database query and an auth check are code that runs on a server — and a single HTML file has no server, nor does any static host.
This is the honest boundary, and naming it plainly saves you an afternoon: a Cursor app with a live backend belongs on a platform that runs your server. Vercel and Netlify are built for exactly this, and you should use them rather than bending a static host into a shape it can't hold. Sharing a Cursor build as a static link is the other half of the same decision — knowing which half you're in is the point.
Where a static private link does fit, even here, is the front-end slice. Plenty of "backend" Cursor projects are really a self-contained front end that talks to a third-party API from the browser — Supabase, an LLM endpoint, Stripe's client SDK. If nothing on your server runs, that's Shape 1 or 2 wearing a backend's clothes: build it, inline it, share the file. The test is narrow and unforgiving — does code you wrote execute on a server when the page loads? If no, it's static. If yes, deploy.
You now have one of two things: a single .html, or a clean dist/ you can zip. Either is a self-contained artifact, which means it's ready for a private link.
Drop the file, get back an unguessable URL that renders in any browser. The viewer needs no account, no install, no sign-up — they open the link, the page is there. Private and hidden from search by default; you can layer a password or set an expiry on top when the work is sensitive or time-boxed.
And because the artifact is self-contained, the link is durable. It doesn't break when you close Cursor, doesn't drag your prompt history along, doesn't tie the viewer to an account on the tool that built it. The page outlives the project — which is the whole point of getting it out of the folder in the first place. If you're weighing where it should live longer-term, the use-case index maps each shape to the right home.
Identify the shape, produce the artifact, drop the link. Three steps, and the one that trips people is the first — so look at your project root before you do anything else.
Bolt.new previews live behind a session URL that changes and can lapse. How to pull a static export — one HTML file or a built dist folder — out of Bolt and turn it into one stable, private link.
Client-side encryption tools turn your page into an encrypted file, so the protection and the artifact are the same object — every edit means re-running the tool and re-uploading. What that actually costs, the salt setting that decides whether your old share links survive, and when a hosted password is the better trade.
Running the studio out of one folder per client is a good structure for making the work. It stops at the point where the client has to open it — a private repo needs a GitHub account, and Pages built from one is public by default. What the handover step actually needs, and how to add it without breaking the folder.
miinideck turns a single HTML file into an unguessable link with optional password and expiry. Default-private, never indexed.