How to Deploy Your Vite React App to GitHub Pages (With and Without React Router)
This article will guide you to deploy existing Vite React app to GitHub. The Vite documentation has already written the steps, but I personally think it misses some details. Let us address it.
Configure Vite Config
First of all, add a property called base with the value of our repository name on vite.config.js or vite.config.ts. For example, if our repository name is react-vite-gh-pages, then we set the configuration as follows:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig(({ command }) => {
const config = {
plugins: [react()],
base: '/',
}
if (command !== 'serve') {
config.base = '/react-vite-gh-pages/'
}
return config
})
The deployment URL would be https://<OUR_GITHUB_USERNAME>.github.io/react-vite-gh-pages. Note that we have a conditional config based on our Vite command. This means when we are running npm run dev, the page will start serving on path http://localhost:5173/ instead of http://localhost:5173/react-vite-gh-pages/
Create GitHub Action Workflow
On our GitHub repository, navigate to “Pages” menu inside “Settings” tab. Set build and deployment source to “GitHub Actions”.

We need to create a Github Action workflow configuration to automate the deployment for every push in main branch or manually triggered from Actions tab. Create the following directory:
react-vite-gh-pages/
├─ .github/
│ ├─ workflows/
│ │ ├─ deploy.yml
Inside deploy.yml, we set the following command from Vite documentation:
name: Deploy static content to Pages
on:
push:
branches: ['main']
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: 'pages'
cancel-in-progress: true
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: 18
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Build
run: npm run build
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: './dist'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
Stage all changes in the current directory using git add ., commit, and push it to our GitHub repository. Under the “Actions” tab, we will see our workflow appear based on our recent push. Congrats, your app is successfully deployed!

If you’re unsure about the address, head back to Settings → Pages and you will find the URL.

If We Have React Router Installed…
When we use React Router on our project, the workflow will run without any problems. But we will get this error when we open our page:

To add more confusion, the console does not show any errors. The actual root cause is that the router’s basename is still set to / when the root of our deployment is /react-vite-gh-pages/. In order to fix that, we need to update it as we did on vite.config.js— adding a conditional base path. import.meta.env.DEV is a built-in Vite environment variable that returns true when npm run dev is running.
import { createBrowserRouter, RouterProvider, Link } from 'react-router-dom'
function App() {
const router = createBrowserRouter(routes, {
basename: import.meta.env.DEV ? '/' : '/react-vite-gh-pages/',
})
return <RouterProvider router={router} />
}
Or, if you write routes as components:
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom'
function App() {
return (
<BrowserRouter basename={import.meta.env.DEV ? '/' : '/react-vite-gh-pages/'}>
<Routes>
<Route
path='/'
element={
<div>
<h1>Hello World</h1>
<Link to='about'>About Us</Link>
</div>
}
/>
<Route path='/about' element={<div>About</div>} />
</Routes>
</BrowserRouter>
)
}
One More Thing!
There is a GitHub’s 404 error when we refresh the page on children path relative to the basename route (e.g. /about). This is because GitHub Pages is looking for about.html while our app is a single page application which has only index.html. To prevent this, update the following line on our deploy.yml:
- Before:
run: npm run build - After:
run: npm run build && cp ./dist/index.html ./dist/404.html
By default, GitHub Pages will look for 404.html if there is no specified document provided. What happens here is we create a copy of our index.html as 404.html.
The source code of this guide can be found here.
Caveats
- This method is only for those who want to deploy their Vite React app to
https://<OUR_GITHUB_USERNAME>.github.io/<REPO_NAME>/path. - If we build locally using
npm run build, it will show a blank page whendistdirectory is served locally. - We are locked in GitHub Pages deployment. If we try to deploy it on Netlify or Vercel, it will show a blank page as if we serve the build locally like number 2.
- It is recommended to use npm or yarn as the package manager and has its
package-lock.jsonoryarn.locklockfile present in the repository. GitHub Actions does not support pnpm’spnpm-lock.yamlat the moment of this writing.