Use Firebase as a full Backend-as-a-Service alternative to Supabase in Bolt.new by installing the firebase npm package and initializing Firestore, Auth, and Storage. The Firebase JS SDK communicates over HTTP and WebSocket — fully compatible with Bolt's WebContainer. Note: choosing Firebase means losing Bolt's native Stripe integration, which requires Supabase edge functions. Firestore real-time listeners work in the preview; OAuth login requires a deployed URL.
Use Firebase as a Full Backend Alternative in Bolt.new
Firebase is the most popular alternative to Supabase for Bolt.new projects. Its JavaScript SDK communicates over HTTP and WebSocket — matching Bolt's WebContainer architecture perfectly, unlike raw TCP database drivers that fail in the browser-based runtime. Firestore's real-time document listeners even work in the preview environment, making live data development unusually smooth. Storage file uploads, authentication flows, and Cloud Functions calls all work through the same HTTP-based SDK.
The key trade-off to understand before choosing Firebase: Bolt.new's native Stripe payment integration is built around Supabase edge functions. If your project needs payments, choosing Firebase as your backend means you lose access to Bolt's one-click Stripe setup and must implement payments manually via Next.js API routes or your own Cloud Functions. If your project doesn't need payments, or you're comfortable with manual Stripe setup, Firebase is an excellent choice — particularly for teams already in the Google ecosystem or applications that benefit from Firebase's real-time database capabilities.
Firebase's document/collection data model differs from Supabase's relational PostgreSQL. It excels at hierarchically organized data (users → posts → comments), real-time collaboration features, and apps that need to work offline. It's less suited for complex relational queries, server-side aggregations, or applications where SQL's expressiveness matters. Bolt's AI understands both backends well — clearly stating 'Use Firebase' in your prompts keeps the AI generating Firebase SDK code rather than Supabase patterns.
Integration method
Firebase's JavaScript SDK communicates over HTTP and WebSocket protocols, making it fully compatible with Bolt's WebContainer runtime — no TCP sockets required. Install the firebase npm package, initialize with your project config, and use Firestore, Auth, and Storage directly from client-side code or server-side API routes. Real-time Firestore listeners work even in Bolt's preview. Social OAuth login requires a deployed URL for redirect URI registration.
Prerequisites
- A Google account to access the Firebase Console at console.firebase.google.com
- A Firebase project created with Firestore, Authentication, and Storage enabled
- Your Firebase web app configuration object (from Project Settings → Your apps)
- A Bolt.new project (Vite or Next.js — both work with the Firebase JS SDK)
- Basic understanding of NoSQL document/collection data modeling
Step-by-step guide
Create a Firebase Project and Get Configuration
Create a Firebase Project and Get Configuration
Go to console.firebase.google.com and click 'Add project'. Name your project, optionally enable Google Analytics, and click 'Create project'. Once created, click the web app icon (`</>`) in the Project Overview to register a web app. Give it a nickname (e.g., 'Bolt App') and click 'Register app'. Firebase shows your configuration object — a JavaScript object with apiKey, authDomain, projectId, storageBucket, messagingSenderId, and appId. Copy the entire config object. Next, enable the services you need: in the left sidebar, click 'Firestore Database' → 'Create database' → select a region → choose 'Start in test mode' for development (you'll tighten security rules before production). Click 'Authentication' → 'Get started' → enable Email/Password and optionally Google sign-in. Click 'Storage' → 'Get started' → 'Start in test mode'. Test mode allows all reads and writes without authentication — fine for development, but set proper security rules before going live. Your Firebase config values are safe to include in client-side code (they're designed to be public) — the apiKey is a project identifier, not a secret. Security is enforced through Firestore Security Rules, not by keeping the config private.
Set up Firebase in my Bolt.new app. Install the firebase npm package. Create a lib/firebase.ts file that initializes Firebase with my config stored in environment variables (NEXT_PUBLIC_FIREBASE_API_KEY, NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, NEXT_PUBLIC_FIREBASE_PROJECT_ID, NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET, NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID, NEXT_PUBLIC_FIREBASE_APP_ID). Export the initialized app, db (Firestore), auth, and storage instances.
Paste this in Bolt.new chat
1// lib/firebase.ts2import { initializeApp, getApps } from 'firebase/app';3import { getFirestore } from 'firebase/firestore';4import { getAuth } from 'firebase/auth';5import { getStorage } from 'firebase/storage';67const firebaseConfig = {8 apiKey: import.meta.env.VITE_FIREBASE_API_KEY,9 authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,10 projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,11 storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,12 messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,13 appId: import.meta.env.VITE_FIREBASE_APP_ID,14};1516// Prevent re-initialization on hot reload17const app = getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0];1819export const db = getFirestore(app);20export const auth = getAuth(app);21export const storage = getStorage(app);22export default app;Pro tip: Use VITE_ prefix for environment variables in Vite projects (Bolt's default). For Next.js projects, use NEXT_PUBLIC_ prefix. Firebase config values are designed to be public — security is enforced by Firestore/Storage rules, not by hiding the config.
Expected result: Firebase is initialized. The db, auth, and storage exports are ready to use throughout your app.
Implement Firestore CRUD with Real-Time Listeners
Implement Firestore CRUD with Real-Time Listeners
Firestore's document database organizes data into collections and documents — conceptually similar to a folder (collection) containing files (documents), where each file has key-value fields. CRUD operations use `addDoc`, `setDoc`, `updateDoc`, `deleteDoc`, and `getDoc` from `firebase/firestore`. The standout feature for Bolt development is `onSnapshot` — a real-time listener that fires whenever data changes. Unlike polling, onSnapshot pushes updates from Firebase to your app instantly, and this works in Bolt's WebContainer preview environment. Each listener returns an unsubscribe function — call it in a React cleanup function to prevent memory leaks. Firestore queries support filtering (`where`), ordering (`orderBy`), and limiting (`limit`), but compound queries (filtering on multiple fields) require composite indexes created in the Firebase Console. If a query returns a 'requires index' error with a link, clicking that link auto-creates the index.
Create a Firestore tasks collection with real-time updates. Build a React hook useTasks() in hooks/useTasks.ts that subscribes to the tasks collection using onSnapshot, returns the current list of tasks, and unsubscribes on cleanup. Export CRUD functions: addTask(title, description), updateTask(id, changes), and deleteTask(id). Use the db export from lib/firebase.ts.
Paste this in Bolt.new chat
1// hooks/useTasks.ts2import { useState, useEffect } from 'react';3import {4 collection,5 onSnapshot,6 addDoc,7 updateDoc,8 deleteDoc,9 doc,10 orderBy,11 query,12 serverTimestamp,13} from 'firebase/firestore';14import { db } from '@/lib/firebase';1516export interface Task {17 id: string;18 title: string;19 description: string;20 status: 'todo' | 'in-progress' | 'done';21 createdAt: Date | null;22}2324export function useTasks() {25 const [tasks, setTasks] = useState<Task[]>([]);26 const [loading, setLoading] = useState(true);2728 useEffect(() => {29 const q = query(collection(db, 'tasks'), orderBy('createdAt', 'desc'));30 const unsubscribe = onSnapshot(q, (snapshot) => {31 const taskList = snapshot.docs.map((doc) => ({32 id: doc.id,33 ...doc.data(),34 createdAt: doc.data().createdAt?.toDate() ?? null,35 })) as Task[];36 setTasks(taskList);37 setLoading(false);38 });39 return () => unsubscribe();40 }, []);4142 return { tasks, loading };43}4445export async function addTask(title: string, description: string) {46 return addDoc(collection(db, 'tasks'), {47 title,48 description,49 status: 'todo',50 createdAt: serverTimestamp(),51 });52}5354export async function updateTask(id: string, changes: Partial<Task>) {55 return updateDoc(doc(db, 'tasks', id), changes);56}5758export async function deleteTask(id: string) {59 return deleteDoc(doc(db, 'tasks', id));60}Pro tip: Firestore's onSnapshot works in Bolt's WebContainer preview — you can see real-time updates between two browser tabs during development, making it easier to test collaborative features before deploying.
Expected result: The useTasks hook subscribes to Firestore changes in real time. Opening two browser tabs and adding a task in one immediately shows it in the other.
Add Firebase Authentication
Add Firebase Authentication
Firebase Authentication handles user sign-up, login, and session management. The `onAuthStateChanged` listener from `firebase/auth` is the canonical way to track the current user across page refreshes — Firebase stores the session in IndexedDB and automatically restores it. Email/password authentication works fully in Bolt's WebContainer preview. Google Sign-In, GitHub, and other OAuth providers redirect to an external authorization page — this redirect works in the preview, but the OAuth provider must have your app's URL registered as an authorized redirect URI. The preview URL is dynamic and changes between sessions, so you cannot pre-register it in Google Cloud Console or GitHub OAuth apps. For social login, either test on your deployed URL or use `signInWithPopup` instead of `signInWithRedirect` — popups work in the preview without redirect URI registration. Set up an AuthContext to make the current user available throughout your app via React context.
Add Firebase Authentication to my app. Create contexts/AuthContext.tsx with an AuthProvider that wraps the app and provides the current Firebase user via useAuth() hook using onAuthStateChanged. Create an auth utilities file lib/auth.ts with functions: signUpWithEmail(email, password), signInWithEmail(email, password), signInWithGoogle() using signInWithPopup, and signOut(). Build a LoginPage component with tabs for sign-in and sign-up.
Paste this in Bolt.new chat
1// contexts/AuthContext.tsx2import { createContext, useContext, useEffect, useState, ReactNode } from 'react';3import { User, onAuthStateChanged } from 'firebase/auth';4import { auth } from '@/lib/firebase';56interface AuthContextValue {7 user: User | null;8 loading: boolean;9}1011const AuthContext = createContext<AuthContextValue>({ user: null, loading: true });1213export function AuthProvider({ children }: { children: ReactNode }) {14 const [user, setUser] = useState<User | null>(null);15 const [loading, setLoading] = useState(true);1617 useEffect(() => {18 const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {19 setUser(firebaseUser);20 setLoading(false);21 });22 return () => unsubscribe();23 }, []);2425 return (26 <AuthContext.Provider value={{ user, loading }}>27 {children}28 </AuthContext.Provider>29 );30}3132export function useAuth() {33 return useContext(AuthContext);34}3536// lib/auth.ts37import {38 createUserWithEmailAndPassword,39 signInWithEmailAndPassword,40 signInWithPopup,41 GoogleAuthProvider,42 signOut as firebaseSignOut,43} from 'firebase/auth';44import { auth } from '@/lib/firebase';4546export const signUpWithEmail = (email: string, password: string) =>47 createUserWithEmailAndPassword(auth, email, password);4849export const signInWithEmail = (email: string, password: string) =>50 signInWithEmailAndPassword(auth, email, password);5152export const signInWithGoogle = () =>53 signInWithPopup(auth, new GoogleAuthProvider());5455export const signOut = () => firebaseSignOut(auth);Pro tip: Use signInWithPopup for Google login during development in Bolt's preview — it doesn't require a pre-registered redirect URI. Switch to signInWithRedirect for production if preferred, and register your deployed domain in Google Cloud Console's Authorized redirect URIs.
Expected result: Email/password sign-up and login work in the preview. Google Sign-In popup opens Firebase's Google OAuth flow. The useAuth() hook provides the current user throughout the app.
Understand the Firebase vs Supabase Trade-Off in Bolt
Understand the Firebase vs Supabase Trade-Off in Bolt
Before committing to Firebase as your backend, understand the key trade-off in the context of Bolt.new. Bolt's native Stripe payment integration — the one-click setup in Settings → Stripe that auto-generates checkout code — is built specifically around Supabase edge functions. Choosing Firebase means Bolt cannot auto-generate Stripe checkout flows, and you must implement payments manually using a Next.js API route or your own Firebase Cloud Functions. If your project needs payments, weigh this carefully. Firebase is the better choice when: your team already uses Firebase/Google Cloud products, your data model is naturally document-based (not relational), you need offline support or advanced real-time sync, or you're building a mobile app alongside the web app. Supabase is the better choice when: you want Bolt's one-click Stripe integration, you prefer SQL and relational data, you need complex queries that Firestore handles poorly, or you want a PostgreSQL-compatible database that can scale to full-featured analytics. You cannot use both Firebase and Supabase as the primary backend in the same Bolt project without significant complexity — pick one and commit. If you choose Firebase and need payments, add Stripe manually using the Next.js API route pattern.
I'm using Firebase as my backend instead of Supabase. Add manual Stripe checkout to my app using a Next.js API route (not Supabase edge functions). Create app/api/checkout/route.ts that creates a Stripe Checkout session using the STRIPE_SECRET_KEY environment variable. The checkout should be for a one-time payment of $49. After payment, redirect to /success.
Paste this in Bolt.new chat
1// app/api/checkout/route.ts2// Manual Stripe checkout when using Firebase (bypasses Bolt's native Stripe integration)3import { NextRequest, NextResponse } from 'next/server';4import Stripe from 'stripe';56const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {7 apiVersion: '2024-04-10',8});910export async function POST(request: NextRequest) {11 const { priceId, userId } = await request.json();1213 const session = await stripe.checkout.sessions.create({14 payment_method_types: ['card'],15 mode: 'payment',16 line_items: [{ price: priceId, quantity: 1 }],17 success_url: `${request.nextUrl.origin}/success?session_id={CHECKOUT_SESSION_ID}`,18 cancel_url: `${request.nextUrl.origin}/pricing`,19 metadata: { userId },20 });2122 return NextResponse.json({ url: session.url });23}Pro tip: If you need both Firebase real-time features AND payments, you can use Firebase for data/auth and add manual Stripe checkout via a Next.js API route — you just lose Bolt's auto-generated Stripe setup. The manual approach still works well.
Expected result: Manual Stripe checkout works with Firebase as the backend. The /api/checkout route creates sessions server-side without Supabase edge functions.
Common use cases
Real-Time Collaborative App
Build a collaborative task board, shared document editor, or team chat application where multiple users see updates in real time. Firestore's onSnapshot listeners push database changes to all connected clients instantly — no polling required.
Build a real-time collaborative task board using Firebase Firestore. Users can add, edit, and delete tasks that appear instantly for all users viewing the board. Use Firestore's onSnapshot listener for real-time updates. Organize tasks in a 'tasks' collection with fields: title, description, status (todo/in-progress/done), assignedTo, and createdAt.
Copy this prompt to try it in Bolt.new
User Authentication with Google Login
Add sign-in with Google, email/password registration, and session management to a Bolt.new app. Firebase Auth handles the OAuth flow, token management, and user profile storage. Note: Google OAuth redirect requires a deployed URL to register as an authorized redirect URI.
Add Firebase Authentication to my app with email/password signup, Google Sign-In, and GitHub login. Show a login page with these options. After authentication, redirect to /dashboard and show the user's display name and avatar from their Firebase profile. Protect the /dashboard route — redirect unauthenticated users to /login.
Copy this prompt to try it in Bolt.new
File Upload App with Firebase Storage
Let users upload images, documents, or other files to Firebase Storage with progress tracking. Store file metadata (URL, name, size, uploader) in Firestore. Display uploaded files in a gallery with download links.
Build a file upload system using Firebase Storage. Users can drag and drop files to upload. Show a progress bar during upload. Store the download URL and metadata in a Firestore 'uploads' collection. Display all uploaded files in a grid with file name, size, upload date, and a download button. Limit uploads to 10MB per file.
Copy this prompt to try it in Bolt.new
Troubleshooting
Firebase initialization fails with 'Firebase: No Firebase App named [DEFAULT] has been created'
Cause: The Firebase app is being used (db, auth, storage calls) before initializeApp() has been called, or in a module that doesn't import from lib/firebase.ts.
Solution: Ensure all Firebase usage imports db, auth, or storage from your lib/firebase.ts file (which calls initializeApp). The getApps().length === 0 guard in lib/firebase.ts prevents double-initialization during hot reload.
1// Always import from your central firebase.ts2import { db, auth } from '@/lib/firebase';3// Never call initializeApp() directly in component filesFirestore query returns an error requiring an index with a link to create it
Cause: Compound Firestore queries (filtering on multiple fields, or filtering + ordering) require composite indexes that must be created in the Firebase Console.
Solution: Click the link in the error message — it opens Firebase Console with the index pre-configured for one-click creation. Wait 1-2 minutes for the index to build, then retry the query.
Google Sign-In fails with 'auth/unauthorized-domain' error
Cause: The current domain (either the Bolt preview URL or your deployed domain) is not in Firebase's list of authorized domains for OAuth redirects.
Solution: In Firebase Console → Authentication → Settings → Authorized domains, add your deployed domain (e.g., your-app.netlify.app). For the Bolt preview, use signInWithPopup instead of signInWithRedirect — popups don't require pre-registered domains.
1// Use popup (works in preview) instead of redirect (requires domain registration)2import { signInWithPopup, GoogleAuthProvider } from 'firebase/auth';3const result = await signInWithPopup(auth, new GoogleAuthProvider());Firestore reads return no data even though documents exist in the Firebase Console
Cause: Firestore Security Rules are blocking reads. By default, test mode allows all access for 30 days after project creation, after which rules may default to denying all access.
Solution: In Firebase Console → Firestore Database → Rules, check the current rules. For development, set rules to allow all reads and writes. For production, write rules that only allow authenticated users to read their own data.
1// Firestore rules for development (update before production!)2rules_version = '2';3service cloud.firestore {4 match /databases/{database}/documents {5 match /{document=**} {6 allow read, write: if request.auth != null;7 }8 }9}Best practices
- Use signInWithPopup for OAuth providers during development — it works in Bolt's preview without requiring pre-registered redirect URIs
- Add authorized domains in Firebase Console → Authentication → Settings before deploying, or OAuth login will fail on your production URL
- Understand the Supabase trade-off before choosing Firebase — Bolt's native Stripe integration requires Supabase and won't work with Firebase as the backend
- Write Firestore Security Rules before deploying to production — test mode's open access expires 30 days after project creation
- Use the getApps().length === 0 guard in your Firebase initialization to prevent errors during Vite's hot module replacement
- Firestore's onSnapshot works in Bolt's WebContainer preview — use it to build and test real-time features before deploying
- For collections with more than 1 million documents, design your data model to avoid full-collection reads — always filter and limit queries
Alternatives
MongoDB Atlas provides a flexible document database with a more powerful query language than Firestore and works in Bolt via the Atlas Data API over HTTP.
Google Cloud Firestore is the same underlying technology as Firebase Firestore but accessed via the Google Cloud Console with more granular IAM permissions for enterprise teams.
Airtable offers a spreadsheet-like interface for non-technical teams who need to manage app data without writing Firestore queries or rules.
Firebase Cloud Messaging adds push notification capabilities to apps already using Firebase, extending the backend with real-time notification delivery.
Frequently asked questions
Does the Firebase JS SDK work in Bolt's WebContainer?
Yes. The Firebase JS SDK uses HTTP and WebSocket protocols under the hood, which are fully supported in Bolt's WebContainer runtime. Firestore CRUD operations, real-time listeners (onSnapshot), Authentication, and Storage uploads all work in the preview environment. This makes Firebase one of the most WebContainer-compatible backend options available.
Can I use Firebase and Bolt's native Stripe integration together?
No — Bolt's native Stripe integration (Settings → Stripe → 'Add payments') auto-generates Supabase edge functions and requires Supabase as the backend. If you use Firebase, you must implement Stripe manually using a Next.js API route. The manual approach works well — you just don't get Bolt's one-click Stripe setup.
Should I choose Firebase or Supabase for my Bolt.new app?
Choose Firebase for real-time collaborative features, document-based data, offline support, or if you're in the Google ecosystem. Choose Supabase if you want relational SQL, Bolt's native Stripe integration, complex queries, or prefer PostgreSQL. Both work in Bolt's WebContainer, but Supabase unlocks Bolt's automated payment setup.
How do I deploy a Bolt.new app with Firebase to Netlify?
In Bolt, click Settings → Applications and connect Netlify via OAuth. Click Publish. After deploying, add your Firebase config values (NEXT_PUBLIC_FIREBASE_API_KEY, etc.) as environment variables in Netlify's Site Configuration → Environment Variables. Add your Netlify domain to Firebase Console → Authentication → Settings → Authorized domains. Redeploy to apply environment variables.
Do Firebase Cloud Functions work with Bolt.new?
You can call deployed Firebase Cloud Functions (v2) from your Bolt app via HTTP using the Firebase SDK or standard fetch. However, you cannot develop or deploy Firebase Cloud Functions from within Bolt itself — Cloud Functions require the Firebase CLI, which runs outside the WebContainer. Develop functions locally and deploy via the CLI, then call them from your Bolt app by URL.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation