Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.modaal.dev/llms.txt

Use this file to discover all available pages before exploring further.

What is Firebase for?

Firebase is Google’s backend-as-a-service for mobile apps. You don’t run servers, manage databases, or write auth flows from scratch — Firebase gives you all of that through a small set of SDKs. Typical things you’d use it for:

Sign-in

Email+password, Apple, Google, phone (SMS code), anonymous — with one line per provider. Users stay signed in automatically across app launches.

Cloud database

Save user data, share it across devices, and collaborate in real time. Firestore keeps a phone’s local cache in sync even when offline.

File storage

User avatars, attached photos, recorded audio — anything that’s too big to go in the database.

Cloud Functions

Server-side code you don’t have to host. Run logic on signup, send push notifications, call paid APIs without exposing keys in the app.

Analytics

See which screens users visit, what they tap, where they drop off. Free, unlimited.

Crashlytics

Real crash reports from real users, grouped by cause, with stack traces and breadcrumbs. Required reading before every release.

Push notifications

Send notifications to one user, a segment, or everyone — from the Firebase console or your own backend.

Remote Config

Flip feature flags, tune limits, A/B test copy — without shipping a new app version.
When Firebase is the wrong choice. If you need a relational database with strict schemas, complex joins, or row-level ownership rules that don’t map to a document model, pick Supabase or a traditional Postgres backend instead. Firestore is great for document-shaped data and real-time sync; it is not a Postgres replacement.

Step-by-step setup

Open the Firebase tab in Modaal (the flame icon in the left sidebar of your project). The panel walks you through connecting your Google account, picking (or creating) a Firebase project, and wiring the iOS app.
1

Connect your Google account

Click Connect. A browser window opens; sign in with the Google account you use (or plan to use) for Firebase. Modaal stores the access token locally and refreshes it automatically in the background — you don’t sign in again every day.
If your Firebase projects are under a different Google account than your primary sign-in, sign in with that one. You can change accounts later from the Firebase panel’s ”⋯” menu.
2

Install the Firebase CLI (first project only)

Some operations (project creation, deployments) go through Google’s firebase command-line tool. Modaal checks whether it’s installed and offers to install it for you if not. Click Install — this runs npm install -g firebase-tools behind the scenes.
3

Pick or create a Firebase project

The Firebase project dropdown lists every project visible to the signed-in Google account.
  • Reuse an existing project (e.g., one you already created in the Firebase console for another app) by picking it from the list.
  • Create a new one by selecting — Create Project — at the top of the dropdown. Modaal creates it under your Google account using the firebase projects:create CLI command.
4

Register your iOS app

The panel compares your iOS bundle identifier (from xcodegen.yml) against the iOS apps registered in the Firebase project.
  • If there’s a match, you’re done — Modaal downloads GoogleService-Info.plist, drops it into src-ios/App/<TargetName>/, and wires it into the Xcode project.
  • If there’s no match, click Register this app. Modaal registers the bundle id with Firebase and downloads the plist automatically.
5

(Optional) Enable deployable services

The Deployable services card lets you toggle Firestore, Cloud Storage, Cloud Functions, and Hosting. Each toggle scaffolds the local files Firebase expects (rules, TypeScript function starter, static site with AASA) and adds the matching top-level key to firebase/firebase.json.You can click Initialize Firebase project to turn them all on in one step.
6

Ask your agent to add a feature

From the chat, say:
“Add Firebase sign-in with Apple, and let users save their favorite recipes to Firestore.”
The agent reads Modaal’s Firebase integration knowledge base, picks the right wrappers, writes the Swift code, and runs the build. When it needs something only a human can do — enabling a provider in the Firebase console, uploading an APNs auth key for push — it tells you exactly what to do and where.

How Modaal wires Firebase — and why

Modaal doesn’t drop the vanilla firebase-ios-sdk into your app. It adds a small Swift package called modaal-firebase-wrappers that wraps each Firebase SDK behind a protocol. Your app depends on ModaalFirebaseAuth, ModaalFirebaseFirestore, etc. — one product per service, each re-exporting the parts of the underlying SDK you need, plus a protocol you can inject and mock.

Why not vanilla firebase-ios-sdk?

With the vanilla SDK, every screen that reads Firestore depends on Firestore directly. That means every unit test needs a real Firestore emulator running, or a tangled manual mock. With ModaalFirebaseFirestore, your screen depends on a FirestoreServiceProtocol. Unit tests inject a fake that returns fixed documents — no emulator, no network, milliseconds per test.Same story for Auth, Functions, Storage, Analytics, and Remote Config. Each one ships a protocol and a ready-made mock you can drop into test targets.
When the agent writes Firebase code, it needs to know the SDK’s types and method signatures. The vanilla firebase-ios-sdk is over a million tokens of symbol information across a dozen modules. The agent can’t hold that in context, so it either hallucinates APIs or skips parts of the SDK.Modaal’s wrappers are tiny — a few hundred lines per product. The agent reads the protocols, sees exactly what’s available, and writes code that actually compiles. Fewer retries, faster turns, lower bills.
The app builds its service dependencies once, at launch, in a single composition-root file. Swapping FirestoreService() (real) for FakeFirestoreService(fixtures: ...) (preview / UI test) is a one-line change. No conditional compilation, no feature flags, no #if DEBUG.This is the same pattern used by RIBs and clean-architecture iOS apps — the wrappers just make it easy for you without writing boilerplate.
Google bumps the Firebase SDK every few weeks. Most updates are silent, but occasionally a public type gets renamed or an enum shifts. When your code depends on ModaalFirebaseAuth instead of FirebaseAuth, the upgrade lands in the wrapper — your app code usually doesn’t need to change.

What Modaal puts in your project

GoogleService-Info.plist is safe to commit to source control. It’s not a secret — it identifies your app to Firebase, but access control lives in Firestore/Storage security rules and in provider restrictions, not in the plist itself.

Typical scenarios

Scenario 1: Add sign-in with Apple + save favorites

You have a working app. You want users to sign in with Apple and save a list of favorites that syncs across their devices.
1

Open the Firebase panel and connect

Click the flame icon, connect your Google account, pick (or create) a Firebase project, register the iOS app. Covered above in Step-by-step setup.
2

Enable Apple sign-in in the Firebase console

Firebase needs Apple as a provider turned on. The agent can’t do this — it’s a privileged action in your Firebase project.Open Firebase Console → Authentication → Sign-in method, enable Apple, and save. (The console will ask you to register a Service ID in your Apple Developer account — it walks you through it.)
3

Ask the agent to implement it

In chat:
“Add Apple sign-in using ModaalFirebaseAuth. After sign-in, save the user’s uid to the users/{uid} document in Firestore. Add a Favorites screen that reads and writes users/{uid}/favorites.”
The agent will:
  • Add the ModaalFirebaseAuth and ModaalFirebaseFirestore products to Package.swift.
  • Add a “Sign in with Apple” button and a sign-in flow.
  • Add a FavoritesService that talks to Firestore through the protocol.
  • Add a real-time listener so favorites sync across devices without a refresh button.
  • Run the build and fix any errors.
4

Tighten security rules before you ship

The scaffolded firestore.rules is default-deny for safety. Ask the agent:
“Update firestore.rules so users can read and write their own users/{uid}/** subtree but nothing else.”
Click Deploy on the Firestore row in the Firebase panel. The rules go live in ~10 seconds.

Scenario 2: Catch crashes in production

You’re a week before launch and want to know what breaks on real devices.
1

Enable Crashlytics (one toggle)

From chat:
“Add ModaalFirebaseCrashlytics to the app. Log non-fatal errors from the top-level catch branches in FavoritesService.”
The agent adds the product, initializes it at launch, and wraps your catch blocks with Crashlytics.record(error:). The dSYM upload script was already added when you registered the iOS app, so symbolicated reports arrive automatically.
2

Test the pipe before release

Ask:
“Add a hidden crashNow() trigger in the Settings screen that forces a crash, so I can verify Crashlytics is catching events end-to-end.”
Build, run on device, crash the app, relaunch. Within a couple of minutes, the crash appears in Firebase Console → Crashlytics.
3

Remove the trigger

“Remove the crashNow() trigger from Settings.”

Scenario 3: Send a welcome notification

You want users to receive a push notification the first time they sign in.
1

Enable Cloud Functions (toggle in the panel)

In the Firebase panel’s Deployable services card, toggle Cloud Functions. Modaal scaffolds firebase/functions/ with a TypeScript starter.
Cloud Functions require the Blaze (pay-as-you-go) plan. Free-tier quotas are generous, but you have to enter a credit card. Upgrade from the Firebase console if prompted.
2

Upload an APNs auth key

Push notifications go through Apple Push Notification service (APNs). Open your Apple Developer account → Keys → create a new key with APNs enabled → download the .p8 file. Upload it to Firebase Console → Project Settings → Cloud Messaging → Apple apps.
3

Ask the agent to implement

“Add ModaalFirebaseMessaging and request notification permission on first launch. When a new user is created in Firestore (onDocumentCreated trigger on users/{uid}), send them a welcome notification via FCM.”
The agent adds the iOS side (permission request, FCM token registration, foreground handler) and writes the Cloud Function in firebase/functions/src/index.ts.
4

Install deps and deploy

Run cd firebase/functions && npm install && npm run build (the agent can do this for you). Then click Deploy on the Functions row in the Firebase panel. Watch the logs stream in the modal.

What do I deploy, and when?

When the agent (or you) edits a file under the firebase/ folder, those changes are local only until you click the matching Deploy button in the Firebase panel. The live app keeps running with the last-deployed version until then. The Firebase panel’s Deployable services card shows one row per service with a colored dot:
  • 🟢 Green — what’s live matches your local files. Nothing to do.
  • 🟡 Yellow — you have local changes that haven’t been deployed yet. Click Deploy on that row.
  • Gray — the service is set up locally but has never been deployed. Click Deploy to publish it for the first time.
  • 🔴 Red — the last deploy failed. Click Deploy again; the log window shows what broke.

Changed this? Deploy that.

You edited or added…Deploy thisWhat happens if you skip the deploy
firebase/firestore.rules — who can read/write your databaseFirestore rulesThe database keeps enforcing the old rules. Users can’t reach new data, or can reach data you meant to lock down.
firebase/firestore.indexes.json — added a new query in the appFirestore indexesNew queries silently fail in the app with a “query requires an index” error.
firebase/storage.rules — who can upload/download filesStorage rulesSame as Firestore rules — old rules stay in effect.
Anything inside firebase/functions/ — your server-side codeCloud FunctionsClients keep calling the old version of your function until you redeploy.
Added an npm package in firebase/functions/package.jsonCloud Functions (after npm install && npm run build)The function crashes at cold-start because the package isn’t in the deployed bundle.
Anything in firebase/hosting/public/ — your static siteHostingThe public site keeps serving the last-deployed content.
The AASA file (apple-app-site-association) for universal linksHostingiOS downloads the AASA from your live site, not from your computer. Until you redeploy, universal links behave however the previous AASA said.
Changed DEVELOPMENT_TEAM in iOS Project Settings after Hosting was set upHostingModaal automatically rewrites the AASA locally, but universal links won’t work with the new team id until the Hosting deploy publishes the updated file.

You do NOT need to deploy after:

  • Swift code changes in your iOS app — those go live when you run or ship the iOS app, not through Firebase deploy.
  • Swapping the Google account connected to Modaal — that’s just a sign-in change.
  • Turning Firebase Analytics events on/off in code — events go live with the next iOS build.
  • Enabling Apple / Google / phone sign-in — that’s done in the Firebase Console → Authentication → Sign-in method, not via Deploy.
  • Uploading an APNs push key — done in the Firebase Console, not via Deploy.
  • Editing Remote Config values — done in the Firebase Console → Remote Config (click Publish there).
Not sure what’s pending? Look at the dots in the Firebase panel. Any yellow, gray, or red dot is something worth deploying. The agent also tends to end its turn with a sentence like “Now open the Firebase panel → Deploy on the Firestore rules row” — that’s your cue.

Troubleshooting

When something goes wrong with Firebase, the best first move is almost always:

Ask the agent to fix it

Type: “Check the Firebase setup for this project and fix anything that’s broken.”The agent walks through every place Firebase wiring lives — the project settings file, the iOS build configuration, the GoogleService-Info.plist, the wrappers package, the crash-reporting upload step — and fixes whatever’s out of place. For anything that can only be done by a human (like enabling a provider in the Firebase console or upgrading the billing plan), it tells you the exact button to click or URL to open.
Modaal also surfaces two ready-made prompts from the Firebase panel’s ”⋯” menu — click one and the agent does the rest:
  • Fix Firebase integration — brings your project’s local files back in sync with Firebase (re-downloads the plist, re-links it in the iOS project, re-adds the crash-reporting upload step).
  • Migrate to wrappers — if your project still uses the vanilla Firebase SDK directly, this switches it over to the Modaal wrappers without changing how the app behaves.

Common issues

Google access tokens expire after about an hour. Modaal refreshes them automatically in the background when the panel opens. If the refresh fails because of a transient network issue, the banner clears on the next Refresh click. If it persists, click Connect again — a re-auth takes ten seconds and doesn’t disturb any other Firebase state.
The Google account you’re signed in with isn’t a member of that Firebase project. This usually means the project was created under a different Google account than the one you used to sign in.Options:
  • Click Sign in with a different Google account in the error banner and use the account that owns the project.
  • Or ask the project owner to invite you as a member in Firebase Console → Project settings → Users and permissions.
Some operations (creating a project, deploying rules or functions) use Google’s firebase command-line tool, which has its own separate sign-in.Modaal shows a Sign in via Terminal button when this is needed — click it, a terminal opens with firebase login pre-typed, finish the browser flow, click Retry. You only do this once per machine.
Firebase Storage needs a one-time console bootstrap. Open Firebase Console → Storage and click Get started. Come back to Modaal and click Deploy again.
Cloud Functions require Firebase’s pay-as-you-go plan (free-tier quotas are generous, but a credit card is required). Click the URL in the error to upgrade, then retry the deploy.
Checklist:
  • Did the app crash on a real device, not the Simulator? (Simulator crashes don’t upload.)
  • Did you relaunch the app after the crash? Crashlytics uploads on the next launch, not at crash time.
  • Is the [Firebase Crashlytics] Upload dSYMs post-build script present in your Xcode target? (The Firebase panel’s status banner shows this explicitly. If it’s missing, click Fix Firebase integration.) This script turns raw crash addresses into readable function names — without it, reports show up but you can’t tell where the crash happened.
Click the refresh icon (↻) at the top of the Firebase panel to re-fetch the list of projects. If the project still doesn’t appear, the Google account signed in to Modaal probably isn’t the one that created it — re-check which account you used in the Firebase console.
From the Firebase panel’s ”⋯” menu, pick Disconnect. This clears the stored Google token but does not touch files in your repository (GoogleService-Info.plist, firebase/…, Package.swift, etc.) — your app keeps working and can be re-connected to the same or a different Firebase project later.To remove Firebase from the project entirely, ask the agent:
“Remove all Firebase integration from this project — the wrappers package, the plist, the post-build script, and the firebase/ directory.”
Still stuck? Share a screenshot of the Firebase panel (the top status banner shows exactly which piece of the setup is out of place) in our Discord — it’s usually enough for us to pinpoint the fix.