Database & Supabase

Set up and manage your Supabase database, authentication, and real-time features.

Database Schema

Set up your database tables with proper relationships and RLS policies:

-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- Create profiles table
CREATE TABLE profiles (
id UUID REFERENCES auth.users ON DELETE CASCADE NOT NULL PRIMARY KEY,
email TEXT,
full_name TEXT,
avatar_url TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- Create subscriptions table
CREATE TABLE subscriptions (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id UUID REFERENCES auth.users NOT NULL,
status TEXT,
price_id TEXT,
quantity INTEGER,
cancel_at_period_end BOOLEAN,
created TIMESTAMPTZ DEFAULT NOW(),
current_period_start TIMESTAMPTZ DEFAULT NOW(),
current_period_end TIMESTAMPTZ DEFAULT NOW(),
ended_at TIMESTAMPTZ,
cancel_at TIMESTAMPTZ,
canceled_at TIMESTAMPTZ,
trial_start TIMESTAMPTZ,
trial_end TIMESTAMPTZ
);
-- Enable Row Level Security
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE subscriptions ENABLE ROW LEVEL SECURITY;
-- Create RLS Policies
CREATE POLICY "Users can view own profile"
ON profiles FOR SELECT
USING (auth.uid() = id);
CREATE POLICY "Users can update own profile"
ON profiles FOR UPDATE
USING (auth.uid() = id);
CREATE POLICY "Users can view own subscriptions"
ON subscriptions FOR SELECT
USING (auth.uid() = user_id);

Database Client

Initialize and use the Supabase client in your application:

// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr'
export const createClient = () => {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
// Example usage in a component
import { createClient } from '@/lib/supabase/client'
export async function ProfileComponent() {
const supabase = createClient()
const { data: profile, error } = await supabase
.from('profiles')
.select('*')
.single()
if (error) {
console.error('Error fetching profile:', error)
return null
}
return <div>{profile.full_name}</div>
}

Real-time Subscriptions

Subscribe to real-time database changes:

import { useEffect } from 'react'
import { createClient } from '@/lib/supabase/client'
export function RealtimeComponent() {
const supabase = createClient()
useEffect(() => {
const channel = supabase
.channel('table-changes')
.on(
'postgres_changes',
{
event: '*',
schema: 'public',
table: 'profiles'
},
(payload) => {
console.log('Change received!', payload)
}
)
.subscribe()
return () => {
supabase.removeChannel(channel)
}
}, [])
return <div>Listening for changes...</div>
}

Storage

Handle file uploads and downloads with Supabase Storage:

import { createClient } from '@/lib/supabase/client'
export async function uploadAvatar(file: File) {
const supabase = createClient()
const fileExt = file.name.split('.').pop()
const fileName = `${Math.random()}${fileExt}`
const { data, error } = await supabase.storage
.from('avatars')
.upload(fileName, file)
if (error) {
throw error
}
const { data: { publicUrl } } = supabase.storage
.from('avatars')
.getPublicUrl(data.path)
return publicUrl
}

Next Steps