Publish a Vite Project

Vite builds to a dist/ directory of plain static files—exactly what Surge publishes. Total time from a fresh project to live on the web: about two minutes, most of it npm.

Build and publish

npm create vite@latest my-project
cd my-project
npm install
npm run build
surge ./dist my-project.surge.sh

That's the entire flow. The publish output confirms your project propagating to every node of Surge's CDN—when it prints Success!, you're live worldwide:

$ surge ./dist lucid-example.surge.sh

   Running as you@example.com (Free)

        project: ./dist
         domain: lucid-example.surge.sh
           size: 3 files, 672 bytes
         upload: [=========================] 100%
            CDN: [=========================] 100%
     encryption: [=========================] 100%

  ┌──────────┬────────────────────────────────────────────────────────────────┬───────────────────────┐
  │   CERT   │   *.surge.sh, surge.sh                                         │   auto-renew          │
  ├──────────┼────────────────────────────────────────────────────────────────┼───────────────────────┤
  │   DNS    │   using Surge Name Servers                                     │   geo-aware           │
  └──────────┴────────────────────────────────────────────────────────────────┴───────────────────────┘
  ┌──────────┬──────────────────┬───────────────────────┬─────────────────────┬─────────────┬─────────┐
  │   HTTP   │   sfo.surge.sh   │   US, San Francisco   │   138.197.235.123   │   D.Ocean   │   ✔ ◍   │
  │   HTTP   │   lhr.surge.sh   │   GB, London          │   46.101.67.123     │   D.Ocean   │   ✔ ◍   │
  │   HTTP   │   yyz.surge.sh   │   CA, Toronto         │   159.203.50.177    │   D.Ocean   │   ✔ ◍   │
  │   HTTP   │   jfk.surge.sh   │   US, New York        │   159.203.159.100   │   D.Ocean   │   ✔ ◍   │
  │   HTTP   │   ams.surge.sh   │   NL, Amsterdam       │   188.166.132.94    │   D.Ocean   │   ✔ ◍   │
  │   HTTP   │   fra.surge.sh   │   DE, Frankfurt       │   138.68.112.220    │   D.Ocean   │   ✔ ◍   │
  │   HTTP   │   sgp.surge.sh   │   SG, Singapore       │   139.59.195.30     │   D.Ocean   │   ✔ ◍   │
  │   HTTP   │   blr.surge.sh   │   IN, Bangalore       │   139.59.50.135     │   D.Ocean   │   ✔ ◍   │
  │   HTTP   │   syd.surge.sh   │   AU, Sydney          │   45.76.126.95      │   Vultr     │   ✔ ◍   │
  │   HTTP   │   nrt.surge.sh   │   JP, Tokyo           │   172.104.96.133    │   Linode    │   ✔ ◍   │
  └──────────┴──────────────────┴───────────────────────┴─────────────────────┴─────────────┴─────────┘
   Live preview ................................................. 1785787164375-lucid-example.surge.sh
   Production ................................................................. lucid-example.surge.sh

   Success! - Published to lucid-example.surge.sh

   domain written to dist/CNAME

Keep the domain across builds

That first publish wrote the domain to dist/CNAME—but vite build wipes and recreates dist/, so the next build would lose it. Move it to public/, which Vite copies verbatim into every build:

mv dist/CNAME public/CNAME

Now the domain travels with every build, and publishing needs no arguments:

npm run build && surge ./dist publish

Make it a script

{
  "scripts": {
    "build": "vite build",
    "deploy": "vite build && surge ./dist publish"
  }
}

npm run deploy now builds and publishes in one move—for you, for teammates you've invited, and for CI.

If you're using a router

Vite + React Router (or Vue Router, or any client-side routing with real URLs) needs one extra file so deep links survive refresh—see Publish a Single-Page App.

Custom domain

Publish to your own domain the same way—surge ./dist example.com—and the output walks you through pointing DNS. The full path is in Put a Project on Your Own Domain.