πŸ”βŒ˜K

Start typing to search docs.

Supabase Provisioning

1.0.0

Shared project strategy, prefixed tables, and provisioning steps.

Supabase Setup Guide

Complete guide to setting up Supabase as your App Factory infrastructure provider.

Why Supabase?

Supabase is the recommended infrastructure provider for App Factory because:

  • βœ… All-in-one solution: Database + Auth + Storage + Real-time
  • βœ… Lowest cost: Free tier β†’ $25/month (vs $74+ for AWS+Neon+Clerk)
  • βœ… Fastest setup: 5-10 minutes from zero to deployed
  • βœ… Built-in features: No need for separate auth or storage services
  • βœ… Simple management: One dashboard, one bill, one service

Prerequisites

Before starting, ensure you have:

  1. Forge CLI installed
  2. Doppler account set up
  3. Supabase account (free to create)
  4. Git configured

Step-by-Step Setup

Step 1: Create Supabase Account

  1. Go to https://supabase.com
  2. Click "Start your project"
  3. Sign up with GitHub (recommended) or email
  4. Verify your email address

Step 2: Get Supabase Access Token

  1. Go to https://supabase.com/dashboard/account/tokens
  2. Click "Generate New Token"
  3. Give it a name: App Factory Forge
  4. Copy the token (starts with sbp_)
  5. Save it securely - you won't be able to see it again

Step 3: Get Organization ID

  1. Go to https://supabase.com/dashboard/org/_/general
  2. Copy your Organization ID (starts with org_)
  3. Keep it handy for the next step

Step 4: Configure Doppler

Add your Supabase credentials to Doppler:

# Using Doppler CLI
doppler secrets set SUPABASE_ACCESS_TOKEN="sbp_your_token_here"
doppler secrets set SUPABASE_ORG_ID="org_your_id_here"

Or add them via the Doppler dashboard:

  1. Go to https://doppler.com
  2. Select your project: onepassword-migration
  3. Select config: migration_vault
  4. Add secrets:
    • SUPABASE_ACCESS_TOKEN: Your token
    • SUPABASE_ORG_ID: Your organization ID

Step 5: Create Your First App with Supabase

Using the Forge CLI:

# Create a new app with Supabase
forge create my-awesome-app --provider supabase

# The CLI will:
# 1. Create Pulumi stack
# 2. Provision Supabase project
# 3. Sync credentials to Doppler
# 4. Configure your apps

Or manually with Pulumi:

cd infra/pulumi-supabase

# Configure Pulumi
pulumi stack init my-app-production

# Set configuration
pulumi config set app:name my-app
pulumi config set --secret supabase:accessToken sbp_your_token_here
pulumi config set supabase:organizationId org_your_id_here
pulumi config set --secret supabase:databasePassword YourSecurePassword123!

# Deploy
pulumi up

Step 6: Get Your Credentials

After provisioning, get your Supabase credentials:

# Via Pulumi
pulumi stack output supabaseUrl
pulumi stack output supabaseAnonKey
pulumi stack output databaseUrl

# Or via Doppler (auto-synced)
doppler secrets get NEXT_PUBLIC_SUPABASE_URL
doppler secrets get NEXT_PUBLIC_SUPABASE_ANON_KEY

Step 7: Configure Your Apps

The credentials are automatically synced to Doppler, so your apps can use them immediately:

// In your Next.js app
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

What Gets Created

When you provision a Supabase project, you get:

1. PostgreSQL Database

  • Full Postgres with all extensions
  • Automatic backups (daily on free tier, continuous on Pro)
  • Point-in-time recovery (Pro tier)
  • Connection pooling built-in

2. Authentication

  • OAuth providers: Google, GitHub, Twitter, etc.
  • Email/password authentication
  • Magic links (passwordless)
  • Phone authentication with SMS
  • Multi-factor authentication (MFA)

3. Storage

  • S3-compatible object storage
  • Image transformations on-the-fly
  • Access control via policies
  • CDN delivery automatic

4. Real-time

  • WebSocket subscriptions to database changes
  • Broadcast messages to channels
  • Presence tracking for users

5. Edge Functions

  • Serverless functions at the edge
  • Deploy with CLI or Git
  • TypeScript support built-in

6. Auto-generated APIs

  • REST API automatically generated
  • GraphQL (PostgREST)
  • Type-safe client libraries

Using Supabase Features

Database Operations

// Insert data
const { data, error } = await supabase
  .from('users')
  .insert({ name: 'John Doe', email: 'john@example.com' });

// Query data
const { data, error } = await supabase
  .from('posts')
  .select('*')
  .eq('author_id', userId)
  .order('created_at', { ascending: false });

// Update data
const { data, error } = await supabase
  .from('users')
  .update({ name: 'Jane Doe' })
  .eq('id', userId);

// Delete data
const { data, error } = await supabase
  .from('posts')
  .delete()
  .eq('id', postId);

Authentication

// Sign up with email
const { data, error } = await supabase.auth.signUp({
  email: 'user@example.com',
  password: 'password',
});

// Sign in with Google OAuth
const { data, error } = await supabase.auth.signInWithOAuth({
  provider: 'google',
  options: {
    redirectTo: 'http://localhost:3000/auth/callback',
  },
});

// Magic link (passwordless)
const { data, error } = await supabase.auth.signInWithOtp({
  email: 'user@example.com',
});

// Get current user
const { data: { user } } = await supabase.auth.getUser();

// Sign out
await supabase.auth.signOut();

Storage

// Upload file
const { data, error } = await supabase.storage
  .from('avatars')
  .upload('user-123.png', file, {
    contentType: 'image/png',
    upsert: true,
  });

// Get public URL
const { data } = supabase.storage
  .from('avatars')
  .getPublicUrl('user-123.png');

// Download file
const { data, error } = await supabase.storage
  .from('avatars')
  .download('user-123.png');

// Delete file
const { data, error } = await supabase.storage
  .from('avatars')
  .remove(['user-123.png']);

Real-time Subscriptions

// Subscribe to database changes
const channel = supabase
  .channel('posts')
  .on('postgres_changes', 
    { event: '*', schema: 'public', table: 'posts' },
    (payload) => {
      console.log('Change received!', payload);
    }
  )
  .subscribe();

// Broadcast messages
channel.send({
  type: 'broadcast',
  event: 'message',
  payload: { text: 'Hello!' },
});

// Track presence
channel.track({ user: 'John', status: 'online' });

// Unsubscribe
channel.unsubscribe();

Security: Row Level Security (RLS)

Supabase uses PostgreSQL's Row Level Security to control data access:

-- Enable RLS on a table
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- Users can only see their own posts
CREATE POLICY "Users can view own posts"
ON posts FOR SELECT
USING (auth.uid() = user_id);

-- Users can only insert their own posts
CREATE POLICY "Users can create posts"
ON posts FOR INSERT
WITH CHECK (auth.uid() = user_id);

-- Users can only update their own posts
CREATE POLICY "Users can update own posts"
ON posts FOR UPDATE
USING (auth.uid() = user_id);

-- Users can only delete their own posts
CREATE POLICY "Users can delete own posts"
ON posts FOR DELETE
USING (auth.uid() = user_id);

Database Migrations

Using Supabase CLI

# Install Supabase CLI
brew install supabase/tap/supabase

# Link to your project
supabase link --project-ref your-project-ref

# Create migration
supabase db diff --file new_table

# Apply migration
supabase db push

Using Prisma

# Generate Prisma Client
npx prisma generate

# Create migration
npx prisma migrate dev --name add_posts_table

# Deploy to production
npx prisma migrate deploy

Monitoring & Analytics

Access your project dashboard:

  1. Go to https://supabase.com/dashboard
  2. Select your project
  3. View:
    • Database: Table editor, SQL editor
    • Authentication: User management
    • Storage: File browser
    • Logs: Real-time logs
    • Settings: Project configuration

Pricing & Limits

Free Tier (Perfect for MVP)

  • 500MB database storage
  • 50,000 monthly active users
  • 1GB file storage
  • 2GB bandwidth
  • Unlimited API requests
  • Daily backups (7 days retention)

Cost: $0/month

Pro Tier (When you grow)

  • 8GB database storage
  • 100,000 monthly active users
  • 100GB file storage
  • 200GB bandwidth
  • Unlimited API requests
  • Point-in-time recovery
  • Daily backups (90 days retention)
  • Priority support

Cost: $25/month

Enterprise (For large scale)

  • Custom everything
  • Dedicated infrastructure
  • SLA guarantees
  • Custom support

Cost: Contact sales

Common Issues & Solutions

Issue: "Project creation failed"

Solution: Check your access token and organization ID are correct.

Issue: "Database connection refused"

Solution: Ensure you're using the correct connection string and database password.

Issue: "Authentication not working"

Solution:

  1. Check OAuth redirect URLs are configured
  2. Verify API keys are correct
  3. Ensure RLS policies allow the operation

Issue: "Storage upload fails"

Solution:

  1. Check bucket exists and is public if needed
  2. Verify file size is within limits
  3. Check storage policies allow upload

Best Practices

DO βœ…

  • Enable RLS on all tables
  • Use Supabase client for all database operations
  • Store service role key securely (never in client-side code)
  • Use database functions for complex logic
  • Set up proper indexes for performance
  • Regular backups (automatic on Pro tier)

DON'T ❌

  • Don't expose service role key to clients
  • Don't skip RLS policies (security risk)
  • Don't store sensitive data without encryption
  • Don't hardcode credentials in code
  • Don't ignore rate limits on free tier

Migration from Other Providers

From AWS RDS

# 1. Export from RDS
pg_dump -h your-rds-endpoint.amazonaws.com -U postgres -d mydb > backup.sql

# 2. Import to Supabase
psql "postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres" < backup.sql

From Neon

# 1. Export from Neon
neon db dump > backup.sql

# 2. Import to Supabase
supabase db push --file backup.sql

Next Steps

  1. βœ… Read the Architecture Guide: docs/ARCHITECTURE_GUIDE.md
  2. βœ… Explore Supabase docs: https://supabase.com/docs
  3. βœ… Build your first feature: Start with authentication
  4. βœ… Set up RLS policies: Secure your data
  5. βœ… Deploy to production: Use Forge CLI

Support


πŸŽ‰ You're all set! Start building your app with Supabase as your backend. πŸš€