Back to Hub
NO-SERVER ARCHITECTURE •
By Yash Panchal · Last updated:

Export to ZIP: From Browser Session to Deployed Site

There is a moment every browser-IDE demo has to survive: the user finishes something they like, and then asks, "Okay — but how do I get it out?"

A share link is not an answer to that question. A link is a demo. A ZIP file is a project you own: a folder you can unzip, open, edit in any editor, hand to a client, or drop onto a static host. NitroIDE's Download ZIP button is the bridge between a browser session and a deployed site, and it is worth explaining properly — including the week it silently broke, and why.

What the button actually does

NitroIDE's workspace is three files: index.html, style.css and script.js. Download ZIP takes exactly those files, exactly as they are in your session, and packs them into one archive — in your browser, with JSZip. Nothing is uploaded to be zipped. The archive is built on your machine and handed straight to your downloads folder.

That matters for two reasons. First, the export is private by the same architecture as the rest of the tool: there is no server round-trip to intercept, log, or fail. Second, the output is boring in the best way. It is a plain folder of web files. Unzip it and open index.html, and your site runs. There is no NitroIDE runtime to install, no export format to decode, no lock-in hiding inside the archive. The other direction works too: Import ZIP / Files (or dropping a ZIP onto the editor) brings a project back into the browser, so the ZIP is a round trip, not a one-way exit.

From ZIP to a live URL, in three moves

The path from session to deployed site is deliberately short:

  1. Build in the browser until the preview looks right. The preview is the site — same files, same rendering — so there is no "works in the IDE, breaks on deploy" translation step for plain HTML, CSS and JS.
  2. Hit Download ZIP. You now own the site as a folder.
  3. Put that folder on any static host. Drag it into Netlify Drop, push it to a GitHub Pages repo, or serve it from any static file host. There is no build step to configure, because there is nothing to build.

One honest caveat belongs in step 1: if your project pulls in a CDN library mid-session (Tailwind, a font, a chart library), the exported files still reference that CDN. The ZIP is self-contained for your code, not for third-party code you linked to — the deployed site still needs an internet connection to fetch those links. That is a property of linking CDNs, not of the export, but it is the kind of thing that surprises someone at deploy time if nobody says it.

The week the button silently did nothing

This feature earned its place in this article the hard way. Recently, Download ZIP broke — and it broke quietly. Clicking it produced no file, no error, and no visible failure. Cache purges and fresh devices changed nothing, which is usually the sign that the bug is not where you are looking.

The real cause was a loader collision, not a ZIP bug. JSZip's UMD wrapper saw Monaco's AMD loader and registered itself as an anonymous AMD module instead of setting window.JSZip. The library file downloaded fine; the global the download code looked for was simply never defined. The fix was ordering plus a guard: load JSZip before the Monaco loader, and shield the loader while JSZip evaluates, so it registers the way the rest of the code expects. It shipped, was verified live, and was confirmed working the same morning — the saga is closed, and the lesson is the one this whole series keeps re-teaching: when a feature fails silently, suspect the wiring between two libraries before you suspect either library.

What a ZIP is not

A ZIP is a snapshot, and snapshots go stale. Export on Tuesday, keep editing in the browser until Friday, and the Friday work is not in the Tuesday archive — there is no live sync between a downloaded folder and your browser session, because there is no server keeping them in sync. Treat the export like a release: export when a version is done, name the file by version if it helps, and re-export when the next version is done.

That is also why the ZIP and the share link are different tools, not two names for the same thing. The share link is for showing: one URL, one running demo, rebuilt in the reader's browser. The ZIP is for owning: a folder you can deploy, archive, or hand over. Use the link when you want someone to see it now; use the ZIP when you want someone — including future you — to have it forever.

Why export is a feature, not an escape hatch

Some tools treat export as an apology: sorry you want to leave, here is your data. I see it the other way around. A tool that refuses to let your work out is a tool you should not trust with your work in the first place. The export button is what makes the no-server, no-account story honest. Your projects live in your browser, and when you want them anywhere else, one click turns them into ordinary files that any host, editor, or teammate can use — no account to close, no dashboard to beg, no format to convert.

Build it in the browser. Own it as a folder. Deploy it anywhere. That is the whole pipeline, and it fits in one click.

Try it

I build NitroIDE — a browser-based IDE where your code never leaves your machine: nitroide.com

⭐ If you enjoyed this, star NitroIDE on GitHub: github.com/nitroideofficial/nitroide

Frequently asked questions

What files does NitroIDE's Download ZIP include?

Exactly the three workspace files as they are in your session: index.html, style.css and script.js. The archive is built in your browser with JSZip — nothing is uploaded to be zipped.

Will a site exported as a ZIP work without an internet connection?

Your own code will. But if your project links a third-party library from a CDN mid-session, the exported files still reference that CDN, so the deployed site needs an internet connection to fetch those links.

Why did Download ZIP once stop working silently?

JSZip's UMD wrapper saw Monaco's AMD loader and registered itself as an anonymous AMD module instead of setting window.JSZip, so the download code's global was never defined. The fix loads JSZip before the Monaco loader and shields the loader while JSZip evaluates.