firebase.json Builder

Generate a Firebase Hosting config with rewrites and cache headers

Build a valid firebase.json for Firebase Hosting with a public directory, SPA rewrites, immutable cache headers for hashed assets, clean URLs, trailing-slash control, and ignore patterns — copy or download instantly. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What does the public directory in firebase.json do?

The public key tells Firebase Hosting which folder contains the static files to deploy. For most modern build tools this is dist or build. Everything inside it is uploaded and served from your hosting site.

A correct firebase.json without the guesswork

Firebase Hosting is configured by a single firebase.json file, and small mistakes — a wrong public directory, a missing SPA rewrite, or no cache headers — lead to 404s on deep links or stale assets after deploys. This builder assembles a valid config from a few toggles so your first firebase deploy works.

How it works

The tool writes a hosting object. The public key points at your build folder, and ignore excludes firebase.json and dotfiles (plus node_modules if you want). When the single-page-app option is on, it adds a catch-all rewrite that maps ** to /index.html, so client-side routes resolve instead of 404ing. The cache-header block applies Cache-Control: public, max-age=<seconds>, immutable to hashed static assets (js, css, fonts, images) while forcing no-cache on index.html, which is the standard pattern for content-hashed builds. cleanUrls and trailingSlash map directly to Firebase’s own options.

Example output and what each section does

Here is a representative firebase.json for a Vite React SPA:

{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      {
        "source": "/index.html",
        "headers": [{ "key": "Cache-Control", "value": "no-cache" }]
      },
      {
        "source": "**/*.@(js|css|woff2|png|jpg|svg)",
        "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
      }
    ],
    "cleanUrls": true,
    "trailingSlash": false
  }
}

Key decisions explained

public: "dist" — Vite outputs to dist; Create React App uses build. If you point at the wrong folder, firebase deploy will succeed but serve an empty or wrong site.

rewrites: [{ source: "**", destination: "/index.html" }] — without this, navigating directly to /about returns a 404 because no physical about.html file exists. The rewrite hands all unmatched requests to index.html so React Router (or any other client router) handles the path.

Cache headers splitindex.html must stay uncached (no-cache) so browsers pick up new deployments immediately. Static assets with content hashes in their names (like main.4f3a8b.js) never change, so they can be cached for a year with immutable. Without this split, either users get stale JS after a deploy, or they download unchanged assets on every page load.

cleanUrls: true — serves about.html at /about instead of /about.html, and 301-redirects the .html version. Primarily useful for multi-page static sites, not SPAs with the catch-all rewrite.

trailingSlash: false — normalises URLs so /about/ redirects to /about. Keep consistent with whatever your router expects.

Common mistakes to avoid

  • Using "source": "**" in headers before the index.html rule causes the more specific rule to never match. In Firebase Hosting, the first matching header rule wins, so put specific paths before wildcards.
  • Setting a year-long cache on files without content hashes will cause users to receive stale code after deploys until their browser cache expires.
  • The rewrite for SPAs and cleanUrls do the same job in different situations — enable the rewrite for SPAs, cleanUrls for MPA static sites, but not necessarily both.

The generated JSON is standard and can be extended later with redirects, additional security headers, or multiple named hosting targets for preview channels.