DeployHQ Static Hosting serves pre-built static assets from Cloudflare's global edge — a clean fit for a Firebase Studio project, where Gemini Code Assist scaffolds a Next.js, Angular, or Vite-based frontend that builds to a flat output directory. This guide walks through deploying a Firebase Studio app end to end: sync the workspace to GitHub, configure the framework for static export, provision Static Hosting, set up the build pipeline, update Firebase Auth's authorized domains, and ship the first deploy.
The framing matters: Static Hosting replaces the Firebase Hosting URL Firebase Studio provisions by default, not the Firebase backend behind it. Firebase Auth still issues tokens. Firestore still stores data. Cloud Functions still run on Google's infrastructure. Static Hosting is the public face — a faster, lock-in-free home for the frontend bundle that calls all of it. The one exception: if you've enabled Firebase App Hosting (which provisions a Cloud Run instance for SSR), that runtime is bound to Google Cloud and can't move to Static Hosting. For static-export builds, you're good — keep reading.
What you'll build
By the end of this guide:
- A Firebase Studio workspace synced to your own GitHub repository
- A DeployHQ project with Static Hosting connected to that repo
- A framework configured for static output (Next.js export, Vite build, Angular
--configuration production, etc.) - A working build pipeline that runs your framework's build and uploads the output to Cloudflare's edge
- Firebase Auth authorized domains updated to include the new URL
- The site serving over HTTPS at
<subdomain>.deployhq-sites.com(and optionally a custom domain) - Atomic deploys on every push to
main, with one-click rollback to any previous version
Expected time: under 20 minutes from a Firebase Studio workspace you already have set up.
Prerequisites
- A Firebase Studio workspace — created at firebase.studio — with a working frontend and a Firebase project providing whatever services it uses (Auth, Firestore, Storage, Functions)
- A GitHub account you can sync the workspace to
- Access to the Firebase project's console (you'll update Auth authorized domains in Step 7)
- A DeployHQ account with beta features enabled (enable under Settings > Beta Features)
- Node.js installed locally if you want to test the build before pushing (optional but recommended)
If you don't have a DeployHQ account yet, you can start a free trial in the next step — the trial includes one Static Hosting site at no charge while the feature is in beta.
Step 1: Sync your Firebase Studio workspace to GitHub
Firebase Studio runs your workspace in a Nix-based environment in the browser, with the source code stored in a Google Cloud workspace. To deploy on DeployHQ, the code needs to live in a normal Git repository.
In Firebase Studio:
- Open the workspace you want to deploy
- Open the Source Control panel from the left sidebar
- Click Publish to GitHub (or Sync if you've already connected a repo)
- Authorize Firebase Studio's GitHub integration if you haven't already
- Choose a repository name and visibility, then publish
Firebase Studio commits the workspace contents — package.json, framework config files, src/, the dev.nix environment file under .idx/, and any Firebase configuration files (firebase.json, .firebaserc) — to the main branch of the new repository.
Open the repo in GitHub and confirm package.json is at the root. You'll identify the build command and output directory in the next step.
Step 2: Configure the framework for static output
Firebase Studio scaffolds projects across several frameworks. The right Static Hosting configuration depends on which template the workspace started from. Two things to verify: the build command and the output directory.
| Framework | Default build command | Output directory | Static-ready out of the box? |
|---|---|---|---|
| Next.js (App Router) | npm run build |
out/ |
No — set output: 'export' in next.config.js |
| Angular | npm run build |
dist/<project-name>/browser/ |
Yes |
| Vite + React | npm run build |
dist/ |
Yes |
| Vite + Vue | npm run build |
dist/ |
Yes |
| Astro | npm run build |
dist/ |
Yes |
| Flutter web | flutter build web |
build/web/ |
Yes |
For the Next.js case specifically, open next.config.js (or next.config.mjs) and add:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
unoptimized: true,
},
};
module.exports = nextConfig;
This switches Next.js from SSR mode to a static export written to out/. Any code path using getServerSideProps, server actions, route handlers, or App Router server components will fail the build — those features need a runtime Static Hosting doesn't provide. The images.unoptimized: true flag disables Next.js Image Optimization, which also needs a server.
If your workspace uses firebase.json to define Firebase Hosting rewrites — single-page-app fallbacks, URL redirects, custom headers — those won't apply on DeployHQ. SPA rewrite is handled by Static Hosting's SPA mode (Step 4), and Cloudflare's edge handles HTTPS and caching headers automatically.
Step 3: Verify the Firebase configuration
Firebase Studio apps initialize the Firebase JS SDK with a config object usually pulled from environment variables (NEXT_PUBLIC_FIREBASE_* for Next.js, VITE_FIREBASE_* for Vite, process.env.NG_APP_FIREBASE_* for Angular).
Open the Firebase initialization file (src/lib/firebase.ts, src/firebase.ts, or wherever your workspace puts it) and confirm it reads from environment variables rather than hardcoded values. The relevant variables are:
*_FIREBASE_API_KEY— public API key (safe in client bundles)*_FIREBASE_AUTH_DOMAIN— typically<project-id>.firebaseapp.com*_FIREBASE_PROJECT_ID*_FIREBASE_STORAGE_BUCKET*_FIREBASE_MESSAGING_SENDER_ID*_FIREBASE_APP_ID
These are all designed to be public — Firebase enforces security at the service level via Firestore Security Rules, Storage Rules, and Firebase Auth, not by hiding the config.
If your project calls Cloud Functions, the function URLs use the Firebase project's default domain (https://<region>-<project-id>.cloudfunctions.net or https://<custom-domain>.cloudfunctions.net). Those calls work from any frontend host as long as the function's CORS is configured to allow your origin (covered in Step 7 and the gotchas section).
Step 4: Provision a Static Hosting site in DeployHQ
In your DeployHQ project (or create one and connect it to the Firebase Studio repository), click New Server:
- Enter a name for the server — internal reference only, doesn't affect the public URL
- Select Static Hosting from the protocol picker under Hosting
- Choose a subdomain — your site serves at
<subdomain>.deployhq-sites.com. Subdomains are unique across all DeployHQ accounts; lowercase letters, numbers, and hyphens only - Set the subdirectory to deploy from to match your framework's output directory from Step 2 (
out/,dist/,dist/<project-name>/browser/, orbuild/web/) - Toggle SPA mode based on your framework:
- On for Angular, Vite + React/Vue SPAs, Flutter web — these use client-side routing and need unknown paths rewritten to
index.html - Off for Next.js static export and Astro — these generate one HTML file per route at build time
- On for Angular, Vite + React/Vue SPAs, Flutter web — these use client-side routing and need unknown paths rewritten to
- Click Create Server
DeployHQ runs framework detection against the connected repository. If a [Framework] detected!
callout appears with a suggested output directory and SPA mode, the rule-based detector is doing the work for you. Accept the suggested values unless your framework config diverges from the defaults.
Provisioning takes under a minute. Once the status flips to active, the site exists on Cloudflare's edge — but no code has shipped yet.
Step 5: Configure the build pipeline
DeployHQ runs your build before transferring artifacts to the edge. For a Firebase Studio-exported project, the build pipeline is two stages: install, then build.
In the project's build settings, add:
npm ci
npm run build
For Flutter, swap to the Flutter SDK install + flutter build web instead. For Angular projects with environment-specific builds, you may need npm run build -- --configuration production.
Environment variables to set in DeployHQ's environment-variable UI — the prefix depends on your framework:
- Next.js:
NEXT_PUBLIC_FIREBASE_API_KEY,NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, etc. - Vite + React/Vue:
VITE_FIREBASE_API_KEY,VITE_FIREBASE_AUTH_DOMAIN, etc. - Angular:
NG_APP_FIREBASE_API_KEYetc. (or environment.ts files if you're using the older pattern)
What you should not put here: Firebase Admin SDK service-account JSON, Firebase Functions deployment tokens, any credential that grants server-side access. Those belong in Cloud Functions runtime config, never in a static bundle.
If your project also uses third-party services (Stripe publishable keys, Sentry DSN, public analytics IDs), they go here too — same prefix rules apply.
Ready to take it live? Sign up free for DeployHQ if you don't have an account, and the beta-tier Static Hosting site is enough to ship this guide end to end.
Step 6: First deploy
Push any change to the configured branch (typically main), or trigger a manual deployment from the DeployHQ dashboard. DeployHQ:
- Clones the repo at the head of the configured branch
- Runs the build pipeline (
npm ci && npm run build) - Uploads the contents of your output directory to object storage atomically
- Flips Cloudflare's edge routing to serve the new version
The deployment log streams each step in real time. When it completes, visit https://<subdomain>.deployhq-sites.com — the site loads, but Firebase Auth won't yet allow sign-ins from the new domain. That's Step 7.
If the build fails, the log shows the exact error. Most common failures for Firebase Studio projects:
- A Next.js page or route handler using a server-only feature without
output: 'export'configured - A missing
*_FIREBASE_*env var the client bundle references at build time - A
firebase.jsondeclaring a Cloud Functions rewrite the static export can't fulfill - An Angular project building without the production configuration, leaving development-only checks in the bundle
Fix the issue in the repo, commit, push — DeployHQ runs the next build automatically.
Step 7: Update Firebase Auth authorized domains
Firebase Auth has an allowlist of authorized domains — sign-in flows only work from domains on that list. Until your new domain is added, OAuth providers (Google, Facebook, GitHub) and email-link sign-ins will reject the authentication request.
In the Firebase Console:
- Open the project that backs this app
- Navigate to Authentication > Settings > Authorized domains
- Click Add domain and enter
<subdomain>.deployhq-sites.com(and any custom domain you'll add in Step 8) - Save
Existing entries like localhost, your old Firebase Hosting domain, and any previously configured custom domains stay on the list — Firebase Auth allows multiple authorized domains, so the Firebase Studio preview environment continues to work.
Sign out, sign back in on the new domain, and confirm the auth flow round-trips correctly.
Step 8: Add a custom domain
To serve from your own domain (e.g., app.example.com):
- In your DNS provider, add a
CNAMErecord pointing your subdomain to<subdomain>.deployhq-sites.com - Wait for DNS propagation (usually minutes; depends on your TTL)
- Cloudflare provisions an HTTPS certificate automatically once the CNAME resolves
- Add the custom domain to Firebase Auth's authorized domains list (same path as Step 7) so OAuth flows from
app.example.comround-trip correctly
Your site now serves from app.example.com over HTTPS via Cloudflare's edge, talking to the same Firebase backend Firebase Studio scaffolded for you.
For an apex domain (example.com with no subdomain), use an ALIAS or ANAME record if your DNS provider supports them — Cloudflare DNS, DNSimple, and Route 53 all do. Otherwise, host the apex elsewhere and CNAME a www subdomain to DeployHQ.
Common gotchas
Firebase Studio App Hosting
isn't supported. Firebase App Hosting is Firebase's newer SSR offering — it provisions a Cloud Run instance per deployment. That runtime is fundamentally Google-bound. If your workspace was scaffolded for App Hosting, you're locked into Firebase Hosting until you switch to a static-export configuration. Static Hosting is for static export only.
OAuth provider rejects the new domain. Google sign-in, Facebook sign-in, GitHub sign-in, and other federated providers have their own allowlists in addition to Firebase Auth's authorized domains list. Open each provider's app/credentials page (Google Cloud Console, Facebook Developers, GitHub OAuth Apps) and add the new Firebase Auth callback URL — usually https://<project-id>.firebaseapp.com/__/auth/handler — to the authorized redirect URIs. The error usually shows up as a redirect_uri_mismatch in the provider's response.
Cloud Functions return CORS errors. Cloud Functions enforce origin allowlists. Update the function's CORS configuration (typically via the cors package in your function source, or via Firebase Hosting rewrites that proxy through firebase.json — which doesn't apply here). For DeployHQ-hosted frontends, configure CORS directly in the function code to accept your new domain.
Firestore queries return empty results in production. Almost always a Firestore Security Rules mismatch. The Firebase Studio preview environment sometimes uses a different auth context. Check the rules on the affected collections and confirm they allow the production user's auth claims.
Build succeeds but environment variables don't appear in the bundle. Each framework requires a specific prefix at build time: Next.js needs NEXT_PUBLIC_*, Vite needs VITE_*, Angular reads from a separate environment.production.ts file by default. Double-check (a) the variable names match the prefix exactly, (b) you triggered a new build after setting them, and (c) for Angular, you're building with the production configuration.
firebase.json rewrites don't apply. Firebase Hosting's rewrites array configures the SPA fallback, URL redirects, and Cloud Function proxying. None of that runs on Static Hosting. Use DeployHQ's SPA mode for the SPA fallback. For Cloud Function proxying, point the frontend directly at the Cloud Function URL instead of relying on a /api/* rewrite.
Next.js next/image falls back to <img>. Static export disables Next.js Image Optimization. For better performance, pre-optimize at build time with sharp or next-export-optimize-images, or use an image CDN (Cloudflare Images, Imgix, Cloudinary).
What you've shipped
You now have:
- A Firebase Studio frontend rebuilding on every push to
main - Atomic deploys with no downtime during the transfer
- HTTPS over Cloudflare's edge with automatic certificate management
- One-click rollback to any previous deployment from the DeployHQ dashboard
- Firebase Auth, Firestore, Storage, and Cloud Functions unchanged, doing exactly what they did before
- A clean separation between the static UI and Google's backend services
For the broader context of how Static Hosting fits among DeployHQ's other hosting types, see the hosting hub. The Static Hosting pillar guide covers framework auto-detection, SPA mode, and the head-to-head against the most common alternatives. If you're weighing your hosting options more broadly, our DeployHQ Static Hosting vs Vercel comparison is a useful next read for the Next.js side of Firebase Studio projects.
What's next
If your Firebase Studio project outgrows static export — you need real SSR, server-rendered routes you can't move to client-side rendering, or a Node service that doesn't fit the Cloud Functions model — there are two clean upgrade paths inside the same DeployHQ project:
- Move SSR rendering to DeployHQ Managed VPS and keep using Firebase services on the backend. The DeployHQ pipeline ships to either target; you swap the server type, not the project.
- Split: keep Static Hosting for the public UI, run dynamic parts on Managed VPS or BYO server. The static frontend stays on Cloudflare's edge; the SSR layer runs elsewhere; Firebase services keep doing their thing.
Either path, the build pipeline you set up here continues to work — DeployHQ's build is generic, the target is what swaps.
Built your app with a different AI tool? Bolt, Lovable, and v0 export the same kind of static frontend, each with its own per-tool quirks — our free static hosting for AI-built apps roundup maps where each builder leaves you and how to host the result without lock-in.
For a roundup of how DeployHQ fits alongside the rest of the deployment-tool category, our best software deployment tools in 2026 post is a useful reference. And for context on the broader DeployHQ proposition across all five hosting types it supports, see your universal deployment and hosting platform.
If you're sizing what's included before signing up, the DeployHQ pricing page lays out which plan covers what — the beta-tier Static Hosting site is enough to ship this guide end to end. For the full product reference, see the Static Hosting support library.
Questions or feedback on deploying Firebase Studio apps to DeployHQ Static Hosting? Email support@deployhq.com or follow @deployhq on X for product updates.