hosting

Static site vs dynamic web app: what can a ZIP host?

By PreviewSend Team · Jul 22, 2026 · 9 min read

A ZIP host serves files a browser can download: HTML, CSS, JavaScript, images, and fonts. It never runs your project's server code. So the static site vs dynamic web app question comes down to one thing: can your app be represented entirely by those browser-delivered files? If yes, a ZIP works. If it needs a server for each request, it won't.

That question is worth answering before you upload anything, because a static host will happily accept a ZIP and then serve a broken app if part of it expected a backend that isn't there.

Static site vs dynamic web app, defined by where the work happens

The useful line isn't about how interactive a site feels. It's about where the work happens.

A static site is a set of finished files. A host looks up the file for a URL and returns it unchanged. All the "dynamic" behavior (menus opening, data loading, forms validating) happens in the browser after those files arrive. A single-page React or Vue app is still static in this sense: the host hands over the same bundle to everyone, and the app comes alive on the visitor's machine.

A dynamic web app, in the sense that matters for hosting, runs code on the server for each request. It might query a database, check a session, or assemble the HTML on the fly before sending it back. MDN's introduction to server-side programming describes this split: static content ships as-is, while server-side code generates a tailored response per request. That per-request generation is the thing a file host cannot do.

So client-side JavaScript does not make a site "dynamic" in the hosting sense. A page packed with interactivity can be completely static. What pushes a project past a ZIP is a dependency on server work at the moment someone loads the page.

Test your project in a few minutes

You don't need to read every line of source. Start with two checks.

Look at what the build produces. Run the project's build (npm run build for most JavaScript projects) and look at the output folder. If you get a folder of .html, .css, .js, and assets, with an index.html and a hashed assets/ or _next/ directory, that folder is servable. If the build also emits a server file (an entry-server bundle, a Node handler, or a server/ directory), that piece needs to run somewhere and won't fit in a ZIP.

Walk the features and ask where each one runs. Go through the things your app does and sort each into one of two buckets:

  • Runs in the browser: rendering the UI, client-side routing, animations, reading from localStorage, calling an external API or browser-safe managed backend over fetch.
  • Runs on a server: validating credentials or holding a server-side session inside this project, reading or writing through a private database connection, generating page HTML from live data, saving an uploaded file, any backend endpoint that is part of this same project.

If everything lands in the first bucket, you have a static site and a ZIP will preserve its behavior. One item in the second bucket means that part needs a runtime, even if the rest is static.

What a ZIP host can and can't serve

Match each capability your project relies on. The "next step" column tells you where it belongs.

What your project relies onRuns on a static ZIP host?WhyNext step
Pre-rendered HTML pagesYesThe file already exists; the host just returns itZip the build and upload
Browser interactivity (React, Vue, vanilla JS)YesThe bundle runs on the visitor's machine after downloadZip the build output, not the source
Calls to a separately hosted APIYes, with careThe browser fetches over the network at runtimeAllow the origin; never ship private secrets
Browser-safe managed backend (public key + RLS)Yes, with careThe browser calls a separately hosted serviceConfigure auth and access rules; use only publishable client credentials
Data known at build timeYesIt gets baked into the HTML during the buildUse a static export / pre-render
HTML generated per request (server-side rendering)NoNeeds a process running for every visitRuntime host
Server-side login, sessions, Server ActionsNoThat code only runs on a serverRuntime host
Private database connection using a server-only keyNoThe credential cannot ship to the browser safelyRuntime host, or move it behind an API
File writes or backend endpoints inside the same projectNoThere's no server in a ZIP to execute themRuntime host

Two rows deserve a note.

A static site calling an API is normal and fine. Your frontend files go in the ZIP; the API lives on its own service. The browser talks to it over the network. The two conditions: the API has to permit requests from your site's origin, or the browser blocks the response under CORS, and you must not embed a private key in the bundle, since anything shipped to the browser can be read by anyone who opens developer tools.

That can include a browser-safe managed backend. Supabase's API-key guide says publishable keys are safe to expose in a web page, while access should be constrained with authentication and Row Level Security. Secret and legacy service_role keys belong only in backend components because they bypass RLS. With that split, a static frontend can sign users in and read or write through the hosted service without running its own server.

Build-time data still counts as static. If the pages and their data are all known when you build, a generator can turn them into plain HTML. A blog with a hundred posts, a docs site, a marketing page pulling from a CMS at build time, all static output. It's request-time decisions, not the mere presence of data, that force a server.

Framework specifics: same test, different switches

Frameworks change the packaging, not the underlying rule.

Vite builds a dist folder of static files by default, and its static-deploy guide treats that folder as something you drop onto any static host. But Vite also supports server-side rendering, so "it's a Vite project" isn't proof it's static. If the build emits only dist and npm run preview shows the whole app working, you're static. If it also produces a server entry, that part isn't. The full walkthrough is in deploying a Vite dist folder without Git, including the base-path check that trips up subpath hosting.

Next.js can produce a static site with output: 'export', which writes an out folder you can host as files. The catch is that Next.js's static-export docs list features that a static export can't include: handlers that read cookies or headers at request time, rewrites, redirects, Server Actions, incremental regeneration, draft mode, and the default image optimizer, among others. If a route depends on one of those when a visitor hits it, that route needs a runtime. The rest of the app can still export cleanly.

For another framework or an AI-generated project, don't infer the hosting model from the brand name. Check its deployment docs, configuration, and production output for the same dividing line: finished browser files or a server process that still has to run.

Choosing where it goes

Once you've run the test, the decision is short:

  • Fully static (everything runs in the browser, build emits only files): a ZIP or folder host works. Get the archive layout right, put index.html at the root, and upload.
  • Static frontend plus an external API: host the frontend as static files, keep the API on its own service, and confirm the origin and secret rules above.
  • Needs a server per request (SSR, server auth, a private database in the same app): choose a runtime host, a platform that runs your server code. A static file host, PreviewSend included, is the wrong tool here, and no amount of ZIP-wrangling changes that.

You can also split the app. Host the frontend as files and deploy the backend separately, so only the API needs a runtime.

Where PreviewSend fits

PreviewSend is a static host with a client-review layer, so it fits the first two cases above and not the third. It serves the extracted files from your ZIP and does not run your project's server code. If your test came back "needs a runtime," reach for a runtime platform instead; PreviewSend won't execute a backend for you.

When the output is static, create a workspace and upload the archive (up to 100 MiB compressed, with per-file and total-size limits checked during extraction). PreviewSend requires an index.html entry, extracts the files, and makes that upload the active version at a stable URL.

New projects turn on account-free client review by default. A reviewer types a name and can pin comments or request changes on the page without making an account, and each note stays tied to the version they saw. You can add a project password, which is checked server-side before any file is served, and every hosted response carries an X-Robots-Tag: noindex, nofollow header. That header is a request to search engines, not access control, so treat the password, not an unguessable link, as the real gate. Uploading a new build replaces the active version at the same URL while earlier versions stay in history within your plan's retention.

One question settles it

The label on the framework matters less than one question: does any part of your app need a server running when a visitor arrives? Run the build, look at the output, and sort your features into browser-work and server-work. All browser-work means a ZIP preserves the app, and the ZIP hosting guide covers the archive details from there. Any server-work means that piece needs a runtime, and the honest move is to host it somewhere that can run it.

FAQ

Can a dynamic website be hosted as static files?

Only if every page and piece of data is known when you build. A build tool can pre-render those into HTML and ship a static folder. Anything decided per request, such as a server rendering a page from a live database, needs a runtime and cannot be represented by a ZIP of files.

Can a static site call an API?

Yes. JavaScript in the browser can fetch from a separately hosted API. Two conditions: the API must allow requests from the browser origin (CORS), and you cannot embed a private secret in the bundle because anyone can read it. The API lives elsewhere; only the frontend files go in the ZIP.

Is a React or Vite app static?

Usually the build output is. A React or Vite frontend compiles to HTML and bundled JavaScript that runs in the browser, which a file host can serve. It stops being static when the same project also renders pages on the server per request, which produces a server bundle a file host cannot execute.

What Next.js features prevent a static export?

Static export cannot include request-time work: server-rendered handlers that read cookies or headers, redirects and rewrites, Server Actions, incremental regeneration, draft mode, and the default image optimizer. If a route needs one of these at request time, that route needs a runtime host.

Have a site to host? Upload it and get a live link in seconds.

Get it free

← Back to the blog