Supabase + Next.js Onboarding Guide
Documentation goals:
- Help new developers understand Supabase quickly and build an MVP in a few days.
- Establish internal standards to scale the dev team, easily onboard new members, or compare effort with traditional backends.
- Provide a foundation for future best practices (batch jobs, auth, RLS, CI/CD, etc.).
🏁 Part 0. Introduction & Overview
Documentation goals
- Training objectives (learning outcomes)
- Target audience (frontend, fullstack, backend devs, interns, etc.)
- How to read the documentation: by week / by module
Supabase + Next.js architecture overview
Diagram: Next.js (App Router) ↔ Supabase (DB + Auth + Storage + Functions)
Explanation of main components:
- Database (Postgres)
- Auth
- Storage
- Edge Functions
- Cron & Queue
- Realtime
Quick comparison with traditional backend (NestJS, Express, Postgres, S3, etc.)
Case study throughout (Sample App)
- Introduction to sample app (e.g., "Subscription Manager")
- Features to implement: Auth, CRUD, Batch Job, Upload, Cron
- Directory structure, learning flow by module
🧱 Part 1. Setup & Environment Preparation
Tool installation
- Node.js / pnpm / npm
- Supabase CLI (
supabase login,supabase start,...) - VSCode plugins (SQLTools, Supabase, etc.)
Project initialization
npx create-next-appnpx supabase init- Configure
.env(Supabase URL, Anon Key) - Test connection with Supabase SDK
Run Supabase locally
supabase start, access http://localhost:54323- Create user, test Auth
- Simulate complete local dev environment
Recommended directory structure
/app- Next.js App Router/lib- Supabase client, hooks/supabase- migrations, policies, seeds/scripts- batch jobs, automation
🔐 Part 2. Authentication
Supabase Auth architecture
- Explanation of JWT mechanism,
auth.uid() - Anon key vs Service role key
- Sign in/out flow
- Explanation of JWT mechanism,
Implement Auth with Next.js
@supabase/supabase-js&@supabase/ssrCreate Supabase client for:
- Client-side (browser)
- Server-side (SSR)
Middleware to protect routes (
middleware.ts)
Login types
- Email/password
- Magic link
- OAuth (Google, GitHub)
- OTP (SMS/Email OTP if needed)
Session management
- Store session in cookie (server component)
- Refresh token
- Logout / Revalidate session
Customize Auth
- Custom user metadata
- Hooks
auth.users→profiletable sync - Best practice: sync user profile using trigger or Edge Function
🔑 Part 3. Authorization (RLS & Policy)
Introduction to RLS (Row-Level Security)
- What RLS is and why Supabase is "secure by default"
- Configure RLS on table
Write basic policies
- SELECT / INSERT / UPDATE / DELETE
- Using
auth.uid() - Example: "User can only view their own tasks"
Organize Roles & Permissions
- Map roles to JWT claims
- Multi-tenant design:
organization_id - Admin / Owner / Member policies
Best Practices
- "Always RLS On"
- Test policies before coding (SQL playground)
- Convention for writing policy.sql / migration.sql files
💾 Part 4. Database & Migrations
Schema design
- Example tables:
users,organizations,memberships,tasks - Using enums, indexes, constraints
- Naming conventions
- Example tables:
Migrations with Supabase CLI
supabase db pushsupabase migration new add_tasks_table- Manage migration files, version control
Seeding & sample data
supabase db seed- Scripts to create data for dev/test environments
Query & Performance
- RPC functions
- Caching (Next.js revalidate tag)
- Use
explain analyzeto check queries
🌐 Part 5. Supabase + Next.js Integration
Next.js App Router with Supabase
- How to call Supabase from server components
- Use Server Actions for CRUD
- Protect routes (redirect if not logged in)
Realtime Subscription
- Realtime setup (
supabase.channel) - Update UI when DB changes
- Example: Realtime task board
- Realtime setup (
Storage (Upload & Access Control)
- Create bucket, configure policies
- Upload files, get signed URLs
- Security: users can only view their own files
Edge Functions
- When to use them
- Write Edge Functions (
supabase functions new send-email) - Test and deploy Edge Functions
- Call Edge Functions from Next.js (client/server)
⏰ Part 6. Batch Job & Background Tasks
Batch jobs with pg_cron
- Install
pg_cronextension - Create scheduled jobs (cleanup, sync, aggregate)
- Best practices for cron in DB
- Install
Edge Function + Cron Scheduler
- Create Edge Function and register Cron job
- Use case: send email reminders
Queues (pgmq)
- Install pgmq extension
- Push / Consume jobs
- Pattern: async processing in Supabase
Compare Cron vs Queue
- Cron → scheduled
- Queue → event-driven
Monitor jobs
- Logs in Supabase dashboard
- Retry / failure tracking
🧩 Part 7. API & Integration Patterns
Direct Query vs API Proxy
- When FE calls Supabase directly
- When to use an intermediate API layer (Route Handler / Function)
Webhooks
- Create DB trigger → call Edge Function
- Example: when user registers → send welcome email
Third-party integrations
- Stripe / GitHub / Slack webhooks
- Best practice: store audit logs
⚙️ Part 8. CI/CD & DevOps
Supabase CLI in pipeline
- Login with token
- Run migrations, tests, deploy functions
- Example GitHub Actions YAML
Environment management
- Dev / Staging / Prod setup
- Env key & secrets conventions
- Sync schema between environments
Deploy Next.js
- Vercel / Cloudflare / Render
- Connect to Supabase project
- Zero-downtime deployment
Testing
- Unit test Next.js logic
- Integration test with Supabase local
- Mock Supabase in Jest
🔍 Part 9. Observability & Debugging
Logs
- Database logs
- Edge Function logs
- Cron / Queue logs
Request tracing
- Attach
request_idthroughout - Error tracking
- Attach
Monitoring
- Alert email / Slack when jobs fail
- Basic metrics (API latency, job duration, etc.)
🔒 Part 10. Security Best Practices
API keys & secrets
- Manage Anon key / Service role key
- Never expose service key to client
RLS mandatory
- RLS checklist when creating new tables
- How to quickly test policies
Rate limiting & abuse
- Use Edge Function middleware
- Logging and spam detection
💰 Part 11. Cost & Performance Optimization
Cost optimization
- Configure appropriate Supabase plan
- Use Storage & Realtime efficiently
Performance optimization
- Index / query tuning
- Cache layer in Next.js
- When to move logic to Edge Functions
Benchmark
- Compare CRUD performance: Supabase vs traditional API backend
📊 Part 12. Comparison with Traditional Tech Stack
| Category | Supabase + Next.js | Traditional Backend |
|---|---|---|
| Auth | Built-in | Must code + DB |
| Storage | Built-in | Self-configure S3 |
| Cron / Batch | pg_cron / Edge Function | Bull / Cloud Tasks |
| Queue | pgmq | Redis / SQS |
| Realtime | Built-in | WebSocket / Socket.IO |
| DevOps | CLI + Dashboard | Self-setup infra |
| Initial cost | Very low | Medium - high |
| Large-scale scaling | Vendor limits | Full control |
🧠 Part 13. Appendix (Advanced)
Multi-project / Monorepo
- Integrate multiple Supabase projects
- Separate environments
Custom Postgres extensions
- Use
pgvector,postgis,citext,pg_partman
- Use
Analytics & AI integration
- Use Supabase Vector
- Query embedding / RAG pattern
Troubleshooting
- Common errors (RLS deny, token expired, etc.)
- Debug checklist
📎 Part 14. References
Supabase Docs (database, auth, cron, queue, cli, function)
Next.js App Router Docs
Example repo (Supabase + Next.js Starter)
Internal:
supabase_onboarding.mdsupabase_best_practices.sqlgithub-actions-supabase.yml