Firebase adapter
The Firebase adapter queries Cloud Firestore via the Firebase Admin SDK. Use this when your data lives in Firestore documents.
Config shape
Inline service account:
{ "type": "firebase", "config": { "projectId": "your-gcp-project", "serviceAccount": { "projectId": "your-gcp-project", "clientEmail": "spelo-readonly@your-gcp-project.iam.gserviceaccount.com", "privateKey": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----\n" } }, "collections": { "properties": { "source": "properties", "searchable_fields": ["address", "city"], "filterable_fields": ["beds", "city", "price"], "display_fields": ["id", "address", "city", "beds", "price"] } }}JSON string form (easier to paste):
{ "type": "firebase", "config": { "serviceAccountJson": "{\"type\":\"service_account\",\"project_id\":\"...\",\"client_email\":\"...\",\"private_key\":\"...\"}" }}Application Default Credentials (if running in GCP, optional):
{ "type": "firebase", "config": { "projectId": "your-gcp-project", "useApplicationDefault": true }}Setup
-
Create a service account with read-only Firestore access
GCP Console → IAM & Admin → Service Accounts → Create Service Account.
Name:
spelo-readonly. Grant the Cloud Datastore Viewer role (which also covers Firestore read). Do not grant Editor / Owner. -
Create a key
Actions → Manage Keys → Add Key → JSON. A file downloads. Keep it secret.
-
Paste in the dashboard
Dashboard → Data → Firebase → paste the entire JSON into the Service Account field → Test connection.
-
Map collections
The
sourceis the Firestore collection path. Sub-collections use/, e.g.users/abc/orders(but the adapter currently queries top-level collections — use a webhook if you need sub-collection queries).
Operator translation
| SearchParams operator | Firestore where() |
|---|---|
eq | where(field, '==', value) |
neq | where(field, '!=', value) |
gt, gte, lt, lte | standard Firestore range ops |
contains (array field) | where(field, 'array-contains', value) |
contains (string field) | in-memory filter after fetch (Firestore has no substring op) |
in | where(field, 'in', values) — max 30 |
Free-text query — Firestore does not support substring search. The adapter fetches up to 50 documents matching the structured filters, then filters in-memory via the shared matchesQuery helper.
Indexes
Firestore requires composite indexes for queries with multiple filters. Run your query once; Firestore’s error message gives you a clickable link to auto-create the index. Create these indexes ahead of time for your expected filter combos.
Security notes
- Read-only via IAM. The service account must have only
roles/datastore.viewer. No write roles. - Collection path segments validated against
^[A-Za-z0-9_]+$— nothing with dots (Firestore field paths) or slashes-out-of-place. - Adapter code only ever calls
.get()and.where()/.orderBy()/.limit()— noset(),update(),delete(),runTransaction.
Troubleshooting
PERMISSION_DENIED: Missing or insufficient permissions.→ the service account doesn’t havedatastore.viewer. Grant it.FAILED_PRECONDITION: The query requires an index.→ follow the link in the error message to create the composite index.INVALID_ARGUMENT: Inequality filter property and first sort order must be the same→ your filter combination isn’t supported by Firestore. Simplify or switch to a webhook.Could not load the default credentials→ you setuseApplicationDefault: truebut the environment has no ADC. Fall back to inline or JSON service account.
More: Database connection errors.