Skip to main content
Typesafe ODM for Firestore - A lightweight wrapper that adds type safety and schema validation to your Firestore database operations in TypeScript. npm version License: MIT Firetype extends the existing Firestore SDK functionality while maintaining all its native features and requiring the original SDK to be installed. It provides a folder-based schema definition system that automatically generates fully type-safe APIs for your Firestore collections and documents.
⚠️ Important: Firetype extends the Firestore SDK and is not a replacement. You’ll still need to install and use either firebase-admin or firebase/firestore as your primary SDK.

✨ Features

  • 🎯 Full Type Safety: Complete TypeScript type inference for all Firestore operations with zero runtime overhead
  • 📁 Folder-Based Schema: Organize your database structure naturally in directories, including nested collections
  • 🔄 Runtime Validation: Optional Zod-powered schema validation with detailed error messages
  • 🛠️ Powerful CLI: Generate type definitions with flexible configuration options
  • SDK Agnostic: Works seamlessly with both firebase-admin and firebase/firestore SDKs
  • 🔗 Nested Collections: Full support for subcollections with automatic path generation
  • 📊 Collection Groups: Type-safe collection group queries across all subcollections
  • 🎨 Zero Config: Just define your schemas and let Firetype handle the rest

📦 Installation

Install Firetype using your preferred package manager:
# npm
npm install @anonymous-dev/firetype

# yarn
yarn add @anonymous-dev/firetype

# pnpm
pnpm add @anonymous-dev/firetype

# bun
bun add @anonymous-dev/firetype

Peer Dependencies

Firetype requires one of the following Firestore SDKs (choose based on your environment):
# For server-side applications (Node.js, Cloud Functions, etc.)
npm install firebase-admin

# For client-side applications (browsers, React Native, etc.)
npm install firebase
💡 Tip: Firetype works with both SDKs simultaneously if you need to support both client and server environments.

🚀 Quick Start

Get started with Firetype in 5 minutes. This guide shows you how to set up type-safe Firestore operations.

1. Set up your schema directory

Create a directory structure for your Firestore database schemas:
mkdir -p schemas/database

2. Define your first collection schema

Create schemas/database/users/schema.ts:
import { z } from 'zod';

export const schema = z.object({
  name: z.string().min(1, 'Name is required'),
  email: z.string().email('Invalid email format'),
  age: z.number().int().positive().optional(),
  createdAt: z.date(),
  metadata: z.object({
    lastLogin: z.date().optional(),
    isVerified: z.boolean().default(false),
    preferences: z.record(z.string()).optional(),
  }),
});

3. Generate type definitions

Use the Firetype CLI to generate your types:
# Generate types for both admin and client SDKs (output written to input folder)
npx @anonymous-dev/firetype generate --input=./schemas/database
# Generate only admin SDK types
npx @anonymous-dev/firetype generate --mode=admin --input=./schemas
# Generate only client SDK types
npx @anonymous-dev/firetype generate --mode=client --input=./schemas
This creates an index.ts file in your input folder with your fully typed Firestore API.

4. Use in your application

Server-side (Admin SDK)

import { createFireTypeAdmin } from './types';
import { getFirestore } from 'firebase-admin/firestore';

const db = getFirestore();
const firetype = createFireTypeAdmin(db);

// Type-safe collection operations
const usersCollection = firetype.users.getCollectionRef();
const allUsers = await usersCollection.get();

// Type-safe document operations
const userDoc = firetype.users.getDocumentRef('user123');
const userSnapshot = await userDoc.get();
const userData = userSnapshot.data(); // Fully typed!

// Add new user with validation
await usersCollection.add({
  name: 'John Doe',
  email: 'john@example.com',
  age: 30,
  createdAt: new Date(),
  metadata: {
    isVerified: false,
    preferences: { theme: 'dark' },
  },
});

Client-side (Web SDK)

import { createFireTypeClient } from './types';
import { getFirestore, getDocs } from 'firebase/firestore';

const db = getFirestore();
const firetype = createFireTypeClient(db);

// Type-safe operations
const usersRef = firetype.users.getCollectionRef();
const usersSnapshot = await getDocs(usersRef);

usersSnapshot.forEach((doc) => {
  const user = doc.data(); // Fully typed user object
  console.log(`${user.name}: ${user.email}`);
});

5. Add subcollections (Optional)

Create nested collections by adding subdirectories. For user comments: schemas/database/users/comments/schema.ts:
import { z } from 'zod';

export const schema = z.object({
  content: z.string().min(1, 'Comment cannot be empty'),
  authorId: z.string(),
  createdAt: z.date(),
  likes: z.number().default(0),
});
Now you can access nested collections:
// Get comments for a specific user
const userComments = firetype.users.comments.getCollectionRef({
  usersId: 'user123',
});

const comments = await userComments.get();

📚 Documentation Sections

🆘 Need Help?