Firebase Cloud Functions compatible SDK backed by ZeroDB. Same trigger syntax you already know, zero vendor lock-in, instant setup.
npm install zerodb-firebase
| Firebase | zerodb-firebase | |
|---|---|---|
| Setup time | Project + billing + deploy | npm install and go |
| Vendor lock-in | Full Google ecosystem | Open API, swap anytime |
| Auto-provisioning | No | Yes, instant (no signup) |
| Cold starts | 1-10s | Sub-100ms (edge hooks) |
| Pricing | Pay per invocation + storage | Free tier, then usage-based |
| Firestore required | Yes | No, any ZeroDB table |
import { onDocumentCreated, onDocumentUpdated, deployTriggers } from 'zerodb-firebase';
// Same Firebase syntax, ZeroDB backend
export const onUserCreated = onDocumentCreated('users/{userId}', (event) => {
const snapshot = event.data;
const userData = snapshot.data();
console.log('New user:', userData.name);
console.log('User ID:', event.params.userId);
});
export const onProfileUpdated = onDocumentUpdated('users/{userId}', (event) => {
const before = event.data.before.data();
const after = event.data.after.data();
console.log('Name changed:', before.name, '->', after.name);
});
// Deploy all triggers to ZeroDB
await deployTriggers();That's it. If you don't set ZERODB_API_KEY and ZERODB_PROJECT_ID, a free project is auto-provisioned on first deploy.
- import { onDocumentCreated } from 'firebase-functions/v2/firestore';
+ import { onDocumentCreated } from 'zerodb-firebase';// This code works with BOTH firebase-functions and zerodb-firebase
export const onOrderPlaced = onDocumentCreated('orders/{orderId}', async (event) => {
const order = event.data.data();
const orderId = event.params.orderId;
// Send confirmation email
await sendEmail(order.customerEmail, `Order ${orderId} confirmed!`);
// Update inventory
for (const item of order.items) {
await updateInventory(item.sku, -item.quantity);
}
});import { deployTriggers } from 'zerodb-firebase';
// Deploy all registered triggers to ZeroDB hooks
await deployTriggers({
apiKey: process.env.ZERODB_API_KEY, // optional: auto-provisions if missing
projectId: process.env.ZERODB_PROJECT_ID, // optional: auto-provisions if missing
});When ZeroDB fires a hook, route the webhook payload to processEvent:
import { processEvent } from 'zerodb-firebase';
import express from 'express';
const app = express();
app.use(express.json());
app.post('/webhooks/zerodb', async (req, res) => {
const results = await processEvent(req.body);
res.json({ results });
});
app.listen(3000);All trigger builders follow the same signature as firebase-functions/v2/firestore:
import {
onDocumentCreated, // Fires on new row insert
onDocumentUpdated, // Fires on row update (provides before/after)
onDocumentDeleted, // Fires on row delete
onDocumentWritten, // Fires on any write (create, update, delete)
} from 'zerodb-firebase';Path patterns use Firebase-style wildcards:
onDocumentCreated('users/{userId}', handler);
onDocumentCreated('orders/{orderId}/items/{itemId}', handler);
onDocumentCreated('logs', handler); // No wildcardsOptions object (alternative to string path):
onDocumentCreated({
document: 'users/{userId}',
callbackUrl: 'https://myapp.com/webhooks/zerodb',
}, handler);Handlers receive a FirestoreEvent:
onDocumentCreated('users/{userId}', (event) => {
event.data; // DocumentSnapshot (created/deleted) or Change (updated/written)
event.params; // { userId: 'abc123' }
event.type; // 'document.created'
event.id; // Row ID
event.path; // 'users/abc123'
event.time; // ISO timestamp
});const snapshot = event.data;
snapshot.data(); // Full document data
snapshot.exists; // true if data is not null
snapshot.id; // Document ID
snapshot.ref.path; // Full path
snapshot.get('name'); // Get field by path (supports dot notation)
snapshot.get('addr.city'); // Nested field accessonDocumentUpdated('users/{userId}', (event) => {
const change = event.data;
change.before; // DocumentSnapshot of old data
change.after; // DocumentSnapshot of new data
const oldName = change.before.data().name;
const newName = change.after.data().name;
});import {
deployTriggers, // Deploy all triggers to ZeroDB hooks
processEvent, // Route a webhook event to matching handlers
initializeApp, // Initialize with explicit config
clearTriggers, // Clear all registered triggers
getRegisteredTriggers, // List all registered triggers
} from 'zerodb-firebase';import { initializeApp } from 'zerodb-firebase';
// Mirrors firebase-admin.initializeApp()
initializeApp({
apiKey: 'zdb_your_key',
projectId: 'your-project-id',
baseUrl: 'https://api.ainative.studio', // optional
});| Firebase event | ZeroDB hook event |
|---|---|
document.created |
zerodb.table.row_inserted |
document.updated |
zerodb.table.row_updated |
document.deleted |
zerodb.table.row_deleted |
document.written |
zerodb.table.row_written |
| Variable | Description | Required |
|---|---|---|
ZERODB_API_KEY |
ZeroDB API key | No (auto-provisions) |
ZERODB_PROJECT_ID |
ZeroDB project ID | No (auto-provisions) |
ZERODB_BASE_URL |
API base URL | No (defaults to https://api.ainative.studio) |
const { onDocumentCreated, deployTriggers } = require('zerodb-firebase');| Feature | Details |
|---|---|
| Auto-provisioning | No signup needed. First deploy creates a free project. |
| Free tier | 10K events/month, 1GB storage |
| Edge hooks | Sub-100ms trigger execution |
| Zero vendor lock-in | Standard HTTP webhooks, export anytime |
| MCP compatible | Works with Claude Code, Cursor, Windsurf |
Get started free: ainative.studio
Built by AINative Studio -- the database for AI agents.
No account needed to start. On first run, this package automatically:
- Provisions a free ZeroDB instance (~800ms)
- Saves credentials locally (
.env,.mcp.json) - Prints a claim link in your terminal
Your auto-provisioned instance is free for 72 hours. To keep your data permanently, visit the claim URL printed in your terminal.
If a coding agent (Claude Code, Cursor, Windsurf) installs this package:
- Auto-provisions without human intervention
- The claim URL appears in agent output — visit it to take ownership
.claude/CLAUDE.mdinstructs agents to surface the claim link to you- Check
.envor~/.ainative/config.jsonfor your project ID if you miss it