"Don't Reinvent the Wheel"
LumiBase is not a final product. It is the technical backbone designed to free developers from repetitive, boring setup tasks.
It combines the flexibility of NoSQL, the power of SQL, and the practicality of a Headless CMS into a unified block, ready to take your idea from draft to digital space in seconds.
We believe every breakthrough product deserves a solid start. LumiBase focuses on 3 pillars:
- Velocity: Skip weeks of Auth, DB, and CMS configuration. Set up once, use for every project.
- Transparency: Every data stream is clear, every query optimized thanks to the power of PostgreSQL.
- Scalability: From a small MVP to a system with millions of users, LumiBase's skeleton remains solid.
LumiBase is forged from the best modern technologies:
- β€οΈ Firebase (The Heart): Provides the "pulse" with world-class Identity and Analytics.
- π§ Supabase (The Brain): Stores and processes data with the intelligence of PostgreSQL, ensuring integrity and complex query capabilities.
- π Directus (The Interface): A sophisticated content administration shell allowing anyoneβeven non-codersβto control the data underneath.
- Indie Hackers: Turn ideas into products in days instead of months.
- Agencies: A standard process to deliver projects with a professional admin interface (Directus) and reliable infrastructure.
- Startups: A flexible launchpad, easy to pivot business models without tearing down old infrastructure.
"LumiBase is not just a start. It's a competitive advantage."
graph TB
Client[Client Application]
Firebase[Firebase Auth]
Functions[Cloud Functions]
Supabase[Supabase PostgreSQL]
Directus[Directus CMS]
Client -->|1. Authenticate| Firebase
Firebase -->|2. JWT Token| Client
Client -->|3. API Request + JWT| Supabase
Supabase -->|4. Verify JWT| Firebase
Firebase -->|5. onCreate Trigger| Functions
Functions -->|6. Sync User Data| Supabase
Directus -->|7. Direct DB Connection| Supabase
subgraph "Docker Environment"
Directus
Supabase
end
sequenceDiagram
participant User
participant Client
participant Firebase
participant CloudFn
participant Supabase
User->>Client: Sign in (Google/Email)
Client->>Firebase: Authenticate
Firebase->>Firebase: Create user
Firebase->>CloudFn: Trigger onCreate
CloudFn->>Supabase: INSERT INTO users
Firebase->>Client: JWT Token
Client->>Supabase: API Request + JWT
Supabase->>Firebase: Verify JWT
Firebase->>Supabase: Valid + firebase_uid
Supabase->>Supabase: Check RLS policies
Supabase->>Client: Data response
graph LR
subgraph "Docker Compose"
Directus[Directus Container<br/>Port 8055]
Postgres[PostgreSQL Container<br/>Port 5432]
Network[Docker Network<br/>directus-network]
Directus -.->|connects via| Network
Postgres -.->|connects via| Network
Directus -->|DB Connection| Postgres
end
Host[Host Machine] -->|Port Mapping| Directus
Volumes[Docker Volumes] -->|Data Persistence| Postgres
Volumes2[Docker Volumes] -->|Uploads/Extensions| Directus
erDiagram
USERS {
varchar firebase_uid PK
varchar email UK
varchar display_name
text photo_url
timestamp created_at
timestamp updated_at
}
- User Authentication: Users authenticate via Firebase (Google OAuth, Email/Password)
- JWT Token: Firebase issues JWT tokens with user claims
- Data Access: Client sends JWT token to Supabase for data access
- Verification: Supabase verifies JWT token with Firebase
- Auto-Sync: Cloud Functions automatically sync user data from Firebase to Supabase
- Content Management: Directus connects directly to Supabase database for content management
- Row Level Security: Supabase RLS policies ensure users can only access their own data
- Node.js 18+ (Download)
- Docker Desktop (Download)
- Git (Download)
- Firebase Account (Sign up)
- Supabase Account (Sign up)
# Clone the repository
git clone https://github.com/khuepm/LumiBase.git
cd LumiBase
# Copy environment template
cp .env.example .env- Go to Firebase Console
- Click Add project or select an existing project
- Enter your project name (e.g., "LumiBase")
- (Optional) Enable Google Analytics for your project
- Click Create project and wait for setup to complete
- In Firebase Console, go to Authentication β Sign-in method
- Click on Google provider
- Toggle Enable switch to ON
- Configure OAuth consent screen:
- Project support email: Select your email
- Project public-facing name: Enter your app name (e.g., "LumiBase")
- Click Save
Important Notes:
- Google OAuth requires a valid OAuth consent screen configuration
- For production, you'll need to verify your domain
- Users will see the app name during Google sign-in
- In Firebase Console, go to Authentication β Sign-in method
- Click on Email/Password provider
- Toggle Enable switch to ON
- (Optional) Enable Email link (passwordless sign-in) if needed
- Click Save
Security Recommendations:
- Enable email verification for new accounts
- Set password requirements in Firebase Console
- Consider enabling multi-factor authentication (MFA) for production
- In Firebase Console, go to Project Settings (gear icon)
- Click on Integrations tab
- Find Google Analytics and click Enable
- Select an existing Analytics account or create a new one
- Configure Analytics settings:
- Analytics location: Select your region
- Data sharing settings: Configure as needed
- Click Enable Analytics
Benefits of Firebase Analytics:
- Track user authentication events
- Monitor user engagement
- Analyze user demographics
- Debug authentication issues
Service account credentials are required for server-side operations (Cloud Functions).
- Go to Project Settings β Service Accounts tab
- Click Generate New Private Key
- A dialog will appear warning about keeping the key secure
- Click Generate Key - a JSON file will be downloaded
- NEVER commit this file to Git
- Store it securely (use environment variables or secret managers)
- Rotate keys regularly (every 90 days recommended)
-
Open the downloaded JSON file and extract these values to your
.envfile:{ "project_id": "your-project-id", "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n", "client_email": "firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com" } -
Add to
.env:FIREBASE_PROJECT_ID=your-project-id FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
Important: Keep the \n characters in the private key - they represent line breaks.
The Web API Key is used for client-side Firebase SDK initialization.
- Go to Project Settings β General tab
- Scroll down to Your apps section
- If you haven't added a web app yet:
- Click the </> (Web) icon
- Register your app with a nickname (e.g., "LumiBase Web")
- (Optional) Set up Firebase Hosting
- Click Register app
- Copy the Web API Key from the Firebase SDK snippet
- Add to
.env:FIREBASE_WEB_API_KEY=AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
After setting up authentication, you'll need to configure Firebase Functions to sync user data to Supabase.
functions:config API. See Firebase Config Migration Guide for details.
Set Supabase Configuration:
Method 1: Environment Variables (Recommended for Development)
Create functions/.env file:
cd functionsAdd to functions/.env:
SUPABASE_URL=https://xxxxxxxxxxxxx.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9....env to Git! (Already in .gitignore)
Method 2: Firebase Secrets (Production)
# Set secrets for production deployment
firebase functions:secrets:set SUPABASE_URL
# Enter URL when prompted: https://xxxxx.supabase.co
firebase functions:secrets:set SUPABASE_SERVICE_ROLE_KEY
# Enter service role key when promptedMethod 3: Legacy Config (Deprecated)
# Only use if necessary
firebase experiments:enable legacyRuntimeConfigCommands
firebase functions:config:set supabase.url="https://xxxxx.supabase.co"
firebase functions:config:set supabase.service_key="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Verify Configuration:
# For environment variables
cat functions/.env
# For secrets
firebase functions:secrets:access SUPABASE_URL
# For legacy config
firebase functions:config:getAfter completing all steps, your .env file should have:
# Firebase Configuration
FIREBASE_PROJECT_ID=your-project-id
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com
FIREBASE_WEB_API_KEY=AIzaSyXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAnd Firebase Functions should be configured with:
- β Supabase URL
- β Supabase Service Role Key
Next Steps:
- Proceed to Step 3 to configure Supabase
- After completing all setup, deploy Cloud Functions (Step 10)
π Detailed Guide: For comprehensive Firebase Authentication setup instructions, troubleshooting, and security best practices, see Firebase Authentication Guide
π Detailed Guide: For comprehensive Supabase setup instructions, see Supabase Project Setup Guide
- Go to Supabase Dashboard
- Create a new project
- Go to Settings β API
- Copy these values to your
.envfile:SUPABASE_URL(Project URL)SUPABASE_ANON_KEY(anon public key)SUPABASE_SERVICE_ROLE_KEY(service_role secret key)SUPABASE_JWT_SECRET(JWT Secret from Settings β API)
- Configure Firebase as third-party auth provider:
- Go to Authentication β Providers
- Enable Firebase provider
- Enter your Firebase Project ID
- Set Issuer URL:
https://securetoken.google.com/your-firebase-project-id
SUPABASE_SERVICE_ROLE_KEY in client-side code! It bypasses all Row Level Security policies.
- Generate random keys for Directus:
openssl rand -base64 32
- Add them to
.env:DIRECTUS_KEYDIRECTUS_SECRET
- Set your admin credentials:
DIRECTUS_ADMIN_EMAILDIRECTUS_ADMIN_PASSWORD
- Set database credentials in
.env:DB_USER=directusDB_PASSWORD(choose a secure password)DB_NAME=directus
# Install project dependencies
npm install
# Install Supabase CLI (for local development)
npm install supabase --save-dev
# Install Firebase CLI (for Cloud Functions)
npm install -g firebase-tools# Start PostgreSQL and Directus
docker-compose up -d
# Check services are running
docker-compose ps
# View logs
docker-compose logs -fπ Quick Verification Checklist: See docs/task-3-checkpoint-checklist.md
π Detailed Verification Guide: See docs/docker-verification-guide.md
-
Check Docker Services:
docker-compose ps
Both
directus-cmsanddirectus-postgresshould show statusUp -
Check PostgreSQL Connection:
docker-compose exec postgres pg_isready -U directusShould return:
/var/run/postgresql:5432 - accepting connections -
Check Directus Health:
curl http://localhost:8055/server/health
Should return:
{"status": "ok", "checks": {"database": "ok"}} -
Check Directus UI: Open http://localhost:8055
- Login with your admin credentials
- You should see the Directus admin panel
-
View Logs (if needed):
# All services docker-compose logs # Specific service docker-compose logs directus docker-compose logs postgres
β All checks passed? You're ready to proceed to Task 4 (Database Schema)!
β Having issues? Check the Docker Verification Guide for detailed troubleshooting.
After creating database schema and RLS policies (Tasks 4-5), verify the database setup:
π Quick Checklist: See docs/TASK-6-CHECKLIST.md
π Detailed Guide: See docs/TASK-6-DATABASE-VERIFICATION.md
On Linux/Mac:
# Make script executable
chmod +x scripts/verify-database-setup.sh
# Run verification
./scripts/verify-database-setup.shOn Windows PowerShell:
# Run verification
.\scripts\verify-database-setup.ps1The script will automatically verify:
- β Database schema (tables, columns, constraints, indexes)
- β RLS policies (enabled and correctly configured)
- β Trigger functionality (auto-update timestamps)
- β Container health and connectivity
# 1. Restart containers to apply migrations
docker-compose down && docker-compose up -d
# 2. Connect to PostgreSQL
docker-compose exec postgres psql -U directus -d directus
# 3. Verify schema
\d public.users
# 4. Verify RLS is enabled
SELECT rowsecurity FROM pg_tables WHERE tablename = 'users';
# 5. List RLS policies
SELECT policyname, cmd FROM pg_policies WHERE tablename = 'users';
# 6. Exit
\qβ All checks passed? Database setup is complete! Proceed to Task 7 (Firebase Setup).
β Having issues? Check the Database Verification Guide for troubleshooting.
Firebase Cloud Functions automatically sync user data from Firebase Authentication to Supabase database.
- Firebase CLI installed (already done in Step 6)
- Firebase project created (already done in Step 2)
- Firebase login:
firebase login
-
Update
.firebasercwith your project ID:# Edit .firebaserc and replace "your-firebase-project-id" with your actual project ID -
Set Firebase project:
firebase use <your-project-id>
-
Configure Supabase credentials for Cloud Functions:
β οΈ Note: Legacyfunctions:configis deprecated. Use environment variables or secrets instead.Option A: Environment Variables (Development)
cd functionsCreate
functions/.env:SUPABASE_URL=<your-supabase-url> SUPABASE_SERVICE_ROLE_KEY=<your-supabase-service-role-key>
Option B: Firebase Secrets (Production)
firebase functions:secrets:set SUPABASE_URL firebase functions:secrets:set SUPABASE_SERVICE_ROLE_KEY
π Migration Guide: See Firebase Config Migration Guide
cd functions
npm install
npm run build
cd ..cd functions
npm run serveThis starts the Firebase emulator suite:
- Functions: http://localhost:5001
- Auth: http://localhost:9099
- Emulator UI: http://localhost:4000
cd functions
npm run deploy-
Check deployed functions:
firebase functions:list
-
View function logs:
firebase functions:log
-
Test the sync:
- Go to Firebase Console β Authentication
- Create a test user (Email/Password or Google)
- Check Supabase database to verify user was synced:
docker-compose exec postgres psql -U directus -d directus -c "SELECT * FROM public.users;"
β Functions deployed successfully? Your Firebase-Supabase integration is complete!
β Having issues? Check the Firebase Functions README for detailed troubleshooting.
LumiBase/
βββ .kiro/ # Kiro specs and documentation
β βββ specs/
β βββ directus-firebase-supabase-setup/
βββ client/ # Client-side integration examples
β βββ auth.ts # Firebase & Supabase auth integration
βββ functions/ # Firebase Cloud Functions
β βββ src/
β β βββ index.ts # User sync functions
β βββ package.json
βββ init-scripts/ # Database initialization scripts
β βββ 01-create-schema.sql # Create users table and indexes
β βββ 02-setup-rls.sql # Row Level Security policies
βββ scripts/ # Development utility scripts
β βββ verify-database-setup.sh # Verify database setup (Bash)
β βββ verify-database-setup.ps1 # Verify database setup (PowerShell)
β βββ seed-data.sh # Seed initial data
β βββ reset-db.sh # Reset database
βββ tests/ # Test suites
β βββ unit/ # Unit tests
β βββ integration/ # Integration tests
β βββ property/ # Property-based tests
βββ docker-compose.yml # Docker services configuration
βββ .env.example # Environment variables template
βββ .gitignore # Git ignore rules
βββ package.json # Node.js dependencies
βββ README.md # This file
LumiBase includes comprehensive testing infrastructure with isolated test environment.
π Complete Testing Guide: See Testing Procedures Guide for comprehensive instructions on:
- Running unit tests, property-based tests, and integration tests
- Testing authentication flow locally
- Debugging Cloud Functions locally
- Continuous integration setup
# Start test environment
npm run test:env:up
# Run all tests
npm test
# Run specific test types
npm run test:unit # Unit tests only
npm run test:property # Property-based tests only
npm run test:integration # Integration tests only
# Run with coverage
npm run test:coverage
# Stop test environment
npm run test:env:downThe test environment runs on separate ports to avoid conflicts with development:
# Start test environment
npm run test:env:up
# Check test environment status
npm run test:env:status
# View test environment logs
npm run test:env:logs
# Stop test environment
npm run test:env:down
# Clean test environment (remove all data)
npm run test:env:cleanTest Environment Ports:
- PostgreSQL:
5433(dev: 5432) - Directus:
8056(dev: 8055)
- Unit Tests: Test individual functions and components in isolation
- Integration Tests: Test interactions between components (database, API, etc.)
- Property-Based Tests: Test universal properties across many generated inputs
For detailed testing documentation, see:
- Testing Procedures Guide - Complete testing guide
- Test Environment Guide - Test environment setup
- Firebase Emulator Guide - Local Firebase testing
LumiBase includes automated CI/CD workflows using GitHub Actions for continuous integration and deployment.
Test Suite (runs on every push and PR):
- β Unit, integration, and property-based tests
- β Docker configuration validation
- β TypeScript type checking
- β Security vulnerability scanning
- β Test coverage reporting
Deploy Firebase Functions (runs on push to main):
- β Builds and tests Cloud Functions
- β Deploys to Firebase automatically
- β Can be triggered manually
-
Configure GitHub Secrets:
- Go to repository Settings β Secrets and variables β Actions
- Add required secrets:
SUPABASE_URLSUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEYFIREBASE_TOKEN(get withfirebase login:ci)FIREBASE_PROJECT_IDCODECOV_TOKEN(optional)
-
Push to GitHub:
git push origin main
-
Monitor Workflows:
- Go to Actions tab in GitHub
- View workflow runs and logs
Add these to your README to show build status:

For detailed CI/CD setup instructions, see CI/CD Setup Guide.
Ready to deploy LumiBase to production? Follow our comprehensive deployment guide.
π Complete Deployment Guide: See Deployment Procedures Guide for:
- Production deployment checklist
- Security best practices
- Monitoring and logging setup
- Backup and recovery procedures
- Scaling considerations
- Troubleshooting production issues
-
Prepare Environment
- Set up production Firebase project
- Create production Supabase project
- Configure production environment variables
- Generate strong secrets and passwords
-
Deploy Database
- Apply database migrations to production
- Enable RLS policies
- Configure backups
-
Deploy Cloud Functions
cd functions firebase use production firebase deploy --only functions -
Deploy Directus CMS
- Deploy to cloud platform (AWS, GCP, Azure) or VPS
- Configure SSL/TLS certificates
- Set up reverse proxy (nginx)
-
Deploy Client Application
- Build production bundle
- Deploy to hosting (Vercel, Netlify, Firebase Hosting)
-
Configure Monitoring
- Set up error tracking (Sentry)
- Configure uptime monitoring
- Set up log aggregation
- Configure alerts
-
Verify Deployment
- Test authentication flow
- Verify data sync
- Check monitoring and alerts
- Run smoke tests
For detailed instructions, security best practices, and troubleshooting, see the Deployment Procedures Guide.
# Start all services
docker-compose up -d
# Watch logs
docker-compose logs -f
# Start Firebase emulator (optional)
cd functions
firebase emulators:start# Stop all services
docker-compose down
# Stop and remove volumes (clean slate)
docker-compose down -vAdd sample users to the database for development and testing:
On Linux/Mac:
# Make script executable
chmod +x scripts/seed-data.sh
# Run seed script
./scripts/seed-data.shOn Windows PowerShell:
# Run seed script
.\scripts\seed-data.ps1Using TypeScript (Cross-platform):
# Install tsx if not already installed
npm install -g tsx
# Run seed script
npx tsx scripts/seed-data.tsThe seed script will:
- β
Load environment variables from
.env - β Connect to PostgreSQL database
- β Insert 5 sample users (or update if they already exist)
- β Display all users in the database
Sample Users Created:
- alice@example.com (Alice Johnson)
- bob@example.com (Bob Smith)
- charlie@example.com (Charlie Brown)
- diana@example.com (Diana Prince)
- eve@example.com (Eve Wilson)
# Reset database (coming soon)
./scripts/reset-db.sh# Access PostgreSQL shell
docker-compose exec postgres psql -U directus -d directus
# View all users
SELECT * FROM public.users;
# Exit shell
\qcd functions
# Install dependencies
npm install
# Login to Firebase
firebase login
# Select project
firebase use <your-project-id>
# Deploy functions
npm run deploy
# Test locally with emulator
npm run serve- Never commit
.envfile - It contains sensitive credentials - Use strong passwords - Minimum 16 characters with mixed case, numbers, and symbols
- Rotate keys regularly - Change JWT secrets and API keys periodically
- Enable 2FA - On Firebase and Supabase accounts
- Use service accounts - For production deployments
- Monitor logs - Set up alerts for suspicious activities
- Keep dependencies updated - Run
npm auditregularly
- Project Specifications - Detailed project requirements
- Architecture Design - System architecture and design decisions
- Implementation Tasks - Step-by-step implementation guide
- Firebase Authentication Guide - Complete Firebase Authentication setup guide
- Supabase Project Setup Guide - Complete Supabase configuration guide
- Test Environment Guide - Testing infrastructure and procedures
- Testing Procedures Guide - Comprehensive testing guide
- Firebase Emulator Guide - Local Firebase development
- CI/CD Setup Guide - Continuous integration and deployment
- Deployment Procedures Guide - Production deployment, security, monitoring, and backup
- Firebase Documentation
- Supabase Documentation
- Directus Documentation
LumiBase uses Supabase's auto-generated REST API for database operations.
https://your-project-id.supabase.co/rest/v1
All requests must include JWT token in Authorization header:
Authorization: Bearer <firebase-jwt-token>GET /users?firebase_uid=eq.<user-firebase-uid>Example Request:
curl -X GET 'https://xxxxx.supabase.co/rest/v1/users?firebase_uid=eq.abc123' \
-H "Authorization: Bearer <jwt-token>" \
-H "apikey: <supabase-anon-key>"Example Response:
[
{
"firebase_uid": "abc123",
"email": "user@example.com",
"display_name": "John Doe",
"photo_url": "https://example.com/photo.jpg",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]PATCH /users?firebase_uid=eq.<user-firebase-uid>Example Request:
curl -X PATCH 'https://xxxxx.supabase.co/rest/v1/users?firebase_uid=eq.abc123' \
-H "Authorization: Bearer <jwt-token>" \
-H "apikey: <supabase-anon-key>" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Jane Doe",
"photo_url": "https://example.com/new-photo.jpg"
}'Example Response:
{
"firebase_uid": "abc123",
"email": "user@example.com",
"display_name": "Jane Doe",
"photo_url": "https://example.com/new-photo.jpg",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-02T10:30:00Z"
}401 Unauthorized - Invalid or expired JWT token:
{
"code": "PGRST301",
"message": "JWT expired",
"details": null,
"hint": null
}403 Forbidden - RLS policy violation:
{
"code": "42501",
"message": "new row violates row-level security policy",
"details": null,
"hint": null
}Directus provides a comprehensive REST API for content management.
http://localhost:8055
Login:
POST /auth/login
Content-Type: application/json
{
"email": "admin@example.com",
"password": "your-password"
}Response:
{
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires": 900000,
"refresh_token": "abc123..."
}
}GET /items/users
Authorization: Bearer <directus-access-token>Example Response:
{
"data": [
{
"firebase_uid": "abc123",
"email": "user@example.com",
"display_name": "John Doe",
"photo_url": "https://example.com/photo.jpg",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
]
}POST /items/users
Authorization: Bearer <directus-access-token>
Content-Type: application/json
{
"firebase_uid": "new-user-123",
"email": "newuser@example.com",
"display_name": "New User"
}Trigger: Firebase Auth onCreate Purpose: Automatically sync new users to Supabase database
Triggered automatically when:
- User signs up with Email/Password
- User signs in with Google OAuth for the first time
Function behavior:
- Extracts user data from Firebase Auth user object
- Inserts or updates user in Supabase
public.userstable - Uses service role key to bypass RLS policies
- Logs success/failure for monitoring
No manual invocation required - this function runs automatically.
Trigger: Firebase Auth onDelete Purpose: Remove user data from Supabase when deleted from Firebase
Triggered automatically when:
- User is deleted from Firebase Authentication
Function behavior:
- Extracts firebase_uid from deleted user
- Deletes corresponding row from Supabase
public.userstable - Logs success/failure for monitoring
import { initializeApp } from 'firebase/app';
import { getAuth, signInWithPopup, GoogleAuthProvider } from 'firebase/auth';
const firebaseConfig = {
apiKey: process.env.FIREBASE_WEB_API_KEY,
authDomain: `${process.env.FIREBASE_PROJECT_ID}.firebaseapp.com`,
projectId: process.env.FIREBASE_PROJECT_ID,
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
// Sign in with Google
async function signInWithGoogle() {
const provider = new GoogleAuthProvider();
const result = await signInWithPopup(auth, provider);
const token = await result.user.getIdToken();
return { user: result.user, token };
}
// Sign in with Email/Password
async function signInWithEmail(email: string, password: string) {
const result = await signInWithEmailAndPassword(auth, email, password);
const token = await result.user.getIdToken();
return { user: result.user, token };
}import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_ANON_KEY!
);
// Set Firebase JWT token
async function setAuthToken(firebaseToken: string) {
await supabase.auth.setSession({
access_token: firebaseToken,
refresh_token: '',
});
}
// Get current user data
async function getUserData(firebaseUid: string) {
const { data, error } = await supabase
.from('users')
.select('*')
.eq('firebase_uid', firebaseUid)
.single();
if (error) throw error;
return data;
}
// Update user profile
async function updateUserProfile(firebaseUid: string, updates: any) {
const { data, error } = await supabase
.from('users')
.update(updates)
.eq('firebase_uid', firebaseUid)
.select()
.single();
if (error) throw error;
return data;
}// 1. Sign in with Firebase
const { user, token } = await signInWithGoogle();
// 2. Set token for Supabase
await setAuthToken(token);
// 3. Wait for Cloud Function to sync (usually < 2 seconds)
await new Promise(resolve => setTimeout(resolve, 2000));
// 4. Fetch user data from Supabase
const userData = await getUserData(user.uid);
console.log('User authenticated and synced:', userData);Supabase:
- Free tier: 500 requests per second
- Pro tier: 1000+ requests per second
Firebase:
- Authentication: 10 requests per second per IP
- Cloud Functions: 1000 concurrent executions (free tier)
Directus:
- No built-in rate limiting (configure via reverse proxy if needed)
Problem: Port 8055 or 5432 already in use
On Windows:
# Find process using port 8055
netstat -ano | findstr :8055
# Kill the process (replace PID with actual process ID)
taskkill /PID <PID> /F
# Or change port in docker-compose.ymlOn Linux/Mac:
# Find process using port 8055
lsof -i :8055
# Kill the process
kill -9 <PID>
# Or change port in docker-compose.ymlSolution: Change port mapping in docker-compose.yml:
services:
directus:
ports:
- "8056:8055" # Use different host portProblem: PostgreSQL container keeps restarting
Diagnosis:
# Check logs
docker-compose logs postgres
# Check container status
docker-compose psCommon causes:
- Port conflict: Port 5432 already in use
- Permission issues: Volume mount permissions
- Corrupted data: Previous incomplete shutdown
Solutions:
# Solution 1: Remove volumes and restart
docker-compose down -v
docker-compose up -d
# Solution 2: Check port availability
netstat -ano | findstr :5432 # Windows
lsof -i :5432 # Linux/Mac
# Solution 3: Verify environment variables
docker-compose configProblem: Directus container exits immediately after starting
Diagnosis:
# View detailed logs
docker-compose logs directus --tail=100
# Check environment variables
docker-compose exec directus env | grep DB_Common causes:
- Database connection failure: Wrong credentials or PostgreSQL not ready
- Missing environment variables: KEY, SECRET, or ADMIN credentials
- Port conflict: Port 8055 already in use
Solutions:
# Verify database connection
docker-compose exec postgres pg_isready -U directus
# Check environment variables in .env
cat .env | grep -E "DB_|DIRECTUS_"
# Restart with fresh logs
docker-compose down
docker-compose upProblem: Containers can't communicate with each other
Diagnosis:
# List networks
docker network ls
# Inspect network
docker network inspect directus-network
# Test connectivity
docker-compose exec directus ping postgresSolution:
# Recreate network
docker-compose down
docker network prune
docker-compose up -dProblem: Admin credentials don't work
Solution 1 - Reset via environment variables:
# Update .env file with new credentials
DIRECTUS_ADMIN_EMAIL=admin@example.com
DIRECTUS_ADMIN_PASSWORD=newpassword
# Restart Directus
docker-compose restart directusSolution 2 - Create new admin user:
docker-compose exec directus npx directus users create \
--email admin@example.com \
--password newpassword \
--role administratorSolution 3 - Reset database:
# WARNING: This deletes all data
docker-compose down -v
docker-compose up -dProblem: Directus shows "Database connection failed"
Diagnosis:
# Check PostgreSQL is running
docker-compose ps postgres
# Test connection from Directus container
docker-compose exec directus nc -zv postgres 5432Common causes:
- Wrong database credentials in
.env - PostgreSQL not fully started (check health)
- Network issues between containers
Solutions:
# Verify environment variables
echo "DB_HOST: $DB_HOST"
echo "DB_USER: $DB_USER"
echo "DB_NAME: $DB_NAME"
# Wait for PostgreSQL health check
docker-compose up -d postgres
sleep 10
docker-compose up -d directus
# Check PostgreSQL logs
docker-compose logs postgresProblem: Browser shows CORS errors when accessing Directus API
Solution: Update docker-compose.yml:
services:
directus:
environment:
CORS_ENABLED: "true"
CORS_ORIGIN: "true" # Allow all origins (dev only)
# For production, specify exact origins:
# CORS_ORIGIN: "https://yourdomain.com,https://app.yourdomain.com"Then restart:
docker-compose restart directusProblem: firebase deploy --only functions fails
Diagnosis:
# Check Firebase login status
firebase login --reauth
# Verify project
firebase projects:list
firebase use --add
# Check Node.js version
node --version # Should be 18+Common causes:
- Not logged in to Firebase CLI
- Wrong project selected
- Build errors in TypeScript
- Missing dependencies
Solutions:
# Re-authenticate
firebase login --reauth
# Select correct project
firebase use <your-project-id>
# Build and check for errors
cd functions
npm install
npm run build
# Deploy with verbose logging
firebase deploy --only functions --debugProblem: Cloud Functions timeout after 60 seconds
Diagnosis:
# View function logs
firebase functions:log --only syncUserToSupabase
# Check function execution timeSolutions:
- Increase timeout in
functions/src/index.ts:
export const syncUserToSupabase = functions
.runWith({ timeoutSeconds: 120 }) // Increase to 120 seconds
.auth.user().onCreate(async (user) => {
// ... function code
});- Optimize function code:
- Use connection pooling for Supabase client
- Reduce unnecessary API calls
- Add proper error handling
- Check network latency:
# Test Supabase connection speed
curl -w "@curl-format.txt" -o /dev/null -s https://your-project.supabase.coProblem: Functions can't access Supabase credentials
Diagnosis:
# Check current configuration
firebase functions:config:get
# Should show:
# {
# "supabase": {
# "url": "https://...",
# "service_key": "eyJ..."
# }
# }Solution:
# Set configuration
firebase functions:config:set supabase.url="https://xxxxx.supabase.co"
firebase functions:config:set supabase.service_key="eyJhbGc..."
# Deploy functions
firebase deploy --only functionsFor local development, create functions/.runtimeconfig.json:
{
"supabase": {
"url": "https://xxxxx.supabase.co",
"service_key": "eyJhbGc..."
}
}Problem: Supabase returns 401 Unauthorized with valid Firebase token
Diagnosis:
# Decode JWT token to check claims
# Use https://jwt.io or:
echo "<token>" | cut -d. -f2 | base64 -d | jqCommon causes:
- Firebase not configured as auth provider in Supabase
- Wrong JWT secret
- Token expired
- Issuer mismatch
Solutions:
-
Configure Firebase in Supabase Dashboard:
- Go to Authentication β Providers
- Enable Firebase
- Set Project ID:
your-firebase-project-id - Set Issuer:
https://securetoken.google.com/your-firebase-project-id
-
Verify JWT secret matches:
# In Supabase Dashboard: Settings β API β JWT Secret
# Should match SUPABASE_JWT_SECRET in .env- Check token expiration:
// Refresh token if expired
const token = await user.getIdToken(true); // Force refreshProblem: User can't access their own data despite valid JWT
Diagnosis:
-- Connect to database
docker-compose exec postgres psql -U directus -d directus
-- Check if RLS is enabled
SELECT rowsecurity FROM pg_tables WHERE tablename = 'users';
-- List policies
SELECT * FROM pg_policies WHERE tablename = 'users';
-- Test policy manually
SET request.jwt.claims = '{"sub": "test-firebase-uid"}';
SELECT * FROM public.users WHERE firebase_uid = 'test-firebase-uid';Common causes:
- RLS policies not created correctly
- JWT doesn't contain firebase_uid claim
- Policy uses wrong claim name
Solutions:
- Verify RLS policies exist:
-- Should show policies for SELECT, UPDATE, INSERT
SELECT policyname, cmd FROM pg_policies WHERE tablename = 'users';- Check JWT claims:
// Ensure Firebase token contains user_id or sub claim
const token = await user.getIdToken();
const decoded = JSON.parse(atob(token.split('.')[1]));
console.log('JWT claims:', decoded);- Recreate policies if needed:
# Re-run RLS setup script
docker-compose exec postgres psql -U directus -d directus -f /docker-entrypoint-initdb.d/02-setup-rls.sqlProblem: "remaining connection slots are reserved" error
Diagnosis:
-- Check active connections
SELECT count(*) FROM pg_stat_activity;
-- Check max connections
SHOW max_connections;Solutions:
- Increase max connections in
docker-compose.yml:
services:
postgres:
command: postgres -c max_connections=200- Use connection pooling in application code:
import { createClient } from '@supabase/supabase-js';
// Create single client instance (reuse across requests)
const supabase = createClient(url, key, {
db: { schema: 'public' },
auth: { persistSession: false }
});- Close idle connections:
-- Kill idle connections
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle'
AND state_change < NOW() - INTERVAL '5 minutes';Problem: Tests can't connect to database
Diagnosis:
# Check test environment is running
npm run test:env:status
# Check test database port
docker-compose -f docker-compose.test.yml psSolution:
# Start test environment
npm run test:env:up
# Wait for services to be ready
sleep 10
# Run tests
npm testProblem: Property-based tests pass sometimes, fail other times
Diagnosis:
- Check test logs for specific failing inputs
- Look for race conditions or timing issues
Solutions:
- Increase test timeout:
describe('Property Test', () => {
it('should pass', async () => {
// ... test code
}, 10000); // 10 second timeout
});- Add proper cleanup:
afterEach(async () => {
// Clean up test data
await supabase.from('users').delete().neq('firebase_uid', '');
});- Use deterministic seeds:
import fc from 'fast-check';
fc.assert(
fc.property(/* ... */),
{ seed: 42, numRuns: 100 } // Reproducible tests
);Problem: Application fails with "undefined" errors
Diagnosis:
# Check .env file exists
ls -la .env
# Verify variables are loaded
docker-compose config | grep -A 20 environmentSolution:
# Copy from example
cp .env.example .env
# Edit with your values
nano .env # or use your preferred editor
# Restart services to load new variables
docker-compose down
docker-compose up -dProblem: Docker Compose doesn't load .env file
Common causes:
.envfile in wrong location (must be in same directory asdocker-compose.yml)- Syntax errors in
.envfile - Variables with spaces not quoted
Solutions:
- Verify file location:
# .env should be in project root
ls -la .env
pwd- Check syntax:
# Variables should be in format: KEY=value
# No spaces around =
# Quote values with spaces: KEY="value with spaces"
# Test loading
docker-compose config- Use explicit env_file:
services:
directus:
env_file:
- .envProblem: Queries take too long to execute
Diagnosis:
-- Enable query logging
ALTER DATABASE directus SET log_statement = 'all';
-- Check slow queries
SELECT query, calls, total_time, mean_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;Solutions:
- Add indexes:
-- Already created in schema, but verify:
CREATE INDEX IF NOT EXISTS idx_users_email ON public.users(email);
CREATE INDEX IF NOT EXISTS idx_users_firebase_uid ON public.users(firebase_uid);- Optimize queries:
// Use select() to fetch only needed columns
const { data } = await supabase
.from('users')
.select('firebase_uid, email, display_name') // Don't use *
.eq('firebase_uid', uid)
.single();- Enable connection pooling (see Connection Pool Exhausted above)
Problem: Docker containers use too much memory
Diagnosis:
# Check container stats
docker stats
# Check PostgreSQL memory
docker-compose exec postgres free -hSolutions:
- Limit container memory in
docker-compose.yml:
services:
postgres:
mem_limit: 512m
directus:
mem_limit: 256m- Optimize PostgreSQL:
services:
postgres:
command: |
postgres
-c shared_buffers=256MB
-c effective_cache_size=512MB
-c work_mem=16MBIf you're still experiencing issues:
-
Check logs for detailed error messages:
docker-compose logs --tail=100 -f
-
Search existing issues: GitHub Issues
-
Create a new issue with:
- Detailed description of the problem
- Steps to reproduce
- Error messages and logs
- Environment details (OS, Docker version, Node version)
-
Join discussions: GitHub Discussions
-
Check documentation:
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the ISC License - see the LICENSE file for details.
- Firebase team for excellent authentication services
- Supabase team for the amazing PostgreSQL platform
- Directus team for the powerful headless CMS
- All contributors who help improve this project
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: khuepm@example.com
Made with β€οΈ by Khue Pham