Try Live
Add Docs
Rankings
Pricing
Docs
Install
Install
Docs
Pricing
More...
More...
Try Live
Rankings
Enterprise
Create API Key
Add Docs
Supabase
https://github.com/supabase/supabase
Admin
Supabase is the Postgres development platform, offering features like hosted Postgres,
...
Tokens:
1,746,934
Snippets:
6,174
Trust Score:
10
Update:
1 week ago
Context
Skills
Chat
Benchmark
71.7
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# Supabase Supabase is an open-source Firebase alternative and Postgres development platform that provides a complete backend infrastructure for building modern applications. It combines enterprise-grade PostgreSQL database hosting with auto-generated APIs (REST and GraphQL), real-time subscriptions, authentication, file storage, edge functions, and vector/AI capabilities. Built on top of proven open-source tools like PostgREST, GoTrue, and Realtime, Supabase gives developers a Firebase-like experience while maintaining full Postgres compatibility and extensibility. The platform offers official client libraries for JavaScript/TypeScript, Flutter/Dart, Swift, and Python, along with community-maintained libraries for C#, Kotlin, Go, Ruby, and Rust. Developers can use Supabase as a hosted platform with instant project provisioning or self-host the entire stack using Docker. The architecture includes Kong as an API gateway, with each service (database, auth, storage, realtime, functions) operating independently yet seamlessly integrated through the Supabase client SDK. ## Initializing the Supabase Client Create a Supabase client instance to interact with your project's database, auth, storage, realtime, and functions services. ```javascript import { createClient } from '@supabase/supabase-js' // Initialize the Supabase client with your project URL and anon key const supabase = createClient( 'https://your-project.supabase.co', 'your-anon-key' ) // The client is now ready to use for all Supabase operations // Example: Check connection by fetching current user const { data: { user }, error } = await supabase.auth.getUser() console.log('Current user:', user) ``` ## Creating Tables Define database tables using SQL with proper data types, primary keys, and relationships. ```sql -- Create a movies table with auto-incrementing primary key create table movies ( id bigint generated by default as identity primary key, name text not null, description text, created_at timestamp with time zone default now() ); -- Create a categories table for relationships create table categories ( id bigint generated always as identity primary key, name text not null ); -- Add a foreign key relationship to movies alter table movies add column category_id bigint references categories; -- Create a many-to-many relationship with actors create table actors ( id bigint generated by default as identity primary key, name text not null ); create table performances ( id bigint generated by default as identity primary key, movie_id bigint not null references movies, actor_id bigint not null references actors ); ``` ## Inserting Data Insert records into tables using SQL or client libraries with support for single and bulk inserts. ```javascript // Insert single or multiple records using the JavaScript client const { data, error } = await supabase.from('movies').insert([ { name: 'The Empire Strikes Back', description: 'After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda.', }, { name: 'Return of the Jedi', description: 'After a daring mission to rescue Han Solo from Jabba the Hutt, the Rebels dispatch to Endor to destroy the second Death Star.', }, ]) if (error) { console.error('Insert error:', error.message) } else { console.log('Inserted movies:', data) } ``` ## Querying Data Fetch data from tables with filtering, ordering, and pagination using the auto-generated REST API. ```javascript // Basic select query - fetch all todos const { data: todos, error } = await supabase.from('todos').select() // Select with filters and ordering const { data: movies, error: moviesError } = await supabase .from('movies') .select('id, name, description') .eq('category_id', 1) // Filter: category_id equals 1 .order('name', { ascending: true }) .limit(10) // Select with joins - fetch movies with their categories const { data: moviesWithCategories } = await supabase .from('movies') .select(` id, name, categories ( id, name ) `) // Using curl to query the REST API directly // curl 'https://<PROJECT_REF>.supabase.co/rest/v1/todos' \ // -H "apikey: <ANON_KEY>" \ // -H "Authorization: Bearer <ANON_KEY>" ``` ## Row Level Security (RLS) Enable and configure Row Level Security policies to control data access at the database level. ```sql -- Enable RLS on a table alter table "todos" enable row level security; -- Allow anonymous read access to all rows create policy "Allow public read access" on todos for select to anon using (true); -- Allow authenticated users to insert their own rows create policy "Users can insert own todos" on todos for insert to authenticated with check (auth.uid() = user_id); -- Allow users to update only their own rows create policy "Users can update own todos" on todos for update to authenticated using (auth.uid() = user_id) with check (auth.uid() = user_id); -- Allow users to delete only their own rows create policy "Users can delete own todos" on todos for delete to authenticated using (auth.uid() = user_id); ``` ## User Authentication - Sign Up Register new users with email/password, phone, or social providers with optional email verification. ```javascript // Sign up with email and password async function signUpNewUser() { const { data, error } = await supabase.auth.signUp({ email: 'user@example.com', password: 'secure-password-123', options: { emailRedirectTo: 'https://yourapp.com/welcome', data: { first_name: 'John', age: 25, } }, }) if (error) { console.error('Signup error:', error.message) return } // User created - check if email confirmation is required if (data.user && !data.session) { console.log('Please check your email to confirm your account') } else { console.log('User signed up and logged in:', data.user) } } ``` ## User Authentication - Sign In Authenticate users with email/password or phone/password credentials. ```javascript // Sign in with email and password async function signInWithEmail() { const { data, error } = await supabase.auth.signInWithPassword({ email: 'user@example.com', password: 'secure-password-123', }) if (error) { console.error('Login error:', error.message) return } console.log('User signed in:', data.user) console.log('Session:', data.session) } // Sign in with phone and password async function signInWithPhone() { const { data, error } = await supabase.auth.signInWithPassword({ phone: '+13334445555', password: 'secure-password-123', }) } ``` ## Password Reset Initiate password reset flow and update user passwords securely. ```javascript // Request password reset email await supabase.auth.resetPasswordForEmail('user@example.com', { redirectTo: 'https://yourapp.com/account/update-password', }) // After user clicks link and is authenticated, update password await supabase.auth.updateUser({ password: 'new-secure-password-456' }) ``` ## Phone OTP Verification Verify phone numbers using SMS one-time passwords for signup confirmation. ```javascript // Sign up with phone number const { data, error } = await supabase.auth.signUp({ phone: '+13334445555', password: 'secure-password-123', }) // Verify the OTP sent via SMS const { data: { session }, error: verifyError } = await supabase.auth.verifyOtp({ phone: '+13334445555', token: '123456', // 6-digit code from SMS type: 'sms', }) if (!verifyError) { console.log('Phone verified, user logged in:', session) } ``` ## Storage - Create Bucket Create storage buckets to organize and manage file uploads with security policies. ```javascript // Create a new storage bucket const { data, error } = await supabase.storage.createBucket('avatars', { public: false, // Set to true for public access fileSizeLimit: 1024 * 1024 * 2, // 2MB limit allowedMimeTypes: ['image/png', 'image/jpeg', 'image/gif'] }) // Using SQL to create a bucket // insert into storage.buckets (id, name, public) // values ('avatars', 'avatars', false); ``` ## Storage - Upload Files Upload files to storage buckets with automatic content-type detection. ```javascript // Upload a file from a form input const avatarFile = event.target.files[0] const fileName = `${Date.now()}_${avatarFile.name}` const { data, error } = await supabase.storage .from('avatars') .upload(`public/${fileName}`, avatarFile, { cacheControl: '3600', upsert: false }) if (error) { console.error('Upload error:', error.message) } else { console.log('File uploaded:', data.path) } ``` ## Storage - Download Files Download files from storage buckets programmatically. ```javascript // Download a file as blob const { data, error } = await supabase.storage .from('avatars') .download('public/avatar1.png') if (!error) { // Create URL for the blob const url = URL.createObjectURL(data) console.log('Download URL:', url) } // Get public URL for publicly accessible files const { data: { publicUrl } } = supabase.storage .from('avatars') .getPublicUrl('public/avatar1.png') ``` ## Storage Security Policies Configure storage policies to control file access using Row Level Security. ```sql -- Allow public read access to a bucket create policy "Public Access" on storage.objects for select using (bucket_id = 'public'); -- Allow authenticated users to upload to their own folder create policy "User Uploads" on storage.objects for insert to authenticated with check ( bucket_id = 'avatars' AND (storage.foldername(name))[1] = auth.uid()::text ); -- Allow users to delete their own files create policy "User Deletes" on storage.objects for delete to authenticated using ( bucket_id = 'avatars' AND (storage.foldername(name))[1] = auth.uid()::text ); ``` ## Realtime - Subscribe to Database Changes Listen to INSERT, UPDATE, and DELETE events on database tables in real-time. ```javascript // Subscribe to all changes on a table const channel = supabase .channel('schema-db-changes') .on( 'postgres_changes', { event: '*', // Listen to all events: INSERT, UPDATE, DELETE schema: 'public', table: 'todos', }, (payload) => { console.log('Change received:', payload) console.log('Event type:', payload.eventType) console.log('New data:', payload.new) console.log('Old data:', payload.old) } ) .subscribe() // Subscribe to INSERT events only const insertChannel = supabase .channel('inserts-only') .on( 'postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages', }, (payload) => console.log('New message:', payload.new) ) .subscribe() // Unsubscribe when done await supabase.removeChannel(channel) ``` ## Realtime - Filtered Subscriptions Subscribe to specific database changes using filters for granular updates. ```javascript // Listen to changes where a specific column matches a value const filteredChannel = supabase .channel('filtered-changes') .on( 'postgres_changes', { event: 'UPDATE', schema: 'public', table: 'messages', filter: 'room_id=eq.123', // Only messages in room 123 }, (payload) => console.log('Room 123 update:', payload) ) .subscribe() // Multiple filters with IN clause const multiFilterChannel = supabase .channel('multi-filter') .on( 'postgres_changes', { event: 'INSERT', schema: 'public', table: 'orders', filter: 'status=in.(pending, processing)', }, (payload) => console.log('New order:', payload.new) ) .subscribe() ``` ## Realtime - Multiple Listeners Subscribe to multiple tables or events on a single channel. ```javascript const channel = supabase .channel('multi-table-changes') .on( 'postgres_changes', { event: '*', schema: 'public', table: 'messages', }, (payload) => console.log('Message change:', payload) ) .on( 'postgres_changes', { event: 'INSERT', schema: 'public', table: 'users', }, (payload) => console.log('New user:', payload.new) ) .subscribe((status) => { if (status === 'SUBSCRIBED') { console.log('Connected to realtime!') } }) ``` ## Database Functions Create reusable SQL functions that can be called via the API. ```sql -- Simple function returning text create or replace function hello_world() returns text language sql as $$ select 'hello world'; $$; -- Function with parameters returning table data create or replace function get_movies_by_year(year_filter int) returns setof movies language plpgsql as $$ begin return query select * from movies where extract(year from created_at) = year_filter; end; $$; -- Function to insert data and return the new ID create or replace function add_movie(movie_name text, movie_description text) returns bigint language plpgsql as $$ declare new_id bigint; begin insert into movies (name, description) values (movie_name, movie_description) returning id into new_id; return new_id; end; $$; ``` ## Calling Database Functions (RPC) Invoke database functions from client libraries with parameters and filtering. ```javascript // Call a simple function const { data, error } = await supabase.rpc('hello_world') console.log(data) // 'hello world' // Call function with parameters const { data: movies } = await supabase.rpc('get_movies_by_year', { year_filter: 2024 }) // Call function and apply filters to results const { data: filteredMovies } = await supabase .rpc('get_movies_by_year', { year_filter: 2024 }) .eq('category_id', 1) .limit(5) // Insert using a function const { data: newId } = await supabase.rpc('add_movie', { movie_name: 'New Movie', movie_description: 'A great new film' }) console.log('New movie ID:', newId) ``` ## Edge Functions - Creating Functions Create serverless functions that run on Deno at the edge for custom backend logic. ```typescript // supabase/functions/hello-world/index.ts Deno.serve(async (req) => { // Parse JSON body const { name } = await req.json() // Create response data const data = { message: `Hello ${name}!`, timestamp: new Date().toISOString(), } // Return JSON response return new Response( JSON.stringify(data), { headers: { 'Content-Type': 'application/json' }, status: 200 } ) }) // Deploy with CLI: supabase functions deploy hello-world ``` ## Edge Functions - Invoking Functions Call edge functions from client applications with authentication. ```javascript // Using the Supabase client const { data, error } = await supabase.functions.invoke('hello-world', { body: { name: 'World' }, }) console.log(data) // { message: "Hello World!", timestamp: "..." } // Using fetch API directly const response = await fetch( 'https://your-project.supabase.co/functions/v1/hello-world', { method: 'POST', headers: { 'Authorization': `Bearer ${supabaseAnonKey}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ name: 'Fetch' }), } ) const result = await response.json() ``` ## Edge Functions - Testing Locally Run and test edge functions locally before deployment. ```bash # Initialize Supabase project supabase init # Create a new function supabase functions new hello-world # Start local Supabase services supabase start # Serve the function locally with hot reloading supabase functions serve hello-world # Test with curl curl -i --location --request POST \ 'http://localhost:54321/functions/v1/hello-world' \ --header 'Authorization: Bearer <ANON_KEY>' \ --header 'Content-Type: application/json' \ --data '{"name":"Functions"}' # Expected response: {"message":"Hello Functions!"} ``` ## Views Create database views to simplify complex queries and provide consistent data access. ```sql -- Create a view joining multiple tables create view transcripts as select students.name as student_name, students.type as student_type, courses.title as course_title, courses.code as course_code, grades.result from grades left join students on grades.student_id = students.id left join courses on grades.course_id = courses.id; -- Grant access to the view grant select on transcripts to authenticated; -- Query the view like a table select * from transcripts where result = 'A'; -- Create a security invoker view for RLS enforcement create view public_profiles with (security_invoker = true) as select id, username, avatar_url from profiles; ``` ## Materialized Views Create cached views for improved performance on complex queries. ```sql -- Create a materialized view for frequently accessed aggregations create materialized view monthly_sales as select date_trunc('month', created_at) as month, sum(amount) as total_sales, count(*) as order_count from orders group by date_trunc('month', created_at); -- Query the materialized view select * from monthly_sales order by month desc limit 12; -- Refresh the materialized view when data changes refresh materialized view monthly_sales; -- Create an index on the materialized view for faster queries create index idx_monthly_sales_month on monthly_sales (month); ``` ## Enabling Realtime for Tables Configure Postgres replication to enable real-time subscriptions on specific tables. ```sql -- Add a table to the realtime publication alter publication supabase_realtime add table todos; -- Enable replica identity to receive old records on UPDATE/DELETE alter table messages replica identity full; -- Add multiple tables at once alter publication supabase_realtime add table messages, users, orders; -- Check which tables are in the publication select * from pg_publication_tables where pubname = 'supabase_realtime'; ``` ## Python Client Usage Use the Supabase Python client for server-side applications and scripts. ```python from supabase import create_client # Initialize client supabase = create_client( 'https://your-project.supabase.co', 'your-anon-key' ) # Query data response = supabase.table('todos').select("*").execute() print(response.data) # Insert data response = supabase.table('todos').insert({ "task": "Learn Supabase", "completed": False }).execute() # Authentication data = supabase.auth.sign_in_with_password({ 'email': 'user@example.com', 'password': 'password123', }) # Call RPC function data = supabase.rpc('hello_world').execute() # Subscribe to realtime (async) changes = supabase.channel('db-changes').on_postgres_changes( "*", schema="public", table="todos", callback=lambda payload: print(payload) ).subscribe() ``` ## REST API Direct Access Query the auto-generated REST API directly using curl or any HTTP client. ```bash # Fetch all records from a table curl 'https://<PROJECT_REF>.supabase.co/rest/v1/todos' \ -H "apikey: <ANON_KEY>" \ -H "Authorization: Bearer <ANON_KEY>" # Insert a new record curl 'https://<PROJECT_REF>.supabase.co/rest/v1/todos' \ -H "apikey: <ANON_KEY>" \ -H "Authorization: Bearer <ANON_KEY>" \ -H "Content-Type: application/json" \ -H "Prefer: return=representation" \ -d '{"task": "New todo item"}' # Update a record curl -X PATCH 'https://<PROJECT_REF>.supabase.co/rest/v1/todos?id=eq.1' \ -H "apikey: <ANON_KEY>" \ -H "Authorization: Bearer <ANON_KEY>" \ -H "Content-Type: application/json" \ -d '{"completed": true}' # Delete a record curl -X DELETE 'https://<PROJECT_REF>.supabase.co/rest/v1/todos?id=eq.1' \ -H "apikey: <ANON_KEY>" \ -H "Authorization: Bearer <ANON_KEY>" # Query with filters curl 'https://<PROJECT_REF>.supabase.co/rest/v1/todos?completed=eq.false&order=created_at.desc' \ -H "apikey: <ANON_KEY>" \ -H "Authorization: Bearer <ANON_KEY>" ``` --- Supabase provides a comprehensive platform for building full-stack applications with minimal backend configuration. The primary use cases include rapid prototyping with instant APIs, building real-time collaborative applications, implementing secure user authentication, managing file uploads and media, and running serverless edge functions. The platform excels at reducing backend development time while maintaining the flexibility and power of PostgreSQL. Integration patterns typically involve initializing the Supabase client at application startup, using Row Level Security for data authorization, subscribing to real-time channels for live updates, and leveraging edge functions for custom business logic. The combination of auto-generated REST/GraphQL APIs with the ability to write custom SQL functions and server-side code provides both convenience and flexibility for applications ranging from simple CRUD apps to complex real-time systems with sophisticated access control requirements.
Supabase (supabase/supabase) | Context7