Table of Contents
1. Prerequisites
Before deploying, make sure you have the following installed and configured on your machine.
| Requirement | Minimum Version | Check Command |
|---|---|---|
| Node.js | 16.x or higher | node -v |
| npm | 8.x or higher | npm -v |
| Git | 2.x | git --version |
| GitHub Account | Any | github.com |
# Verify installations
node -v # Should show v18.x or higher
npm -v # Should show 9.x or higher
git --version # Should show git version 2.x
nodejs.org. The LTS (Long Term Support) version is recommended for stability.
2. Creating a React App
You can use either Vite (recommended) or Create React App to scaffold your project.
Using Vite
npm create vite@latest my-portfolio -- --template react
cd my-portfolio
npm install
Using Create React App
npx create-react-app my-portfolio
cd my-portfolio
Verify It Works
# Start the dev server
npm run dev # Vite
npm start # CRA
# Build for production
npm run build
After running npm run build, you'll see a dist/ folder (Vite) or build/ folder (CRA) containing your production-ready files.
3. Setting Up GitHub Repository
Create a new repository on GitHub and push your code.
Create a New Repository
# Initialize git in your project
git init
# Add all files
git add .
# Commit
git commit -m "Initial commit"
# Rename branch to main
git branch -M main
# Add remote (replace YOUR_USERNAME and REPO_NAME)
git remote add origin https://github.com/YOUR_USERNAME/REPO_NAME.git
# Push to GitHub
git push -u origin main
https://YOUR_USERNAME.github.io/REPO_NAME/. If your repo is named YOUR_USERNAME.github.io, it becomes your main GitHub Pages site.
4. Installing gh-pages Package
The gh-pages npm package simplifies deploying to GitHub Pages by creating and pushing to a gh-pages branch.
# Install as dev dependency
npm install --save-dev gh-pages
This package provides a predeploy and deploy script that builds your app and pushes the output to the gh-pages branch automatically.
gh-pages) containing only the built files, keeping your main branch clean.
5. Configuring package.json
Add the homepage field and deployment scripts to your package.json.
For Vite Projects
{
"name": "my-portfolio",
"homepage": "https://YOUR_USERNAME.github.io/REPO_NAME",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"predeploy": "npm run build",
"deploy": "gh-pages -d dist"
},
"devDependencies": {
"gh-pages": "^6.0.0"
}
}
For Create React App Projects
{
"name": "my-portfolio",
"homepage": "https://YOUR_USERNAME.github.io/REPO_NAME",
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
},
"devDependencies": {
"gh-pages": "^6.0.0"
}
}
homepage field tells React where the app will be hosted. Without it, asset paths will be wrong and your site will show a blank page.
6. Deploying with GitHub Actions
GitHub Actions provides automated deployment on every push. This is the modern, recommended approach.
.github/workflows/deploy.yml
name: Deploy React to GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
env:
VITE_BASE_URL: /REPO_NAME/
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Enable GitHub Pages in Repository Settings
- Go to your repository on GitHub
- Click Settings → Pages
- Under Source, select GitHub Actions
- Save the settings
7. Deploying with gh-pages Branch
Alternatively, use the gh-pages package directly from your terminal.
# Deploy in one command
npm run deploy
This runs the predeploy script (builds the app) and then gh-pages -d dist which pushes the dist/ folder to the gh-pages branch.
Manual gh-pages Push
# Build the app
npm run build
# Navigate into the build output
cd dist
# Initialize git
git init
git add -A
git commit -m 'Deploy'
# Push to gh-pages branch
git push -f git@github.com:YOUR_USERNAME/REPO_NAME.git main:gh-pages
8. Handling Client-Side Routing
If your React app uses React Router, you need to handle routing on GitHub Pages since it only serves static files.
The Problem
When you navigate to /about on GitHub Pages, it tries to find an about.html file that doesn't exist, resulting in a 404 error.
Solution 1: HashRouter (Easiest)
// Use HashRouter instead of BrowserRouter
import { HashRouter as Router, Routes, Route } from 'react-router-dom'
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/projects" element={<Projects />} />
</Routes>
</Router>
)
}
// URL will be: https://yoursite.github.io/repo/#/about
Solution 2: BrowserRouter with 404.html Redirect
// Add a 404.html redirect (in your public/ folder)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=/REPO_NAME/">
<script>
window.location.href = '/REPO_NAME/' +
window.location.pathname.substr(1).replace(/\/$/, '')
</script>
</head>
</html>
| Approach | Pros | Cons |
|---|---|---|
| HashRouter | Zero config, works immediately | URLs contain # (ugly) |
| BrowserRouter + 404.html | Clean URLs | Extra file needed, more complex |
| BrowserRouter + SPA plugin | Clean URLs, automatic redirect | Requires GitHub Actions setup |
9. Custom Domain Setup
Use your own domain name instead of the default GitHub Pages URL.
Step 1: Add a CNAME File
# In your public/ or src/ directory, create CNAME file
echo "yourdomain.com" > public/CNAME
Step 2: Configure DNS
At your domain registrar, add these DNS records:
| Type | Name | Value | TTL |
|---|---|---|---|
| A | @ | 185.199.108.153 | 3600 |
| A | @ | 185.199.109.153 | 3600 |
| A | @ | 185.199.110.153 | 3600 |
| A | @ | 185.199.111.153 | 3600 |
| CNAME | www | YOUR_USERNAME.github.io | 3600 |
Step 3: Enable in GitHub Settings
- Go to repository Settings → Pages
- Under Custom domain, enter your domain
- Check Enforce HTTPS
dig yourdomain.com to check if the records are live.
10. Troubleshooting Common Issues
Blank White Page
// Problem: The homepage field is missing or wrong
// Fix: Ensure package.json has correct homepage
{
"homepage": "https://username.github.io/repo-name"
}
// Also check your router basename if using BrowserRouter
<BrowserRouter basename="/repo-name">
404 Error on Refresh
// Problem: Client-side routing without server config
// Fix: Use HashRouter or add 404.html redirect
// For Create React App, add this to public/ folder:
// public/redirect.html → rename to 404.html
<meta http-equiv="refresh" content="0;url=/">
Assets Not Loading (CSS/JS 404)
// Problem: Asset paths are absolute instead of relative
// Fix: Don't use absolute paths in your code
// Bad
<img src="/images/logo.png" />
// Good (use relative or process.env.PUBLIC_URL)
<img src={process.env.PUBLIC_URL + "/images/logo.png"} />
// For Vite, use the base config in vite.config.js:
export default defineConfig({
base: '/REPO_NAME/',
})
Deployment Succeeds But Site Doesn't Update
# Clear your browser cache
# Or use hard refresh: Ctrl+Shift+R (Windows) / Cmd+Shift+R (Mac)
# Check GitHub Pages settings for correct source branch
# gh-pages branch should contain the built files, not source code
.env.local for local development.
Quick Deployment Checklist
-
homepagefield set in package.json - Build runs without errors (
npm run build) - Repository is public (or GitHub Pro for private)
- GitHub Pages source is set to
gh-pagesbranch or GitHub Actions - Router configured with correct basename or HashRouter
- All asset paths are relative (no leading
/) - No secrets or API keys in code