Back to Tutorials

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.

June 1, 2026 12 min read Paddy B
Firebase Hosting GitHub Actions CI/CD Preview Channels Deployment

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@latest or a global firebase-tools install.
  • A known build command and output directory, for example npm run build and dist, build, or public.

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:list

If you prefer a global install, keep it current and confirm the version before setup.

npm install -g firebase-tools firebase --version firebase login

3. Initialize Firebase Hosting

For a brand-new Hosting setup, run the full Hosting initializer from the repository root.

npx firebase-tools@latest init hosting

The 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.html unless 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:github

4. 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: 30d

The 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: live

If 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.json points 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 projectId in the action or commit a correct .firebaserc.
  • Permission denied: rerun firebase init hosting:github or rotate the service account secret.
  • PR comment missing: include repoToken and grant pull-requests: write permissions in the workflow.
  • Wrong Node version: pin the same Node major in GitHub Actions that you use locally.

10. Production checklist

  • Run npm ci in CI so installs are reproducible from package-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.