hosting
How to Host a ZIP File as a Website
By PreviewSend Team · Jul 14, 2026 · 9 min read

A ZIP lands in your downloads and now you're stuck. Maybe it's a dist folder from a build, a single HTML page a chatbot wrote for you, or a template you bought that shipped as an archive. The files themselves are finished. What's missing is a URL, somewhere those files can live so you can send a link instead of an attachment nobody can open.
A ZIP of static files is one of the simpler things to host. Problems usually come from the archive layout or from asset paths, and both are easier to fix before you upload.
What counts as a static site
A static site is any site a server can hand over as-is, without running code to build the page first. Open the archive. If you see .html, .css, .js, images, and fonts, with nothing that expects a database or running backend, you have a static site.
Most modern web projects end up here even when they didn't start that way. A React or Vue app compiles down to static files. A framework like Vite, Astro, or Next.js in export mode produces a folder of HTML and bundled JavaScript. The app still does plenty in the browser, but the hosting is dumb: fetch file, return file. That's why a ZIP is enough.
Anything that runs on the server per request is not static. That includes a PHP app, a Rails backend, a Node server that renders pages on the fly, or an app whose database lives on the same box. Those need a runtime, not a file host. A static frontend can still call a separately hosted API. If you're not sure which side of the line your project falls on, the static-versus-dynamic test sorts a project's features into browser work and server work before you upload.
Get the ZIP structure right
The safest layout puts index.html at the root of the archive. PreviewSend can fall back to the shallowest nested copy, but many hosts expect it at the top.
When a host unzips your file, it looks for index.html to know what to serve at /. If the archive contains my-site/index.html instead of a root-level index.html, some hosts find a wrapper folder but no entry point. They may reject it or serve a directory listing. If an upload has already failed that way, diagnosing a missing index.html in a ZIP walks through spotting the cause and rebuilding the archive.
This is the number-one gotcha because of how the OS "Compress" command works. Right-click a folder and compress it, and you get an archive containing that folder. What you want instead is to open the folder, select everything inside, and compress the selection:
cd dist
zip -r ../site.zip .
The . means "the contents of this directory," so index.html lands at the top of site.zip. On macOS or Windows, do the equivalent: enter the folder, select all, then Compress or Send to → Compressed folder.

Some hosts, PreviewSend included, will rescue a nested index.html. We confirmed this against
PreviewSend's parser (src/lib/zip.ts): it prefers a root-level index.html and otherwise falls
back to the shallowest one anywhere in the archive. That is a useful safety net, but zipping the
contents directly offers the broadest host compatibility, so don't build a habit on the fallback.
Where the build output actually is
If you built the site yourself, zip the compiled output rather than the source code. Different tools put that output in different folders, which is why zipping the project root can leave a host staring at raw .jsx files.
The common ones:
dist/: Vite's default build output, and Astro's too. On Vite, building and uploading that dist folder without Git is the full walkthrough; on Astro, hosting the dist folder covers the static-versus-on-demand check first.build/: Create React App and some others.out/: Next.js static export; hosting a Next.js static export covers theoutput: 'export'switch and the image and dynamic-route checks first.public/: a few site generators, though this name also means "source assets" in other tools, so check.
Run your build (npm run build for most JS projects), then look for the folder that contains a fresh index.html and a hashed assets/ or _next/ directory. That folder's contents are what you zip. If you're not sure which folder is the output, the one with minified filenames like index-a1b2c3.js is the built one.
The relative-path trap
You upload the ZIP and the page loads as raw HTML, with no styling, images, or working JavaScript. The asset paths are usually the first place to look.
The cause is absolute paths. If your HTML says:
<link rel="stylesheet" href="/assets/app.css" />
the leading / tells the browser to fetch app.css from the very top of the domain. That is correct when your site owns the domain root. On a subpath such as example.com/my-project/, the browser instead looks for example.com/assets/app.css, which does not exist.
Two fixes:
- Use relative paths.
href="assets/app.css"(no leading slash) resolves next to the current page, wherever that is. - Tell your build tool the base path. Vite exposes a
baseoption for exactly this. Set it to the deployment subpath and Vite rewrites the asset URLs. Astro and most bundlers have an equivalent.
PreviewSend handles the subpath case for you. Its serving layer injects a <base href> tag pointing
at the served document's real directory (src/lib/preview/base-href.ts), so relative references
resolve correctly even on nested SPA routes. It leaves your own <base> tag alone if you've
already set one. Absolute-from-root paths are still on you to fix.
Where you can host it
Once the ZIP is well-formed, you have real choices. A few take a folder or an archive directly, no Git required:
- Cloudflare Pages has a Direct Upload mode with a "Drag and drop your files" box that accepts a ZIP or a folder. It's fast and free, capped at 1,000 files per drag-and-drop deploy, and it publishes to a
pages.devURL. - Netlify Drop lets you drag a build folder or ZIP file onto a drop zone and get a live link. You can update the same project later by dropping in a new build.
Both are solid choices for a permanent public site. A private draft takes more setup: you configure access control and indexing behavior separately, and neither service automatically adds a noindex response header to every page you upload. For a side-by-side of these and other no-Git destinations, see Netlify Drop alternatives for ZIP website hosting.
For a client-facing draft, PreviewSend's upload flow is:
- Create a free PreviewSend account. Eligible first-time owners get a one-time 14-day Pro trial on their first workspace without entering a card. Afterward, Free limits apply: the most recently updated site stays live and excess sites are archived.
- Create a project and upload
site.zip(up to 100 MB compressed and 256 files and folders). It validates the archive, extracts it, and gives you a stable URL right away. - Share the link. Every project gets a globally unique PreviewSend URL and a
noindex, nofollowheader that asks supporting search engines not to index the response. Anyone with the link can still open it until you add a password. - Let the client pin comments or request changes directly on the page without creating an account. Export the version's comments as CSV or Markdown, or turn unresolved comments into an AI-ready revision plan; then upload the next ZIP to the same URL.
- For final approval, create a named, version-specific approver link on Starter, Pro, Agency, or an active Pro trial. Sign-off PDFs require Pro, Agency, or an active Pro trial and are audit records, not electronic signatures.

From there you can add a password, set an expiry date so the link stops working after a deadline, or point a custom domain at it on the paid tiers. Passwords and expiry keep the existing address; a custom domain adds a branded address while the default one remains available. If the link is headed to a client, the client-preview workflow covers preflighting the build, choosing access, and running the review rounds around it.
If your ZIP came out of an AI builder, see how to move a compatible Lovable build off Lovable's hosting, how to export and host a Bolt.new project, or put a self-contained Claude HTML artifact behind a password. For a hand-written index.html beside styles.css and script.js, the plain HTML, CSS, and JavaScript guide covers the layout and relative links to check before zipping.
Give search engines a noindex directive
Hosting a ZIP publicly and asking search engines not to index it are separate jobs.
The reliable control is a noindex directive, delivered one of two ways per Google's indexing docs: a <meta name="robots" content="noindex"> tag in the page <head>, or an X-Robots-Tag: noindex HTTP response header. On a plain static host you'd add the meta tag to every page yourself.
The trap is reaching for robots.txt instead. A robots.txt disallow blocks crawling, not indexing. Google says a blocked URL can still appear in results if it is linked elsewhere, because the crawler cannot see a noindex header on a response it never fetches. PreviewSend puts the noindex header on normal site responses and password challenges. Active projects without a password also serve a robots.txt disallow. These are crawl and indexing directives, not an absolute guarantee that a known URL can never appear in search.
Updating the same URL
The reason a hosted URL beats a re-shared ZIP is that the link outlives the file. Push a change and everyone who already has the link sees the new version without another attachment.
On PreviewSend, updating means uploading a new ZIP to the same project. It's what the URL serves from that point on, the address is untouched, and earlier versions stay in version history within your plan's retention. The file-level version diff is available on Pro, Agency, and during the active Pro trial. If a new build breaks something, re-upload the previous one as a new version to put it back in front. For the full release routine, updating a static website without changing its URL covers preflighting the replacement, deploying in place, and clearing a stale cache. That's the practical difference between hosting a ZIP and just sharing one: the address is stable, and the contents behind it are yours to swap out whenever the site changes.
FAQ
Can I really host a website straight from a ZIP file?
Yes, as long as the ZIP holds static HTML, CSS, JavaScript, and assets with no server runtime. Put index.html at the archive root for the broadest host compatibility; PreviewSend can also use the shallowest nested index.html.
My page loads but the CSS and images are missing. What went wrong?
Almost always an absolute path. If your HTML references /assets/app.css with a leading slash, it resolves against the domain root instead of your site folder. Switch to relative paths (assets/app.css), or set your build tool base option to match where the site is served.
Should I zip the folder or the files inside it?
Zip the contents, not the wrapping folder. Some hosts refuse an archive where index.html sits inside a nested dist/ folder. Open the build folder, select everything inside, and compress that.
Will a hosted ZIP show up in Google?
That depends on the host. Public static hosts can be indexed unless you add a noindex directive yourself. PreviewSend adds a noindex header to normal site responses and password challenges. Active projects without a password also serve a robots.txt disallow.
Have a site to host? Upload it and get a live link in seconds.
Get it free