Firebase Hosting + GitHub Actions: Complete Setup Guide (2026)
Deploy a static site or single-page app to Firebase Hosting automatically, get a review URL for every pull request, and publish to the live channel safely when changes merge.
The short version
Run firebase init hosting for a new site or firebase init hosting:github for an existing Hosting project, let the Firebase CLI create the GitHub secret and workflow files, then commit the generated YAML. Pull requests get preview URLs, and your main branch can deploy to the live channel.
Firebase Hosting's GitHub integration is still the easiest path in 2026 because it wires together the Firebase project, service account, encrypted GitHub secret, and workflow files for you. You can hand-edit the generated YAML afterward, but start with the CLI unless you have a reason not to.
1. What you need before starting
- A Firebase project with Hosting enabled or permission to enable it.
- A GitHub repository where you have admin access, because the CLI needs to create repository secrets.
- Node.js and your app's package manager installed locally.
- The latest Firebase CLI available through
npx firebase-tools@latestor a globalfirebase-toolsinstall. - A known build command and output directory, for example
npm run buildanddist,build, orpublic.
Do one manual local build before you touch GitHub Actions. CI should automate a process you already understand, not debug your framework, output folder, and Firebase setup all at once.
2. Install and sign in to the Firebase CLI
You can avoid global installs by using npx. This is my default for one-off setup commands because it makes it obvious which tool is running.
npx firebase-tools@latest login
npx firebase-tools@latest projects:listIf you prefer a global install, keep it current and confirm the version before setup.
npm install -g firebase-tools
firebase --version
firebase login3. Initialize Firebase Hosting
For a brand-new Hosting setup, run the full Hosting initializer from the repository root.
npx firebase-tools@latest init hostingThe important prompts are:
- Select the Firebase project you want to deploy to.
- Choose the public directory that contains your built files.
- Answer yes to single-page app rewrites if your app uses client-side routing.
- Do not overwrite your existing
index.htmlunless you intentionally want Firebase's starter page.
For a project that already has firebase.json and .firebaserc, run only the GitHub Actions initializer.
npx firebase-tools@latest init hosting:github4. What the GitHub setup command creates
The Firebase CLI handles the boring but security-sensitive pieces:
- Creates a Firebase service account with permission to deploy Hosting.
- Uploads that service account JSON as an encrypted GitHub repository secret.
- Writes one workflow for pull-request preview deploys.
- Optionally writes one workflow for live deploys when changes land on your chosen branch.
Treat the service account like production access
Never paste the service account JSON into a workflow file. Keep it in GitHub secrets, rotate it if it leaks, and delete stale secrets when you move repositories or Firebase projects.
5. Preview workflow for pull requests
The generated preview workflow usually lives in .github/workflows/firebase-hosting-pull-request.yml. A simple 2026 version looks like this:
name: Deploy Firebase Hosting preview
on:
pull_request:
permissions:
checks: write
contents: read
pull-requests: write
jobs:
build_and_preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: ${{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_YOUR_PROJECT_ID }}
projectId: your-project-id
expires: 30dThe repoToken lets the action comment on the pull request with the preview URL. The preview URL updates as you push more commits to the same PR, so reviewers keep using one link.
6. Live workflow for your main branch
Use a separate live workflow for pushes to main. Keep this boring and predictable.
name: Deploy Firebase Hosting live
on:
push:
branches:
- main
permissions:
contents: read
jobs:
build_and_deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
firebaseServiceAccount: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_YOUR_PROJECT_ID }}
projectId: your-project-id
channelId: liveIf your default branch is master, production, or a release branch, change the branch name. If your app lives in a subdirectory, add the right working-directory to build steps and use the action's entryPoint option for the folder containing firebase.json.
7. Understand live and preview channels
Firebase Hosting has a live channel for production and optional preview channels for temporary review builds. Preview channels are perfect for pull requests because they expose the exact built assets and Hosting config that reviewers need to test.
One important gotcha: a preview URL still talks to your real Firebase backend unless your app is explicitly configured to use staging resources. If a pull request can write to Firestore, call Cloud Functions, or hit production APIs, protect those paths with rules, staging projects, feature flags, or emulator-only local testing.
8. Framework-specific notes
Vite, React, Vue, and Svelte
Most Vite-style apps build to dist. Your firebase.json usually needs this Hosting block:
{
"hosting": {
"public": "dist",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{ "source": "**", "destination": "/index.html" }
]
}
}Create React App
Use build as the public directory and keep the same rewrite for client-side routing.
Static HTML sites
If your repo already serves files from public, you may not need a build step. Remove npm ci and npm run build only if the deployed directory is committed and complete.
9. Troubleshooting checklist
- 404 after deploy: confirm
firebase.jsonpoints at the build output directory, not your source directory. - Blank app: inspect the browser console and confirm asset paths match your router or base path settings.
- Action cannot find a Firebase project: set
projectIdin the action or commit a correct.firebaserc. - Permission denied: rerun
firebase init hosting:githubor rotate the service account secret. - PR comment missing: include
repoTokenand grantpull-requests: writepermissions in the workflow. - Wrong Node version: pin the same Node major in GitHub Actions that you use locally.
10. Production checklist
- Run
npm ciin CI so installs are reproducible frompackage-lock.json. - Run tests, linting, or type checks before the deploy action.
- Use preview channels for every pull request.
- Deploy live only from a protected branch.
- Limit GitHub workflow permissions to what the workflow needs.
- Keep production Firebase config separate from staging config when backend writes matter.
- Document where the GitHub secret came from and who can rotate it.
Once this is in place, deploying becomes simple: open a pull request, review the Firebase preview URL, merge when it looks good, and let the live workflow publish the exact code that landed on your production branch.