DEV Community

Udara Dananjaya
Udara Dananjaya

Posted on

Automating Vue.js App Deployment to Firebase Hosting with GitHub Actions Without npm firebase-tools

Deploying a web app efficiently is a game-changer for developers. For my financial project management system (PMS) built with Vue.js, I wanted to streamline deployments using Firebase Hosting and GitHub Actions, but without relying on the firebase-tools npm package for initialization. This approach is useful if you want to avoid installing additional npm dependencies or prefer manual configuration for more control. Below, I’ll walk you through the process I used to set up automated deployments, leveraging GitHub Actions for CI/CD and Firebase Hosting for a fast, scalable static site.

This guide assumes you’re comfortable with GitHub, Firebase, and basic terminal commands, and it mirrors the steps I took to achieve a seamless pipeline. We’ll manually configure Firebase, set up GitHub Actions workflows, and automate builds and deployments—all without npm install firebase-tools.

Prerequisites

Before starting, ensure you have:

  • Node.js and npm installed (for building your app, e.g., npm run build).
  • A GitHub repository for your project (mine is a Vue.js app, but this works for any static site).
  • A Firebase project created in the Firebase Console.
  • Your app’s build output in a dist folder (common for Vue CLI projects).
  • A local Git repository synced with GitHub.
  • A Firebase service account JSON key (downloadable from Firebase Console).

Step 1: Set Up Firebase Hosting Manually

Without the Firebase CLI, we’ll configure Firebase Hosting by creating the necessary files manually.

Create firebase.json

In your project root (e.g., the deployment folder), create a firebase.json file to define Hosting settings. For a Vue.js single-page app (SPA), I used:

{
  "hosting": {
    "public": "dist",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode
  • public: Specifies the dist folder, where npm run build outputs your app.
  • ignore: Excludes files from deployment (e.g., config and hidden files).
  • rewrites: Routes all URLs to index.html for SPA functionality.

Create .firebaserc

To link your project to Firebase, create a .firebaserc file in the root:

{
  "projects": {
    "default": "your-project-id"
  }
}
Enter fullscreen mode Exit fullscreen mode

Replace your-project-id with your Firebase project ID from the Firebase Console (e.g., finagle-pms-test in my case). You can find it under Project settings > General.

Update .gitignore

Add Firebase-related files to .gitignore to avoid committing sensitive data:

.firebase/
firebaserc
node_modules/
Enter fullscreen mode Exit fullscreen mode

If .gitignore doesn’t exist, create it. This ensures your local Firebase cache and node modules aren’t pushed to GitHub.

Generate a Service Account Key

  1. Go to the Firebase Console.
  2. Navigate to Project settings > Service accounts.
  3. Click Generate new private key to download a JSON file (e.g., your-project-id-firebase-adminsdk-xyz.json).
  4. Store this securely—you’ll need it for GitHub Actions.

Step 2: Test Your Build Locally

Ensure your app builds correctly:

npm run build
Enter fullscreen mode Exit fullscreen mode

This should generate a dist folder with your static assets (e.g., index.html, JS, and CSS files). If you’re using Vue CLI, this is typically configured out of the box. Verify dist/index.html exists, as Firebase Hosting will serve it.

Step 3: Set Up GitHub Actions for CI/CD

Without firebase-tools, we’ll manually create GitHub Actions workflows to build and deploy to Firebase Hosting. These workflows will handle pull request previews and live deployments on merge.

Add Service Account Key to GitHub Secrets

  1. Go to your GitHub repository: https://github.com/your-org/your-repo.
  2. Navigate to Settings > Secrets and variables > Actions > New repository secret.
  3. Name the secret FIREBASE_SERVICE_ACCOUNT_YOUR_PROJECT_ID (replace YOUR_PROJECT_ID with your Firebase project ID, e.g., FINAGLE_PMS_TEST).
  4. Paste the entire JSON content of the service account key you downloaded.

Create Workflow for Pull Requests

In your project root, create a folder: .github/workflows/firebase-hosting-pull-request.yml. Add:

name: Deploy to Firebase Hosting on PR

on:
  push:
    branches:
      - master  # Deploy to live when changes are pushed to master
  pull_request:
    branches:
      - master  # Deploy to preview on PRs targeting master
permissions:
  checks: write
  contents: read
  pull-requests: write

jobs:
  build_and_deploy‎:
    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: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_YOUR_PROJECT_ID }}'
          projectId: your-project-id
  # Conditional for the event type
          channelId: ${{ github.event_name == 'push' && 'live' || 'pr' }}  # 'live' for push to master, 'pr' for pull request
Enter fullscreen mode Exit fullscreen mode

Replace your-project-id with your Firebase project ID. This workflow:

  • Triggers on pull requests to the master branch.
  • Checks out code, sets up Node.js, installs dependencies, and builds the app.
  • Deploys to a Firebase Hosting preview channel using the service account.

Create Workflow for Live Deployment

Create another file: .github/workflows/firebase-hosting-merge.yml:

name: Deploy to Firebase Hosting on merge
'on':
  push:
    branches:
      - master
jobs:
  build_and_deploy:
    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: FirebaseExtended/action-hosting-deploy@v0
        with:
          repoToken: '${{ secrets.GITHUB_TOKEN }}'
          firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_YOUR_PROJECT_ID }}'
          channelId: live
          projectId: your-project-id
Enter fullscreen mode Exit fullscreen mode

This triggers on pushes to master, deploying to the live Firebase Hosting channel.

Step 4: Push and Test the Workflows

Commit and push your changes:

git add .
git commit -m "Add Firebase Hosting config and GitHub Actions workflows"
git push origin master
Enter fullscreen mode Exit fullscreen mode

Create a feature branch and open a pull request. Check the Actions tab in your GitHub repo to see the PR workflow run. It will:

  1. Build your app (npm run build).
  2. Deploy to a Firebase Hosting preview URL (visible in the Action logs).

Merge the PR, and the merge workflow will deploy to the live site.

Step 5: Verify Deployment

After the workflows run:

  • Preview: Find the preview URL in the GitHub Actions logs (e.g., https://your-project-id--preview-channel.web.app).
  • Live: Visit your live site (e.g., https://your-project-id.web.app) after merging.

Ensure your Vue.js app loads correctly, with all routes handled by index.html.

Troubleshooting

  • Build fails? Verify npm run build works locally and outputs to dist.
  • Secret errors? Double-check the service account key in GitHub Secrets.
  • 404 on routes? Confirm the rewrites rule in firebase.json.
  • Permission issues? Ensure the service account has Firebase Hosting Admin permissions in the Firebase Console.
  • Vue-specific: If using environment variables, add them to GitHub Secrets and reference them in the workflow (e.g., env: VUE_APP_API_KEY: ${{ secrets.VUE_APP_API_KEY }}).

Why This Approach Wins

This setup streamlined my PMS deployments without relying on firebase-tools. It’s lightweight, avoids extra npm dependencies, and gives you full control over configuration. Firebase Hosting offers a global CDN, free SSL, and generous free tier, while GitHub Actions provides cost-free CI/CD for public repos. Previews on PRs catch issues early, and live deploys are instant on merge.

Try this for your next project! What’s your favorite way to automate deployments? Share below.

Originally published on October 15, 2025. Crafted with Vue.js and Firebase Hosting.

Top comments (0)