1. Quick Start
Supabase is an open-source Firebase alternative that provides a full backend platform built on Postgres. It offers a managed database, authentication, real-time subscriptions, file storage, edge functions, and auto-generated REST and GraphQL APIs — all accessible through client SDKs or a web dashboard called Supabase Studio.
Key features:
- Postgres database with Row Level Security (RLS), extensions, and full SQL access
- Authentication supporting email/password, magic links, phone OTP, and 20+ OAuth providers
- Realtime subscriptions via WebSockets for Postgres changes, broadcast, and presence
- Storage for files with CDN, image transformations, and resumable uploads
- Edge Functions — Deno-based serverless functions deployed globally
- Auto-generated APIs — PostgREST (REST) and pg_graphql (GraphQL) from your schema
- Supabase Studio — web-based dashboard for managing your project
Prerequisites: A Supabase account at supabase.com, or Docker for self-hosting.
Get started in 60 seconds:
npm install @supabase/supabase-js
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
'https://your-project.supabase.co',
'your-anon-key'
)
// Query your database
const { data, error } = await supabase
.from('todos')
.select('*')
[ { id: 1, task: 'Buy groceries', is_complete: false } ]
Tip
Find your project URL and anon key in the Supabase Dashboard under Settings > API. The anon key is safe to use in client-side code — Row Level Security protects your data.
What to try next:
- Set up authentication (see "Authentication" in Core Usage)
- Create database tables in the Studio Table Editor
- Add real-time subscriptions to your app
- See the Admin Guide for self-hosting and architecture details
2. Installation
System requirements
| Requirement | Minimum |
|---|---|
| Node.js | 18+ (22+ for monorepo development) |
| Package manager | npm, yarn, pnpm, or bun |
| Browser | Modern browser for Studio access |
Client SDK installation
npm
npm install @supabase/supabase-js
yarn
yarn add @supabase/supabase-js
pnpm
pnpm add @supabase/supabase-js
bun
bun add @supabase/supabase-js
Important
The
@supabase/supabase-jspackage (v2.103.2 as of this source) bundles@supabase/auth-js,@supabase/postgrest-js,@supabase/realtime-js, and@supabase/storage-js. You do not need to install these separately unless you want to use them standalone.
Supabase CLI installation
The Supabase CLI is distributed separately via the supabase npm package. It manages local development, migrations, and deployments.
npm
npm install -D supabase
Homebrew
brew install supabase/tap/supabase
Verification
npx supabase --version
2.76.10
import { createClient } from '@supabase/supabase-js'
console.log('Supabase JS loaded successfully')
Self-hosting with Docker
For self-hosted deployments, Supabase provides a complete Docker Compose setup:
git clone --depth 1 https://github.com/supabase/supabase
cd supabase/docker
cp .env.example .env
docker compose pull
docker compose up -d
Warning
The default
.env.exampleships with example secrets (JWT secret, anon key, service role key). You must generate new secrets before exposing the instance to any network. See the Admin Guide for secure configuration.
After startup, access Supabase Studio at http://localhost:8000 with the dashboard credentials from your .env file.
Install troubleshooting
Error: Cannot find module '@supabase/supabase-js'
Cause: Package not installed or wrong node_modules resolution.
Solution:
- Run
npm install @supabase/supabase-jsagain - Check your
package.jsonincludes the dependency - Delete
node_modulesandpackage-lock.json, then reinstall
Prevention: Pin the version in package.json and use a lockfile.
Error: pnpm: command not found (monorepo development)
Cause: The Supabase monorepo requires pnpm 10.24 specifically.
Solution:
npm install -g pnpm@10.24
Prevention: The root package.json enforces pnpm via a preinstall script (npx only-allow pnpm).
Error: Docker containers fail to start
Cause: Missing .env file or port conflicts.
Solution:
- Verify
.envexists indocker/directory - Check for port conflicts on 8000, 5432, 9000
- Run
docker compose logsto identify the failing service
Prevention: Always copy .env.example before first start.
3. Configuration
Client initialization
Every Supabase client requires two values: your project URL and your anon key:
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)
Common environment variables
| Variable | Purpose | Example |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Project API URL | https://xyzproject.supabase.co |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Public (anon) API key | eyJhbGciOiJI... |
SUPABASE_SERVICE_ROLE_KEY |
Server-side admin key | eyJhbGciOiJI... |
EXPO_PUBLIC_SUPABASE_URL |
Expo/React Native project URL | https://xyzproject.supabase.co |
EXPO_PUBLIC_SUPABASE_ANON_KEY |
Expo/React Native anon key | eyJhbGciOiJI... |
VUE_APP_SUPABASE_URL |
Vue/Ionic project URL | https://xyzproject.supabase.co |
VUE_APP_SUPABASE_KEY |
Vue/Ionic anon key | eyJhbGciOiJI... |
REACT_APP_SUPABASE_URL |
Create React App project URL | https://xyzproject.supabase.co |
REACT_APP_SUPABASE_ANON_KEY |
Create React App anon key | eyJhbGciOiJI... |
Warning
The
SUPABASE_SERVICE_ROLE_KEYbypasses Row Level Security entirely. Never expose it in client-side code — use it only in server-side environments (API routes, edge functions, backend services).
Framework-specific SSR setup
Supabase provides a dedicated package for server-side rendering:
npm install @supabase/ssr
This package (@supabase/ssr v0.10.2) handles cookie-based auth for Next.js, SvelteKit, Nuxt, and other SSR frameworks.
Local development configuration
The local Supabase CLI uses supabase/config.toml to configure services:
[api]
port = 54321
schemas = ["public", "storage", "graphql_public"]
extra_search_path = ["public", "extensions"]
max_rows = 1000
[db]
port = 54322
major_version = 15
[studio]
port = 54323
[auth]
site_url = "http://localhost:3000"
jwt_expiry = 3600
enable_signup = true
[auth.email]
enable_signup = true
double_confirm_changes = true
enable_confirmations = false
[storage]
file_size_limit = "50MiB"
Note
The
schemasarray under[api]controls which Postgres schemas are exposed via the REST API. Thepublicandstorageschemas are always included.
For the complete configuration reference including all auth providers, storage backends, and deployment settings, see the Admin Guide.
4. Core Usage
Database queries
Supabase auto-generates a REST API from your Postgres schema via PostgREST. Use the JavaScript client to query tables:
Select rows:
const { data, error } = await supabase
.from('countries')
.select('id, name, population')
.order('name')
Insert rows:
const { data, error } = await supabase
.from('countries')
.insert({ name: 'Japan', population: 125800000 })
.select()
Update rows:
const { data, error } = await supabase
.from('countries')
.update({ population: 125700000 })
.eq('name', 'Japan')
.select()
Delete rows:
const { data, error } = await supabase
.from('countries')
.delete()
.eq('id', 42)
Filtering:
const { data } = await supabase
.from('countries')
.select('*')
.gte('population', 1000000)
.ilike('name', '%land%')
.limit(10)
Note
The API respects Row Level Security policies. The default
max_rowsis 1000 (configurable insupabase/config.tomlunder[api]). Use.range()for pagination beyond this limit.
Authentication
Supabase Auth (GoTrue) supports multiple authentication methods.
Email/password signup:
const { data, error } = await supabase.auth.signUp({
email: '[email removed]',
password: 'secure-password',
})
Email/password login:
const { data, error } = await supabase.auth.signInWithPassword({
email: '[email removed]',
password: 'secure-password',
})
OAuth login:
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'github',
})
Supported OAuth providers: Apple, Azure, Bitbucket, Discord, Facebook, Figma, GitHub, GitLab, Google, Keycloak, LinkedIn, LinkedIn OIDC, Notion, Twitch, Twitter, Slack, Spotify, WorkOS, and Zoom.
Sign out:
const { error } = await supabase.auth.signOut()
Listen to auth state changes:
supabase.auth.onAuthStateChange((event, session) => {
console.log(event, session)
})
Tip
Use
supabase.auth.getUser()rather thansupabase.auth.getSession()for server-side validation —getUser()verifies the JWT with the auth server, whilegetSession()only reads the local session.
Realtime subscriptions
Subscribe to database changes, broadcast messages, or track user presence.
Listen to INSERT events:
const channel = supabase
.channel('todos')
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'todos',
}, (payload) => {
console.log('New todo:', payload.new)
})
.subscribe()
Broadcast messages:
const channel = supabase.channel('room-1')
// Send
channel.send({
type: 'broadcast',
event: 'cursor',
payload: { x: 100, y: 200 },
})
// Receive
channel.on('broadcast', { event: 'cursor' }, (payload) => {
console.log('Cursor position:', payload)
})
Presence (track online users):
const channel = supabase.channel('online-users')
channel.on('presence', { event: 'sync' }, () => {
const state = channel.presenceState()
console.log('Online users:', state)
})
channel.subscribe(async (status) => {
if (status === 'SUBSCRIBED') {
await channel.track({ user_id: '123', online_at: new Date() })
}
})
Note
Realtime requires the table to be added to the
supabase_realtimepublication. In SQL:alter publication supabase_realtime add table your_table;
Storage
Upload, download, and manage files with Supabase Storage.
Upload a file:
const { data, error } = await supabase.storage
.from('avatars')
.upload('public/avatar.png', file, {
cacheControl: '3600',
upsert: false,
})
Download a file:
const { data, error } = await supabase.storage
.from('avatars')
.download('public/avatar.png')
Get a public URL:
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('public/avatar.png')
List files in a bucket:
const { data, error } = await supabase.storage
.from('avatars')
.list('public', { limit: 100, offset: 0 })
The default file size limit is 50MiB (configurable in supabase/config.toml under [storage]).
Edge Functions
Invoke Deno-based serverless functions:
const { data, error } = await supabase.functions.invoke('my-function', {
body: { name: 'World' },
})
Edge Functions are deployed via the Supabase CLI:
npx supabase functions deploy my-function
Important
By default, Edge Functions require a valid JWT. To make a function publicly accessible, set
verify_jwt = falsein yoursupabase/config.tomlunder[functions.function-name]. The monorepo's ownsearch-embeddingsfunction uses this pattern.
5. Common Tasks
Set up a new project with Next.js
Goal: Create a Next.js app connected to Supabase with authentication.
Prerequisites: Node.js 18+, a Supabase project.
Steps:
-
Create a Next.js app:
npx create-next-app my-app cd my-app -
Install Supabase packages:
npm install @supabase/supabase-js @supabase/ssr -
Add environment variables to
.env.local:NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key -
Create a Supabase client utility:
// lib/supabase.js import { createClient } from '@supabase/supabase-js' export const supabase = createClient( process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ) -
Use it in a component:
const { data } = await supabase.from('todos').select('*')
Verify: Data loads from your Supabase project in the browser.
Create a user profile system with avatar uploads
Goal: Set up a profiles table with RLS and avatar storage.
Steps:
-
Create the profiles table in SQL Editor:
create table profiles ( id uuid references auth.users not null primary key, updated_at timestamp with time zone, username text unique, avatar_url text, website text, constraint username_length check (char_length(username) >= 3) ); alter table profiles enable row level security; create policy "Users can view their own profile." on profiles for select using (auth.uid() = id); create policy "Users can insert their own profile." on profiles for insert with check (auth.uid() = id); create policy "Users can update their own profile." on profiles for update using (auth.uid() = id); -
Create a storage bucket for avatars:
insert into storage.buckets (id, name) values ('avatars', 'avatars'); create policy "Avatar images are publicly accessible." on storage.objects for select using (bucket_id = 'avatars'); create policy "Anyone can upload an avatar." on storage.objects for insert with check (bucket_id = 'avatars'); -
Set up realtime for profile updates:
alter publication supabase_realtime add table profiles; -
Query and update the profile from your app:
// Fetch profile const { data } = await supabase .from('profiles') .select('username, avatar_url, website') .eq('id', user.id) .single() // Update profile await supabase .from('profiles') .upsert({ id: user.id, username: 'newname', updated_at: new Date() })
Verify: Users can view and edit only their own profile.
If it fails: Check that RLS policies are active with select * from pg_policies where tablename = 'profiles';
Enable real-time for a table
Goal: Receive live updates when rows change.
Steps:
-
Enable the realtime publication:
alter publication supabase_realtime add table todos; -
Subscribe in your client:
supabase .channel('todos-changes') .on('postgres_changes', { event: '*', schema: 'public', table: 'todos', }, (payload) => { console.log('Change:', payload) }) .subscribe()
Verify: Insert a row in the Studio Table Editor and confirm the subscription fires.
If it fails: Check that RLS allows SELECT for the subscribing user role.
Set up local development
Goal: Develop against a local Supabase stack.
Steps:
-
Initialize Supabase in your project:
npx supabase init -
Start the local stack:
npx supabase start -
The CLI outputs local URLs and keys:
API URL: http://127.0.0.1:54321 Studio URL: http://127.0.0.1:54323 Inbucket URL: http://127.0.0.1:54324 anon key: eyJ... service_role key: eyJ... -
Point your app to the local instance:
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321 NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
Verify: Open Studio at http://127.0.0.1:54323.
Tip
Use
npx supabase db resetto rerun migrations and seed data. Usenpx supabase status --output json > keys.jsonto programmatically capture keys. The local email testing server (Inbucket) at port 54324 captures all auth emails.
Build a Slack clone with real-time messaging
Goal: Create a multi-channel chat application.
The examples/slack-clone/ directory provides a complete Next.js implementation. The key patterns:
- Channels table with RLS for authorized access
- Messages table joined to user profiles
- Realtime subscriptions for new messages per channel
- Presence tracking for online users in each channel
// Subscribe to new messages in a channel
const channel = supabase
.channel(`room:${channelId}`)
.on('postgres_changes', {
event: 'INSERT',
schema: 'public',
table: 'messages',
filter: `channel_id=eq.${channelId}`,
}, (payload) => {
setMessages(prev => [...prev, payload.new])
})
.subscribe()
Integrate with Clerk for external authentication
Goal: Use Clerk as an external auth provider with Supabase.
The examples/clerk/ directory demonstrates this pattern. It includes a Supabase migration (examples/clerk/supabase/migrations/) that creates a requesting_user_id() helper function to extract the user ID from Clerk JWTs.
- Configure Clerk JWT templates to include Supabase claims
- Create a Supabase client that passes the Clerk JWT:
const supabase = createClient(url, anonKey, { global: { headers: { Authorization: `Bearer ${clerkToken}` }, }, })
Implement caching with React Query
Goal: Use TanStack React Query for client-side caching of Supabase data.
The examples/caching/with-react-query-nextjs-14/ directory shows the pattern:
import { useQuery } from '@tanstack/react-query'
function useTodos() {
return useQuery({
queryKey: ['todos'],
queryFn: async () => {
const { data, error } = await supabase.from('todos').select('*')
if (error) throw error
return data
},
})
}
Set up multi-factor authentication (Flutter)
Goal: Add MFA to a Flutter app.
The examples/auth/flutter-mfa/ directory provides a complete implementation including:
- Enroll a TOTP factor after sign-in
- Challenge verification flow
- UI for entering the 6-digit code
Deploy edge functions with WASM modules
Goal: Use WebAssembly modules inside Edge Functions.
The examples/edge-functions/supabase/functions/wasm-modules/ directory demonstrates loading and calling Rust-compiled WASM within a Deno Edge Function:
// src/lib.rs
#[no_mangle]
pub extern "C" fn add(a: u32, b: u32) -> u32 {
a + b
}
Use OAuth authorization flow for third-party apps
Goal: Build an app that authenticates via Supabase as an OAuth 2.0 provider.
The examples/oauth-app-authorization-flow/ provides a Hono-based example with /callback handling:
// Handle the OAuth callback
app.get('/callback', async (c) => {
const code = c.req.query('code')
// Exchange code for tokens
})
Note
Issue #45006 reports that the OAuth 2.1 consent example documentation references
redirect_towhen the actual response property isredirect_url. Useredirect_urlas shown in the source code.
6. Troubleshooting
Diagnostic decision tree
Problem with Supabase?
├── Can't connect to the API?
│ ├── Check project URL and API key are correct
│ ├── Verify the project is not paused (Dashboard > Settings)
│ └── Check DNS resolution (issue #44977)
├── Auth not working?
│ ├── Check redirect URLs in Dashboard > Auth > URL Configuration
│ ├── Verify OAuth provider credentials
│ └── Check regional connectivity (issue #45002)
├── Realtime not receiving events?
│ ├── Table added to supabase_realtime publication?
│ ├── RLS policies allow SELECT for the subscribing user?
│ └── Check WebSocket connection in browser DevTools
├── Slow queries?
│ ├── Add indexes for frequently filtered columns
│ ├── Check query plan with EXPLAIN ANALYZE
│ └── Review RLS policy complexity
└── Self-hosting issues?
├── All containers running? docker compose ps
├── .env file present with valid secrets?
└── Check service logs: docker compose logs <service>
Error: Failed to fetch on API calls
Cause: Network connectivity issue, project paused, or DNS resolution failure. Community reports of regional connectivity problems (issue #44978).
Solution:
- Verify your project URL resolves:
nslookup your-project.supabase.co - Check the Supabase status page
- If self-hosting, verify all Docker containers are healthy:
docker compose ps
Prevention: Implement retry logic with exponential backoff in production apps.
Error: Discord OAuth consistently slow (5+ seconds)
Cause: GoTrue auth worker latency for specific OAuth providers (issue #45014).
Solution:
- This is a known platform issue being investigated
- Implement a loading state in your UI during OAuth redirects
- Check if the issue persists across different project regions
Error: Functions deploy returns 500 (internal error)
Cause: Internal server error during function deployment, potentially specific to certain function slugs (issue #45013).
Solution:
- Retry the deployment after a brief wait
- Test the function locally first:
npx supabase functions serve my-function - Verify the function name doesn't conflict with reserved names
- Check function dependencies compile cleanly
Prevention: Always test functions locally with supabase functions serve before deploying.
Error: Password reset link creates unintended session
Cause: Password reset flow creates an authenticated session before the user changes their password (issue #32681).
Solution:
- Handle the
PASSWORD_RECOVERYevent explicitly inonAuthStateChange:supabase.auth.onAuthStateChange((event, session) => { if (event === 'PASSWORD_RECOVERY') { // Redirect to password change form, NOT to protected routes } }) - Implement a dedicated password reset page that checks the token type
Prevention: Always handle PASSWORD_RECOVERY separately from SIGNED_IN.
Error: Phone Auth not enabling despite correct Twilio credentials
Cause: Configuration format or credential mismatch (issue #44966).
Solution:
- Verify Twilio Account SID starts with
AC - Confirm Auth Token is the primary token, not a secondary one
- Re-enter credentials in Dashboard > Auth > Providers > Phone
- Save and wait 60 seconds for configuration to propagate
Error: SUPABASE_URL missing!
Cause: Environment variable not set or not loaded.
Solution:
- Check
.envor.env.localfile exists and contains the variable - Restart your development server after adding env vars
- For frameworks, use the correct prefix:
NEXT_PUBLIC_(Next.js),EXPO_PUBLIC_(Expo),REACT_APP_(CRA),VUE_APP_(Vue CLI)
Prevention: Use a .env.example file to document required variables.
Error: Row Level Security blocks all access
Cause: RLS is enabled but no policy grants access.
Solution:
- Check existing policies:
select * from pg_policies where tablename = 'your_table'; - Add appropriate policies for SELECT, INSERT, UPDATE, DELETE
- Test with the SQL Editor using
set role authenticated;orset role anon;
Prevention: Design and test RLS policies before enabling RLS on a table.
Caution
Disabling RLS (
alter table your_table disable row level security;) exposes all rows to anyone with the anon key. Only disable for truly public, non-sensitive data.
Error: Foreign row save failures silently swallowed in Studio
Cause: Studio's SidePanelEditor does not surface errors from foreign key constraint violations (issue #44949).
Solution:
- Use the SQL Editor to run the INSERT/UPDATE directly and see the full error
- Verify the referenced foreign key value exists in the parent table
- Check the browser console Network tab for the underlying API error
Error: Project stuck on pausing or unpausing
Cause: Infrastructure provisioning delay (issue #45001).
Solution:
- Wait 30 minutes — most operations complete within this window
- If still stuck after 1 hour, contact Supabase support via the Dashboard
- Check the status page for ongoing incidents
Warning
Do not repeatedly trigger pause/unpause — each attempt queues a new operation and may extend the wait time.
Error: Connect modal stuck on loading for non-JS frameworks
Cause: Studio's connect modal only renders connection details for JavaScript-based frameworks (issues #44984, #44985).
Solution:
- Use the Settings > API page to get connection details directly
- Copy the project URL and API keys manually
- Use the generic REST API documentation for non-JS languages
Error: Can't save Email auth settings
Cause: Known issue with the auth settings form in Studio (issue #3192).
Solution:
- Clear browser cache and retry
- Try a different browser
- If persists, configure email auth via the Supabase CLI config instead
Error: invalid secret key after Postgres upgrade
Cause: PG 15 and PG 17 use different postgres UIDs. Starting a PG 17 container with a leftover db-config volume from PG 15 produces this error.
Solution:
- Run the upgrade script:
docker/utils/upgrade-pg17.sh - Or remove the old volume:
docker volume rm supabase_db-config
Prevention: Follow the Postgres 17 upgrade guide before switching images.
7. FAQ
Q: What is Supabase?
Supabase is an open-source Firebase alternative that provides a Postgres database, authentication, real-time subscriptions, file storage, edge functions, and auto-generated APIs. You can use it as a hosted platform or self-host with Docker.
Q: Is Supabase free?
Supabase offers a free tier for hobby projects. Paid plans add more resources and features. Self-hosting is free — you provide the infrastructure.
Q: Can I use Supabase with frameworks other than React?
Yes. The JavaScript SDK (@supabase/supabase-js) works with any JavaScript framework. The repo's examples/ directory includes working implementations for Next.js, SvelteKit, Nuxt 3, Angular, Ionic (React, Angular, Vue), React Native (Expo), Flutter, Solid, Svelte, and more. The blocks/vue/ directory provides pre-built Vue/Nuxt UI blocks.
Q: How do I connect from a mobile app?
For React Native/Expo, use @supabase/supabase-js with EXPO_PUBLIC_SUPABASE_URL and EXPO_PUBLIC_SUPABASE_ANON_KEY environment variables. For Flutter, use the supabase_flutter package (separate repository).
Q: What is the difference between the anon key and service role key?
The anon key is safe to use in client code — it respects Row Level Security policies. The service role key bypasses RLS entirely and should only be used server-side for admin operations.
Q: How do I run Supabase locally?
Use the Supabase CLI: npx supabase init then npx supabase start. This starts a local Postgres, GoTrue (auth), PostgREST, Realtime, Storage, Studio, and Inbucket (email testing) using Docker.
Q: Can I self-host Supabase?
Yes. The docker/ directory contains a production-ready Docker Compose setup with all services (Kong API gateway, GoTrue auth, PostgREST, Realtime, Storage, Studio, Postgres, and more). See the Admin Guide for deployment instructions.
Q: What Postgres version does Supabase use?
The default local development version is Postgres 15 (configured in supabase/config.toml under [db] major_version). A Postgres 17 override is available via docker/docker-compose.pg17.yml for self-hosted deployments.
Q: How do I expose additional schemas via the API?
Add them to the schemas array in supabase/config.toml under [api]. The default includes public, storage, and graphql_public. After changing, restart the local stack or update the remote project's PostgREST configuration.
Q: Why are my Realtime subscriptions not working?
Three common causes: (1) The table is not in the supabase_realtime publication — run alter publication supabase_realtime add table your_table;, (2) RLS policies block SELECT for the subscribing user's role, (3) the WebSocket connection is blocked by a proxy or firewall.
Q: How do I use Supabase with Vue/Nuxt?
The blocks/vue/ directory provides pre-built Nuxt UI blocks including password-based auth, social auth, realtime cursor tracking, avatar stacks, and file dropzones. These blocks include server middleware for Supabase SSR auth.
Q: How do I handle file uploads with size validation?
Set the file_size_limit in supabase/config.toml under [storage]. The default is 50MiB. Client-side, check the file size before uploading and handle the 413 error if the server rejects the file.
Q: What is Supabase Studio?
Studio is the web-based dashboard for managing Supabase projects. It includes a Table Editor, SQL Editor, Auth management, Storage browser, Edge Function logs, and database schema visualization. It runs as a Next.js application.