Docs
Svelte Firebase Library
A comprehensive Svelte 5 library for Firebase integration with reactive state management
Svelte Firebase Library
A comprehensive, production-ready Firebase integration library for Svelte 5 applications. Built with reactive state management using Svelte 5 runes, providing a complete solution for authentication, Firestore, Storage, Realtime Database, Analytics, and more.
🚀 Features
- Complete Firebase Integration - All Firebase products supported
- Svelte 5 Runes - Reactive state management with optimal performance
- TypeScript First - Full type safety and excellent developer experience
- SSR Compatible - Server-side rendering support
- Real-time Updates - Live data synchronization across all services
- Authentication System - Complete auth solution with multiple providers
- Advanced Querying - Complex Firestore queries with type safety
- File Management - Storage upload/download with progress tracking
- Presence System - User online/offline tracking with geolocation
- Analytics Integration - Comprehensive event tracking
- Error Handling - Robust error management with retry mechanisms
- Performance Optimized - Persistent cache, memory management, and optimizations
📦 Installation
npm install svelte-firekit firebase
🔧 Quick Setup
1. Environment Variables
Create a .env
file with your Firebase configuration:
PUBLIC_FIREBASE_API_KEY=your_api_key
PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
PUBLIC_FIREBASE_PROJECT_ID=your_project_id
PUBLIC_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
PUBLIC_FIREBASE_APP_ID=your_app_id
PUBLIC_FIREBASE_MEASUREMENT_ID=your_measurement_id
2. Initialize Firebase
<script>
import { FirebaseApp } from 'svelte-firekit';
</script>
<FirebaseApp>
<!-- Your app content -->
</FirebaseApp>
3. Basic Usage
<script>
import { firekitUser, firekitCollection, firekitDoc } from 'svelte-firekit';
// Reactive user state
const user = $derived(firekitUser.user);
const isAuthenticated = $derived(firekitUser.isAuthenticated);
// Reactive document
const userDoc = firekitDoc('users/123');
// Reactive collection
const posts = firekitCollection('posts', [
where('published', '==', true),
orderBy('createdAt', 'desc'),
limit(10)
]);
</script>
{#if isAuthenticated}
<h1>Welcome, {user?.displayName}!</h1>
{#if userDoc.loading}
<p>Loading user data...</p>
{:else if userDoc.data}
<p>Email: {userDoc.data.email}</p>
{/if}
<h2>Recent Posts</h2>
{#each posts.data as post}
<article>
<h3>{post.title}</h3>
<p>{post.content}</p>
</article>
{/each}
{/if}
📚 Core Services
Authentication
import { firekitAuth, firekitUser } from 'svelte-firekit';
// Sign in methods
await firekitAuth.signInWithEmail('[email protected]', 'password');
await firekitAuth.signInWithGoogle();
await firekitAuth.signInWithFacebook();
await firekitAuth.signInWithApple();
// User registration
await firekitAuth.registerWithEmail('[email protected]', 'password', 'John Doe');
// Reactive user state
const user = $derived(firekitUser.user);
const isAuthenticated = $derived(firekitUser.isAuthenticated);
const isEmailVerified = $derived(firekitUser.isEmailVerified);
Firestore Documents
import { firekitDoc, firekitDocOnce } from 'svelte-firekit';
// Real-time document subscription
const userDoc = firekitDoc<User>('users/123', {
name: 'Loading...',
email: ''
});
// One-time document fetch
const userData = firekitDocOnce<User>('users/123');
// Access reactive state
const isLoading = $derived(userDoc.loading);
const userData = $derived(userDoc.data);
const userError = $derived(userDoc.error);
$effect(() => {
if (isLoading) console.log('Loading...');
if (userData) console.log('User:', userData);
if (userError) console.error('Error:', userError);
});
Firestore Collections
import { firekitCollection, where, orderBy, limit } from 'svelte-firekit';
// Simple collection
const users = firekitCollection<User>('users');
// With query constraints
const activeUsers = firekitCollection<User>('users', [
where('active', '==', true),
orderBy('name'),
limit(10)
]);
// Advanced options
const paginatedUsers = firekitCollection<User>('users', {
pagination: { enabled: true, pageSize: 20 },
cache: { enabled: true, ttl: 300000 }
});
// Access reactive state
const usersData = $derived(users.data);
const usersLoading = $derived(users.loading);
const usersError = $derived(users.error);
$effect(() => {
console.log('Users:', usersData);
console.log('Loading:', usersLoading);
console.log('Error:', usersError);
});
Document Mutations
import { firekitDocMutations } from 'svelte-firekit';
// Create document
const result = await firekitDocMutations.add(
'users',
{
name: 'John Doe',
email: '[email protected]'
},
{
timestamps: true,
validate: true
}
);
// Update document
await firekitDocMutations.update('users/123', {
name: 'Jane Doe'
});
// Delete document
await firekitDocMutations.delete('users/123');
// Batch operations
const batchResult = await firekitDocMutations.batch([
{ type: 'create', path: 'users', data: userData },
{ type: 'update', path: 'profiles/123', data: profileUpdate }
]);
Storage Management
import { firekitDownloadUrl, firekitUploadTask, firekitStorageList } from 'svelte-firekit';
// Download URL
const imageUrl = firekitDownloadUrl('images/photo.jpg');
const downloadUrl = $derived(imageUrl.url);
// File upload with progress
const upload = firekitUploadTask('uploads/file.pdf', file);
const uploadProgress = $derived(upload.progress);
const uploadCompleted = $derived(upload.completed);
const uploadDownloadUrl = $derived(upload.downloadURL);
$effect(() => {
if (downloadUrl) console.log('Image URL:', downloadUrl);
console.log('Upload progress:', uploadProgress);
if (uploadCompleted) console.log('Download URL:', uploadDownloadUrl);
});
// Storage listing
const files = firekitStorageList('uploads');
const fileItems = $derived(files.items);
const filePrefixes = $derived(files.prefixes);
$effect(() => {
console.log('Files:', fileItems);
console.log('Folders:', filePrefixes);
});
Realtime Database
import { firekitRealtimeDB, firekitRealtimeList } from 'svelte-firekit';
// Single value
const userStatus = firekitRealtimeDB<{ online: boolean }>('users/123/status');
// List data
const messages = firekitRealtimeList<Message>('messages');
// Access data
const statusData = $derived(userStatus.data);
const messagesList = $derived(messages.list);
$effect(() => {
console.log('Status:', statusData);
console.log('Messages:', messagesList);
});
// Update data
await userStatus.set({ online: true });
await messages.push({ text: 'Hello', userId: '123' });
Presence System
import { firekitPresence } from 'svelte-firekit';
// Initialize presence
await firekitPresence.initialize(user, {
geolocation: {
enabled: true,
type: 'browser',
requireConsent: true
}
});
// Set presence status
await firekitPresence.setPresence('online');
// Access reactive state
const presenceStatus = $derived(firekitPresence.status);
const presenceLocation = $derived(firekitPresence.location);
const presenceSessions = $derived(firekitPresence.sessions);
Analytics
import { firekitAnalytics } from 'svelte-firekit';
// Track custom events
firekitAnalytics.trackEvent('button_click', {
button_name: 'signup',
page_location: '/home'
});
// Track purchases
firekitAnalytics.trackPurchase({
transaction_id: 'T12345',
value: 29.99,
currency: 'USD',
items: [{ item_id: 'prod_123', item_name: 'Premium Plan' }]
});
// Set user properties
firekitAnalytics.setUserProperties({
user_type: 'premium',
subscription_plan: 'pro'
});
🧩 Components
Authentication Components
<script>
import { AuthGuard, SignedIn, SignedOut } from 'svelte-firekit';
</script>
<!-- Route protection -->
<AuthGuard requireAuth={true} redirectTo="/login">
<h1>Protected Content</h1>
</AuthGuard>
<!-- Conditional rendering -->
<SignedIn>
<h1>Welcome back!</h1>
</SignedIn>
<SignedOut>
<h1>Please sign in</h1>
</SignedOut>
Data Components
<script>
import { Doc, Collection } from 'svelte-firekit';
</script>
<!-- Document component -->
<Doc ref="users/123" let:data let:ref let:firestore>
<h1>{data.name}</h1>
<p>{data.email}</p>
</Doc>
<!-- Collection component -->
<Collection ref="posts" let:data let:ref let:firestore let:count>
<h1>Posts ({count})</h1>
{#each data as post}
<article>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
{/each}
</Collection>
Storage Components
<script>
import { StorageList, DownloadURL, UploadTask } from 'svelte-firekit';
</script>
<!-- Storage listing -->
<StorageList path="uploads" let:items let:prefixes>
<h2>Files</h2>
{#each items as item}
<p>{item.name}</p>
{/each}
<h2>Folders</h2>
{#each prefixes as prefix}
<p>{prefix.name}</p>
{/each}
</StorageList>
<!-- Download URL -->
<DownloadURL path="images/photo.jpg" let:url let:loading let:error>
{#if loading}
<p>Loading image...</p>
{:else if url}
<img src={url} alt="Photo" />
{:else if error}
<p>Error: {error.message}</p>
{/if}
</DownloadURL>
<!-- Upload with progress -->
<UploadTask path="uploads/file.pdf" file={selectedFile} let:progress let:completed let:error>
{#if !completed}
<div class="progress-bar">
<div class="progress" style="width: {progress}%"></div>
</div>
<p>{progress}% uploaded</p>
{:else}
<p>Upload complete!</p>
{/if}
</UploadTask>
🔧 Advanced Features
Query Builders
import { firekitCollection } from 'svelte-firekit';
const query = firekitCollection
.createQuery()
.where('status', '==', 'active')
.where('category', 'in', ['tech', 'design'])
.orderBy('createdAt', 'desc')
.limit(20);
const results = firekitCollection('posts', query.build());
Custom Validation
import { firekitDocMutations } from 'svelte-firekit';
const validateUser = (data: any) => {
if (!data.email || !data.email.includes('@')) {
return { valid: false, message: 'Invalid email' };
}
return { valid: true };
};
await firekitDocMutations.add('users', userData, {
validate: true,
validator: validateUser
});
Error Handling
import { firekitDoc } from 'svelte-firekit';
const userDoc = firekitDoc('users/123');
const userError = $derived(userDoc.error);
$effect(() => {
if (userError) {
if (userError.isRetryable()) {
// Retry the operation
userDoc.retryIfNeeded();
} else {
// Handle non-retryable error
console.error('Permanent error:', userDoc.error);
}
}
Performance Monitoring
import { firekitCollection, firekitDocMutations } from 'svelte-firekit';
// Collection statistics
const users = firekitCollection('users');
const stats = $derived(users.getStats());
$effect(() => {
console.log('Cache hit rate:', stats.cacheHitRate);
console.log('Average query time:', stats.averageQueryTime);
});
// Mutation analytics
const analytics = $derived(firekitDocMutations.getAnalytics());
$effect(() => {
console.log('Success rate:', analytics.successRate);
console.log('Average duration:', analytics.averageDuration);
});
🎯 Best Practices
1. Use Reactive State
// ✅ Good - Reactive state
const user = $derived(firekitUser.user);
const isAuthenticated = $derived(firekitUser.isAuthenticated);
// ❌ Avoid - Direct service calls in templates
const user = firekitUser.getCurrentUser();
2. Handle Loading States
{#if userDoc.loading}
<LoadingSpinner />
{:else if userDoc.error}
<ErrorMessage error={userDoc.error} />
{:else if userDoc.data}
<UserProfile user={userDoc.data} />
{/if}
3. Clean Up Subscriptions
import { onDestroy } from 'svelte';
const userDoc = firekitDoc('users/123');
onDestroy(() => {
userDoc.dispose();
});
4. Use Type Safety
interface User {
id: string;
name: string;
email: string;
active: boolean;
}
const userDoc = firekitDoc<User>('users/123');
const users = firekitCollection<User>('users');
5. Optimize Queries
// ✅ Good - Specific queries
const activeUsers = firekitCollection('users', where('active', '==', true), limit(10));
// ❌ Avoid - Fetching all data
const allUsers = firekitCollection('users');
🔍 API Reference
Core Services
firekitAuth
- Authentication servicefirekitUser
- Reactive user storefirekitDoc
- Document managementfirekitCollection
- Collection managementfirekitDocMutations
- Document mutationsfirekitStorage
- Storage managementfirekitRealtimeDB
- Realtime DatabasefirekitPresence
- Presence systemfirekitAnalytics
- Analytics integration
Components
FirebaseApp
- Firebase initializationAuthGuard
- Route protectionDoc
- Document componentCollection
- Collection componentStorageList
- Storage listingDownloadURL
- Download URLUploadTask
- File upload
Types
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
📄 License
MIT License - see LICENSE for details.
🆘 Support
Built with ❤️ for the Svelte community