Setup & Configuration
Learn how to configure Plainform to connect to your Supabase-hosted PostgreSQL database.
Plainform connects to Supabase's PostgreSQL database using DATABASE_URL (for connection pooling) and DIRECT_URL (for migrations). It also ships with @supabase/supabase-js for optional Supabase platform features, configured with NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY.
Getting Your Connection Strings
Create a Supabase Project
- Go to Supabase Dashboard
- Click "New Project"
- Choose your organization and region
- Set a strong database password (save this - you'll need it)
- Wait for the project to finish provisioning
Get Connection Strings and API Keys
- In your Supabase project, go to Settings → Database
- Scroll to the Connection String section
- You'll see two connection modes:
Connection Pooling (Transaction Mode):
- Used for: Regular database queries via Prisma Client
- Copy the connection string (it includes
?pgbouncer=true) - This will be your
DATABASE_URL
Direct Connection (Session Mode):
- Used for: Database migrations via Prisma Migrate
- Copy the connection string (without
?pgbouncer=true) - This will be your
DIRECT_URL
Then go to Settings → API Keys and copy:
- Project URL: This will be your
NEXT_PUBLIC_SUPABASE_URL - Publishable key: This will be your
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY - Secret key: This will be your
SUPABASE_SECRET_KEYfor trusted server-side admin operations
Add to Environment Variables
Add both connection strings to your .env file:
# Supabase PostgreSQL Connection
DATABASE_URL="postgresql://postgres.xxxxx:[YOUR-PASSWORD]@aws-0-us-west-1.pooler.supabase.com:6543/postgres?pgbouncer=true"
DIRECT_URL="postgresql://postgres.xxxxx:[YOUR-PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres"
# Supabase Client
NEXT_PUBLIC_SUPABASE_URL="https://xxxxx.supabase.co"
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY="sb_publishable_xxxx"
# Trusted server-side admin operations only
SUPABASE_SECRET_KEY="sb_secret_xxxx"Replace [YOUR-PASSWORD] with the database password you set when creating the project.
Verify Configuration
The @t3-oss/env-nextjs schema in env.ts validates these variables:
export const env = createEnv({
server: {
DATABASE_URL: z.string().min(5),
DIRECT_URL: z.string().min(5),
SUPABASE_SECRET_KEY: z.string().min(5),
// ... other variables
},
client: {
NEXT_PUBLIC_SUPABASE_URL: z.string().url(),
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY: z.string().min(5),
// ... other variables
},
// ...
});If either variable is missing or invalid, your app won't start and you'll see a validation error.
Apply Migrations and RLS Policies
Run the included Prisma migrations:
npx prisma migrate devThis creates the database tables and applies Supabase API policies:
Eventis readable with the publishable keyEventwrites require the secret key or Prisma-backed server codeUseris private to public Supabase clientsUserremains available to Prisma-backed webhooks and API routes
Test the Connection
Run Prisma's introspection to verify the connection works:
npx prisma db pullIf successful, you'll see your database schema. If it fails, double-check your connection strings and password.
Connection String Breakdown
Understanding the two connection strings:
DATABASE_URL (Pooled Connection)
postgresql://postgres.xxxxx:[PASSWORD]@aws-0-us-west-1.pooler.supabase.com:6543/postgres?pgbouncer=true- Port:
6543(PgBouncer pooler) - Parameter:
?pgbouncer=true - Used by: Prisma Client for queries
- Why: Connection pooling prevents exhausting database connections in serverless environments
DIRECT_URL (Direct Connection)
postgresql://postgres.xxxxx:[PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres- Port:
5432(standard PostgreSQL) - No pooling parameter
- Used by: Prisma Migrate for schema changes
- Why: Migrations require direct database access (poolers don't support all migration operations)
Prisma Configuration
Your prisma/schema.prisma uses both URLs:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL") // Pooled connection
directUrl = env("DIRECT_URL") // Direct connection
}Prisma automatically uses:
DATABASE_URLfor queries (prisma.user.findMany())DIRECT_URLfor migrations (npx prisma migrate dev)
Supabase Client Helpers
Use the included helpers when you want Supabase features outside of Prisma:
import { supabase } from '@/lib/supabase/client';
const { data, error } = await supabase.functions.invoke('hello-world');import { supabaseServer } from '@/lib/supabase/server';
const { data, error } = await supabaseServer.functions.invoke('hello-world');import { getSupabaseAdmin } from '@/lib/supabase/admin';
const supabaseAdmin = getSupabaseAdmin();Default RLS Policies
The included migrations enable RLS for the default Supabase-facing tables:
| Table | Publishable key access | Secret key access | Prisma access |
|---|---|---|---|
Event | Read only | Read/write | Read/write |
User | No access | Read/write | Read/write |
Use Prisma for application database operations by default. Use the Supabase client when you need Supabase platform features such as Edge Functions, Storage, Realtime, or direct REST access with explicit RLS policies.
Security Best Practices
Never commit your .env file to version control. It's already in .gitignore.
- Use strong passwords: Generate a random 32+ character password for your database
- Rotate credentials: If credentials are exposed, reset your database password in Supabase dashboard
- Keep secret keys server-only: Never expose
SUPABASE_SECRET_KEYto client components or browser code - Environment-specific: Use different databases for development, staging, and production
- Team access: Share connection strings securely (1Password, encrypted channels)
Troubleshooting
Common issues and solutions:
"Invalid connection string"
- Verify you copied the entire string including
postgresql:// - Check for extra spaces or line breaks
- Ensure password is URL-encoded (replace special characters)
"Connection timeout"
- Check your internet connection
- Verify Supabase project is active (not paused)
- Confirm you're using the correct region endpoint
"Too many connections"
- Use
DATABASE_URL(pooled) for queries, notDIRECT_URL - Check if you have connection leaks in your code
- Consider upgrading your Supabase plan for more connections
For more troubleshooting, see the Supabase Troubleshooting page.
Next Steps
- Database Setup - Learn about Prisma schema and models
- Migrations - Create and apply database migrations
- Supabase Documentation - Explore Supabase database features
How is this guide ?
Last updated on