Deploying React App to Github Pages

I recently went through the process of deploying my little React project to GitHub Pages, and there were a few tricky parts that I wish someone had told me earlier. So I’m writing this down like a personal note to future me (and maybe to you if you’re trying the same thing).

25 Sep 2025
React Deployment

GitHub Actions Workflow for Deployment

We’ll start by creating a GitHub Actions workflow that builds and deploys your React project automatically whenever you push to the main branch.

Create a file at .github/workflows/deploy.yml with the following content :

# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages

on:
  # Runs on pushes targeting the default branch
  push:
    branches: ["main"]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages
permissions:
  contents: read
  pages: write
  id-token: write

# Allow one concurrent deployment
concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  # Single deploy job since we're just deploying
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v5
      - name: Set up Node
        uses: actions/setup-node@v5
        with:
          node-version: lts/*
          cache: "npm"
      - name: Install dependencies
        run: npm ci
      - name: Build
        run: npm run build
      - name: Setup Pages
        uses: actions/configure-pages@v5
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v4
        with:
          # Upload dist folder
          path: "./dist"
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

What this workflow does

  1. Triggers when you push to main.

  2. Installs dependencies using npm ci.

  3. Builds the project with npm run build.

  4. Uploads the build output from the dist/ folder.

  5. Deploys automatically to GitHub Pages.

Add a 404 Fallback for React Router

GitHub Pages doesn’t know how to handle React Router paths like /path. It will try to look for a file and fail.

To fix this, we add a 404 fallback that serves your index.html instead, so React Router takes over routing.

Update your deploy steps:

- name: Build
  run: npm run build
- name: Add 404 fallback
  run: cp dist/index.html dist/404.html

This simply copies index.html as 404.html inside dist/.

Now, when someone visits /invoices, GitHub Pages serves 404.html (which is really your index.html), and React Router loads the correct route.

Wrap Your App with BrowserRouter

In your React entry point, make sure your <App /> is wrapped in BrowserRouter. This enables proper routing on GitHub Pages.

import { BrowserRouter } from "react-router-dom";

<BrowserRouter basename="/invoice-app">
    <App />
</BrowserRouter>
  • BrowserRouter tells React Router to use the browser’s history API.

  • basename="/invoice-app" is important when deploying to a subpath (e.g., username.github.io/invoice-app).

Add Base in vite.config.ts

If you’re using Vite, you must tell it where your app will live on GitHub Pages.

Update vite.config.ts

export default defineConfig({
  plugins: [react(), tailwindcss()],
  base: "/
repo-name/", // add this line
});
  • Replace repo-name with the name of your GitHub repository.

  • This ensures that all built files use the correct path when deployed.

Final Thoughts

With these steps, you now have:

  • Automatic deployments via GitHub Actions.

  • A working fallback for React Router paths.

  • Proper base paths for GitHub Pages.

This setup lets you focus on building your app without worrying about manual deployments.