Deploying to GitHub Pages
GitHub Actions can build your React app and push the result to GitHub Pages automatically — every push to main triggers a fresh deploy. No manual steps required after the initial setup.
The workflow file
Section titled “The workflow file”name: Deploy 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: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npm run build - 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: - id: deployment uses: actions/deploy-pages@v4Two jobs: build compiles and uploads the artifact; deploy publishes it to Pages. They run sequentially — deploy waits for build to succeed.
Enabling GitHub Pages in the repository
Section titled “Enabling GitHub Pages in the repository”- Go to your GitHub repo → Settings → Pages
- Under Build and deployment, set Source to GitHub Actions
- Save
GitHub Pages is now configured to accept deployments from the Actions workflow.
The deploy URL
Section titled “The deploy URL”Once the workflow runs, your app is live at:
https://your-github-username.github.io/bulletin/(Or without the subpath if the repo is named username.github.io.)
npm ci vs npm install
Section titled “npm ci vs npm install”The workflow uses npm ci instead of npm install. The difference:
| Command | Behavior |
|---|---|
npm install | Installs and may update package-lock.json |
npm ci | Installs exactly from package-lock.json — faster, reproducible, fails if lock file is out of sync |
CI environments always use npm ci — you want the exact same dependency versions every time.
Monitoring the deployment
Section titled “Monitoring the deployment”After pushing to main, go to your repo’s Actions tab and watch the workflow run. Each step shows its output in real time. If the build fails, the error is in the npm run build step.
Common failures:
- TypeScript errors that pass locally but fail in CI (strict mode differences)
- Missing environment variables — CI doesn’t have your
.envfiles
For env vars in CI, you can bake the production URL directly into the build command:
- run: VITE_API_URL=https://your-app.railway.app npm run buildOr use GitHub Actions secrets if the URL is sensitive.
Exercise
Section titled “Exercise”In your Bulletin frontend project (GitHub repo):
- Create
.github/workflows/deploy.ymlwith the workflow shown above. - Go to GitHub → Settings → Pages → set source to GitHub Actions.
- Push the workflow file to
main. - Watch the Actions tab — confirm the workflow completes successfully.
- Visit
https://your-username.github.io/bulletin/and confirm the app loads and connects to your Railway backend.
- GitHub Actions builds and deploys on every push to
main— no manual deploy steps. - Two jobs:
build(compiles + uploads artifact) anddeploy(publishes to Pages). - Enable Pages in repo settings → set source to GitHub Actions.
- Use
npm ciin CI for reproducible installs. - Pass
VITE_API_URLas an environment variable in the build step if it’s not committed.