The Vite Base Path: Fix Blank Pages And Broken Assets

A blank page after deploy usually means the Vite base path is wrong. What base does, when to set it, why './' breaks routers, and the two places it can't reach.
The OxyPages Team · · 8 min read
You deployed your Vite app, opened the link, and got a white page. No error on screen, no content, nothing. Open the browser console and it's full of red: GET https://you.github.io/assets/index-DSXtc1GT.js 404.
That address is the clue. Your app lives at /my-repo/, but the page is asking for its JavaScript at the root of the domain, where nothing exists. The setting that controls this is the Vite base path, and it defaults to /.
At the root of a domain, / is correct and you never think about it. Move the app into a subfolder, which is exactly what a GitHub Pages project site does, and every asset request points one level too high.
The fix is one line in vite.config.js. But there are three ways to write that line, and one of them quietly breaks apps that use a router. If the app isn't online yet, deploying a Vite app from its dist folder comes first. Below is what each value does, which one to pick, and the two places where setting it isn't enough: the router, and any asset path you typed by hand.
TL;DR: Vite's base option sets the path every built asset is requested from. It defaults to /, which is right when your app sits at the root of a domain or subdomain. For a subfolder, like a GitHub Pages project site, set base: '/my-repo/' with both slashes and rebuild. base: './' makes paths relative, which suits an embedded app but breaks nested routes in a history-router app. Also pass the base to your router, and import assets instead of typing /logo.png, because hand-typed paths are never rewritten.
What Is The Vite Base Path?
The Vite base path is the public URL prefix your app is served from. Vite writes it into every asset URL during npm run build, so the browser knows where to fetch the JavaScript, CSS and images. It's the base option in vite.config.js, and Vite's documentation of the base option lists its default as /.
I built the same app three times on Vite 8.3.6 to show exactly what changes, and a rerun on Vite 8.3.8 on 13 November 2026 gave identical output. Here's the script and stylesheet tag from dist/index.html each time:
base value | What index.html asks for | Works when the app is at |
|---|---|---|
'/' (default) | /assets/index-DSXtc1GT.js | The root of a domain or subdomain |
'/demo/' | /demo/assets/index-CPcTYj_z.js | example.com/demo/ only |
'./' | ./assets/index-ql14x63E.js | Anywhere, relative to the page |
With the default, the request starts at the domain root. With /demo/, every request is prefixed. With ./, each path is relative to whatever page loaded it, which sounds like the safe choice and mostly is, with one exception covered below.
When Do You Need To Set It?
You need it whenever the app isn't served from the root of its domain. That covers four common setups:
- A GitHub Pages project site. It lives at
username.github.io/repo-name/, sobasemust be'/repo-name/'. A user site atusername.github.iosits at the root and needs nothing. - A subfolder on an existing website. Your app at
example.com/tools/calculator/needsbase: '/tools/calculator/'. - An app embedded in another page or platform, where you don't know the final path in advance. That's the case Vite's docs give for a relative base.
- A reverse proxy that mounts the app under a path like
/dashboard/.
And you never need it on a host that gives each project its own subdomain. Netlify's *.netlify.app, Cloudflare's *.pages.dev, Vercel's *.vercel.app and OxyPages' *.myoxypages.com all serve your app at /, and so does a custom domain pointed at any of them. If you're on one of those and seeing a blank page, the base path probably isn't your problem.
That's also my main advice if you can choose: put the app on its own subdomain and leave base alone. It's one less setting to keep in sync, and the GitHub Pages subfolder setup is where this bug shows up most. The trade-offs of GitHub Pages are worth reading if that's where you are.
How To Set The Base Path In Vite
Set it in vite.config.js and rebuild:
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [react()],
base: '/my-repo/',
})
Or pass it on the command line for a single build, which is handy in a deploy script: vite build --base=/my-repo/.
Whichever you use, your code can read the value back as import.meta.env.BASE_URL, one of Vite's built-in env variables. Vite's guide to env variables and modes lists it, and the guide to Vite environment variables explains how those values get baked into the build.
Three rules keep it working:
- Start and end with a slash.
'/my-repo/', not'my-repo'or'/my-repo'. - Match the real path exactly. URL paths on most hosts are case sensitive, so
/My-Repo/and/my-repo/aren't the same folder. - Rebuild after changing it. The base is baked in at build time. Changing the config without running
npm run buildchanges nothing on the live site.
Before uploading, check dist/index.html. If the script tag says /my-repo/assets/..., the base took effect.
Relative Base: When './' Breaks Your App

A relative base like './' makes every asset URL relative to the page that loaded it. Vite's docs suggest it when you don't know the deploy path in advance, and for a one-screen app it works anywhere.
The trouble starts with a history router and nested routes. Say someone opens example.com/app/settings/profile directly, and the host's fallback serves index.html. The browser resolves ./assets/index.js against the current URL and requests /app/settings/assets/index.js.
That file doesn't exist. Depending on the host you get a 404, or, worse, your index.html served in place of the script, which shows up as Unexpected token '<' in the console.
So my rule of thumb:
- One screen, or a hash router:
'./'is fine. - A history router with nested routes: use the absolute path,
'/my-repo/'.
The single-page fallback itself is a separate fix, and the 404 on refresh guide has it for each host.
Two Places The Base Path Doesn't Reach

Setting base fixes what Vite can see. Two things it can't.
Your Router Needs It Too
Vite rewrites asset URLs, but it doesn't tell your router where the app lives. Without that, React Router sees the path /my-repo/settings, looks for a route called /my-repo/settings, and renders nothing.
React Router takes a basename, and Vue Router takes the base as the argument to createWebHistory. Vite exposes your configured value as import.meta.env.BASE_URL, so you only set it in one place:
// React Router
<BrowserRouter basename={import.meta.env.BASE_URL}>
<App />
</BrowserRouter>
// Vue Router
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
})
The Vue line is what create-vue scaffolds by default, which is why Vue apps hit this less often than React ones.
Paths You Typed By Hand Aren't Rewritten
Vite adjusts asset URLs it knows about: files you import in JavaScript, url() in CSS, and references in index.html. A path written as a plain string in your code is just text, and Vite leaves it alone.
My test build showed this with create-vite's own React template. The hero image is imported, so with base: '/demo/' it became /demo/assets/hero-CLDdwZDr.png. The social icons use a hand-typed href="/icons.svg#github-icon", and after the build they still pointed at /icons.svg. Under a subfolder, those icons break while the rest of the page works.
Two fixes:
- Import the file from
src/assetsso Vite tracks it and rewrites the URL. - Prefix the path at runtime for files in
public: build the URL fromimport.meta.env.BASE_URLplus'icons.svg'. Vite's docs note the variable is replaced at build time, so it has to appear exactly as written.
Walkthrough: A Vite App On A GitHub Pages Project Site
Here's the sequence I'd follow for a React app in a repository called budget-tracker:
- Set
base: '/budget-tracker/'invite.config.js. - Pass
import.meta.env.BASE_URLtoBrowserRouteras itsbasename. - Search the code for
src="/andhref="/and either import those files or prefix them with the base. - Run
npm run buildand opendist/index.html. The script tag should start with/budget-tracker/assets/. - Run
npm run previewand visithttp://localhost:4173/budget-tracker/. Vite's preview server serves the build under the base, so this is a real test. - Publish
distto Pages and openusername.github.io/budget-tracker/. Click through, then refresh on a deep route.
If step 6 shows the page but refresh on a route 404s, the base is fine and you need the fallback. If you'd rather not deal with subfolders at all, a host that gives the app its own subdomain skips this whole post.
What To Do Next
Open the console on your blank page and read the failing URL. If it's missing your subfolder, set base to that subfolder with slashes at both ends, pass it to your router, rebuild and redeploy.
If you can put the app on its own subdomain instead, do that and delete the setting. Publish your build at its own address on OxyPages, where every project gets a subdomain served from /. For a portfolio or a personal project, start a free account, no card needed. It hosts the built files only, so if your app needs a server, pick a host that runs one.
FAQ
Why Is My Vite App A Blank Page After Deploying?
Usually because the Vite base path doesn't match where the app is served. Open the console: 404s for files under /assets/ mean the build asked for assets at the domain root while the app sits in a subfolder. Set base to that subfolder and rebuild.
Should I Use base './' Or An Absolute Path?
Use an absolute path like '/my-repo/' if your app uses a history router with nested routes, because a relative base resolves assets against the current URL and breaks on deep links. Use './' for a single-screen app or one you embed somewhere with an unknown path.
Does The Base Path Affect Files In The Public Folder?
Vite rewrites references to them in index.html and CSS, but not paths typed as strings in your JavaScript or JSX. Prefix those with import.meta.env.BASE_URL, or move the file into src/assets and import it.
Do I Need A Base Path On A Custom Domain?
No, as long as the app sits at the root of that domain. A custom domain pointed at a GitHub Pages project site serves from /, so you'd set the Vite base path back to '/' when you add the domain.