Database Guide
Learn about your database structure and how to work with it
Initial Setup
Your database comes pre-configured with the following core tables and security policies from the seed.sql file:
1. Core Tables
The main tables that power your application:
-- Users table for profile informationCREATE TABLE public.users (id UUID PRIMARY KEY,email TEXT UNIQUE NOT NULL,full_name TEXT,avatar_url TEXT,created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP NOT NULL,updated_at TIMESTAMP WITH TIME ZONE,provider TEXT DEFAULT 'email' NOT NULL,role TEXT DEFAULT 'user' NOT NULL,billing_address JSONB,payment_method JSONB,terms_accepted BOOLEAN DEFAULT FALSE,terms_accepted_at TIMESTAMP WITH TIME ZONE,terms_version TEXT);-- Customers table for subscription managementCREATE TABLE public.customers (id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),user_id UUID REFERENCES public.users(id) ON DELETE CASCADE NOT NULL,stripe_customer_id TEXT UNIQUE,subscription_status TEXT,subscription_tier TEXT DEFAULT 'free',subscription_updated_at TIMESTAMP WITH TIME ZONE,trial_end TIMESTAMP WITH TIME ZONE,is_lifetime BOOLEAN DEFAULT FALSE,current_period_end TIMESTAMP WITH TIME ZONE);-- Products table for subscription tiersCREATE TABLE public.products (id TEXT PRIMARY KEY,active BOOLEAN DEFAULT TRUE NOT NULL,name TEXT NOT NULL,description TEXT,image TEXT,metadata JSONB);-- Prices table for product pricingCREATE TABLE public.prices (id TEXT PRIMARY KEY,product_id TEXT REFERENCES public.products(id) NOT NULL,active BOOLEAN DEFAULT TRUE NOT NULL,description TEXT,unit_amount BIGINT NOT NULL,currency TEXT NOT NULL,type TEXT NOT NULL,interval TEXT,interval_count INTEGER,trial_period_days INTEGER,metadata JSONB);
2. Security Policies
Row Level Security (RLS) policies to protect your data:
-- Enable RLS on all tablesALTER TABLE public.users ENABLE ROW LEVEL SECURITY;ALTER TABLE public.customers ENABLE ROW LEVEL SECURITY;ALTER TABLE public.products ENABLE ROW LEVEL SECURITY;ALTER TABLE public.prices ENABLE ROW LEVEL SECURITY;-- Users table policiesCREATE POLICY "Users can read own data" ON public.usersFOR SELECT USING (auth.uid() = id);CREATE POLICY "Users can update own data" ON public.usersFOR UPDATE USING (auth.uid() = id);-- Customers table policiesCREATE POLICY "Authenticated users can read customer data" ON public.customersFOR SELECT USING (auth.role() = 'authenticated');CREATE POLICY "Users can read own customer data" ON public.customersFOR SELECT USING (auth.uid() = user_id);CREATE POLICY "Users can insert own customer data" ON public.customersFOR INSERT WITH CHECK (auth.uid() = user_id);CREATE POLICY "Users can update own customer data" ON public.customersFOR UPDATE USING (auth.uid() = user_id);-- Products and Prices policiesCREATE POLICY "Anyone can read active products" ON public.productsFOR SELECT USING (active = true);CREATE POLICY "Anyone can read active prices" ON public.pricesFOR SELECT USING (active = true);
3. Default Products
Pre-configured subscription tiers and their prices:
-- Available productsINSERT INTO public.products (id, active, name, description, metadata) VALUES('prod_free', true, 'Free Plan', 'Basic features for individuals','{"features": ["Basic dashboard", "Limited API calls", "Email support"]}'),('prod_basic', true, 'Basic Plan', 'Essential features for small teams','{"features": ["Everything in Free", "Advanced analytics", "Team collaboration"]}'),('prod_pro', true, 'Pro Plan', 'Advanced features for growing businesses','{"features": ["Everything in Basic", "Premium support", "Custom integrations", "Advanced security"]}');-- Product pricingINSERT INTO public.prices (id, product_id, active, description, unit_amount, currency, type, interval) VALUES('price_free_monthly', 'prod_free', true, 'Free Plan', 0, 'usd', 'recurring', 'month'),('price_basic_monthly', 'prod_basic', true, 'Basic Plan Monthly', 1000, 'usd', 'recurring', 'month'),('price_pro_monthly', 'prod_pro', true, 'Pro Plan Monthly', 2500, 'usd', 'recurring', 'month');
Common Operations
Query User Profile
const { data: user } = await supabase.from('users').select('*, customers(*)').eq('id', userId).single()
Update User Profile
const { data, error } = await supabase.from('users').update({full_name: 'New Name',billing_address: { country: 'US' }}).eq('id', userId)