OxyPages

How To Deploy A Vite App From Its Dist Folder

How To Deploy A Vite App From Its dist Folder

How to deploy a Vite app: what npm run build puts in dist, why only that folder ships, the routing setting that saves deep links, and three ways to go live.

The OxyPages Team · · 8 min read

You ran npm run build, a dist folder appeared, and now you're wondering which of the files in your project actually go online. Most guides answer by walking you through a git provider, a dashboard and a build pipeline before you see a live link.

You can skip most of that. To deploy a Vite app, you put the contents of dist on a web server. That's it. Everything else in your project folder, node_modules included, stays on your laptop.

I scaffolded a fresh React app with create-vite on 8 November 2026 to check what that folder really holds. The build took 171 milliseconds and produced eight files, under 300 KB in total. The node_modules folder next to it was about 55 MB. A rerun on 13 November with Vite 8.3.8 produced the same eight files, byte for byte.

That ratio is the whole story. Below is what's in the folder, why only the folder ships, the one setting that decides whether links survive a refresh, and three ways to get it live, from a drag and drop to a host that rebuilds on every push. The wider React hosting picture is covered elsewhere; this one stays on the folder.

TL;DR: A Vite build is plain static files. Run npm run build, then upload what's inside dist (not the folder around it, and never node_modules). If your app has client-side routes, the host must serve index.html for paths it can't find, or deep links 404 on refresh. Pick one of three routes: drag the folder onto a host, send it from a CLI or an AI agent, or connect the repository so the host builds on every push. If your Vite app renders on a server, none of this applies and you need a host that runs code.

What Does npm run build Put In dist?

The dist folder is your finished website: HTML, CSS, JavaScript and images, already bundled and named for caching. Vite's guide to deploying a static site puts it plainly: by default, the build output goes to dist, and that's the folder you deploy.

Here's the real listing from my test build, Vite 8.3.6 with the React template:

dist/
  index.html                  0.45 kB
  favicon.svg                 9.5 kB
  icons.svg                   5.0 kB
  assets/
    index-DSXtc1GT.js       222.4 kB  (69.3 kB gzipped)
    index-DykytF2W.css        4.1 kB
    hero-CLDdwZDr.png        13.1 kB
    react-CHdo91hT.svg        4.1 kB
    vite-BF8QNONU.svg         8.7 kB

Three things are worth noticing.

index.html is tiny. Its body is one empty <div id="root"> plus a script tag. Your whole app lives in that one JavaScript bundle, React included.

The random-looking part of each name, like DSXtc1GT, is a content hash. Change your code and the hash changes, so a host can tell browsers to cache these files forever and still ship updates instantly.

Files in your public folder, like favicon.svg, are copied across as they are, with their names untouched.

Why You Deploy Only The dist Folder

Why You Deploy Only The dist Folder - OxyPages

Your source files are instructions for Vite, not a website. A browser can't read JSX, can't resolve import React from 'react', and has no idea what a .tsx file is. The build turns all of that into the files above.

So when you upload, upload what's inside dist:

  • Not the project folder. Its index.html points at /src/main.jsx, source code no browser can run, so you get a blank page.
  • Not node_modules. It's build-time tooling. My test app had 55 MB of it, and nothing in it is needed once the build has run.
  • Not src. Shipping it just publishes your source code next to the bundle.
  • Not the dist folder itself, if the host wants a zip. Zip the contents, so index.html sits at the top of the archive. Zipping the contents rather than the folder covers that trap in detail.

One check before you upload: run npm run preview. It serves dist at http://localhost:4173, so you see the built version, not the dev server. Vite's CLI reference for vite preview is clear that it's for checking locally and isn't meant to be a production server. One thing it hides: preview serves index.html for every path, so it won't show you a refresh 404. Test that on the live link.

If your app uses React Router, Vue Router or any client-side router, the host has to send index.html for paths that don't match a file. That's called a single-page app fallback.

Without it, the home page works and clicking around works, but refreshing on /settings or opening a shared link to it returns a 404. The browser asked the server for /settings, and there's no such file in dist. Only the JavaScript knows that route exists.

Every major static host can fix this, each with its own switch or file, and it's one line of config on most of them. The guide to fixing a 404 on refresh has the exact setting for each host. Do it before you share a link, not after someone tells you it's broken.

Two related gotchas come up right after this one. If the app lives in a subfolder rather than at the root of a domain, set Vite's base path, or the page goes blank. And any VITE_ environment variable is baked into the bundle as plain text, so never put a secret in one. My test build proved it: a VITE_ value showed up word for word in the JavaScript, and a variable without the prefix came out as undefined.

Three Ways To Deploy A Vite App

Three Ways To Deploy A Vite App - OxyPages

There are three real routes, and they differ mostly in who runs the build and when.

Upload the folderSend it from a CLI or agentPush to deploy
Who runs npm run buildYou, on your machineYou, or the agentThe host, on its servers
What you hand overThe contents of distdist, usually zippedThe repository
How you updateUpload againRun the command againPush a commit
SetupNoneA CLI install, or none for some agent routesConnect GitHub and set the build
Best forA first deploy, a demo, a one-offScripts and AI coding agentsAnything you change weekly

Route 1: Upload The Folder

This is the quickest way to see your app live, and most static hosts offer it. Netlify Drop takes a dragged folder. Cloudflare Pages has a direct upload. GitHub Pages wants the files committed to a repository, which is more steps than it sounds.

On OxyPages it's New Project, then Upload Files, then drag in dist or a zip of its contents. If the app has client-side routes, switch on Single-Page App Mode in the same step, or later in the project's Settings.

The catch with this route is that every update is a manual rebuild and re-upload. Fine for a portfolio you touch twice a year. Tedious for a project you're actively shipping.

Route 2: Send It From A CLI Or An AI Agent

Every big host has a command that uploads a built folder: netlify deploy --dir=dist, vercel deploy, wrangler pages deploy dist. Each needs its CLI installed and, for anything permanent, an account.

If you're working with an AI coding agent like Claude Code, the agent can do the whole thing in one go. Here's the request it sends to the same host as the upload example above, with no account and no CLI:

npm run build
(cd dist && zip -r ../dist.zip .)
curl -sS -X POST https://api.oxypages.com/drops/app \
  -H "X-Oxy-Agent: my-agent" \
  -F "file=@dist.zip"

The reply carries a live HTTPS link that lasts 30 minutes and a claim link that keeps it permanently in a free account. Claiming moves the app to its own new address. The same request works from any agent that can run a shell command, and the agent publishing guide has the details.

Send the built output, not the source. A folder with a package.json and no build output gets refused with a message saying exactly that, because a no-account drop never runs your build for you.

Route 3: Push To Deploy

For anything you'll keep changing, connect the repository and let the host build it. You set the build command (npm run build) and the output folder (dist) once, and every push to your main branch rebuilds and redeploys. Most hosts also give each pull request its own preview link.

Netlify, Vercel and Cloudflare all detect Vite automatically, and so do newer hosts that build from GitHub. Each one counts build minutes against a monthly allowance, so check what yours includes before you push forty times a day.

This is the route I'd use for any project I expect to touch more than once a month. The first setup costs ten minutes and every deploy after that costs a git push.

When This Isn't A Static Deploy

Everything above assumes your Vite app is a client-side app, which is what create-vite gives you. Some Vite projects aren't.

If you've added a server layer, like Nitro, Vike in server mode or TanStack Start with server functions, your build produces code that has to run on a server. No static host can run it, and that includes OxyPages, which serves files and never runs your code. Use Vercel, Netlify or Cloudflare Workers for those, because they run server functions and a static host doesn't.

A quick test: if dist contains only HTML, CSS, JavaScript and assets, it's static. If your build also writes a server folder or an entry file meant for Node, it isn't.

What To Do Next

  1. Run npm run build and open dist. Check that index.html is at the top.
  2. Run npm run preview and click through every route at http://localhost:4173.
  3. Decide on the route: upload for a one-off, CLI or agent for scripts, push to deploy for anything ongoing.
  4. If you have client-side routes, turn on your host's single-page app fallback before you share a link.
  5. Open the live link, go to a deep route, and hit refresh. If it loads, you're done.

If you want the folder live without connecting anything first, put your dist folder online with OxyPages and claim it when you're happy with it. For a portfolio, a demo or a side project, start a free account, no card needed: 25 MB of storage covers a build like the one above many times over.

FAQ

Do I Need Node.js On The Server To Deploy A Vite App?

No. Node runs on your machine during the build. Once npm run build finishes, dist is ordinary files, and the server's only job is to hand them to browsers. That's why almost any host will serve one.

How Big Is A Vite Build?

Smaller than people expect. My fresh React test app built to eight files and under 300 KB, against about 55 MB of node_modules it needed to get there. The JavaScript bundle was 222 KB, or 69 KB once a host compresses it.

Should I Commit The dist Folder To Git?

Usually not. Add dist to .gitignore and let the host build it from source, so the repository holds code and the host holds output. The exception is a host with no build step, like plain GitHub Pages without Actions, where you commit the built files on purpose.

Can I Deploy A Vite App Without A Repository?

Yes. Upload the contents of dist by dragging them onto a host, or send them with a single command from a CLI or an AI agent. A repository only becomes worth it once you're deploying often enough that rebuilding by hand gets old.

Try It Now

Still Here? Drop It In.

The whole pitch fits in one sentence: your HTML, on a link, in seconds.

Drag and drop your HTML files, a folder, a ZIP, your app's build folder, a PDF or an image

or ·

No account needed. Your unclaimed website stays live for 30 minutes on a free subdomain. Claim it to your account to keep it permanently.

  • No Account Needed
  • Free SSL
  • 30-Minute Unclaimed Link, Claim To Keep It