What You'll Build
- User authentication - Signup, login, password reset
- Member profiles - Store user data, preferences, settings
- Row-level security - Users only see their own data
- File storage - Upload logos, avatars, documents
- Real-time updates - Live chat, notifications
Step 1: Create Your Account
- Go to supabase.com
- Click "Start your project"
- Sign up with GitHub or email
- Verify your email
Step 2: Create a New Project
- Click "New Project"
- Name: Your project name (e.g., "AI Orchestrator")
- Database Password: Generate a strong password (save it!)
- Region: Choose closest to you (e.g., us-east-2 for Idaho)
- Plan: Free tier (perfect for starting)
- Click "Create new project"
⏱️ Wait time: 2-5 minutes while Supabase provisions your database
Step 3: Get Your API Keys
- In your project dashboard, click Settings (left sidebar)
- Click API
- Copy these two values:
- Project URL:
https://xxxxx.supabase.co
- anon public key:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
⚠️ Security Note: The anon key is safe to use in frontend code. It's restricted by Row-Level Security (RLS). Never expose your service_role key!
Step 4: Add Supabase to Your HTML
<!-- In your <head> section -->
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
<script>
const supabaseUrl = 'https://YOUR_PROJECT_ID.supabase.co';
const supabaseKey = 'YOUR_ANON_KEY';
const supabase = window.supabase.createClient(supabaseUrl, supabaseKey);
</script>
Step 5: Create Your First Table
- In Supabase dashboard, click Table Editor
- Click "New table"
- Name:
profiles
- Enable RLS: ✅ Checked (important!)
- Click "Create"
Step 6: Add Columns to Profiles Table
Add these columns:
| Column |
Type |
Default |
Notes |
id |
uuid |
Primary Key |
Links to auth.users |
email |
text |
- |
User's email |
full_name |
text |
null |
Optional |
tier |
text |
'become_curious' |
Membership tier |
created_at |
timestamp |
now() |
Auto-set |
Step 7: Set Up Row-Level Security (RLS)
RLS ensures users can only access their own data. Go to Authentication → Policies and add:
-- Allow users to read their own profile
CREATE POLICY "Users can view own profile"
ON profiles FOR SELECT
USING (auth.uid() = id);
-- Allow users to update their own profile
CREATE POLICY "Users can update own profile"
ON profiles FOR UPDATE
USING (auth.uid() = id);
-- Allow users to insert their own profile (on signup)
CREATE POLICY "Users can insert own profile"
ON profiles FOR INSERT
WITH CHECK (auth.uid() = id);
Step 8: Create a Signup Function
-- In SQL Editor, run this:
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS trigger AS $$
BEGIN
INSERT INTO public.profiles (id, email, full_name, tier)
VALUES (
NEW.id,
NEW.email,
NEW.raw_user_meta_data->>'full_name',
NEW.raw_user_meta_data->>'tier'
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Trigger on new user signup
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();
Step 9: Test Signup in Your App
const { data, error } = await supabase.auth.signUp({
email: 'user@example.com',
password: 'SecurePassword123!',
options: {
data: {
full_name: 'John Doe',
tier: 'become_curious'
}
}
});
if (error) console.error('Signup failed:', error);
else console.log('Signup successful!', data);
Step 10: Test Login
const { data, error } = await supabase.auth.signInWithPassword({
email: 'user@example.com',
password: 'SecurePassword123!'
});
if (error) console.error('Login failed:', error);
else console.log('Login successful!', data.user);
Common Use Cases
Fetch User Profile
const { data: profile } = await supabase
.from('profiles')
.select('*')
.eq('id', user.id)
.single();
Update Profile
const { error } = await supabase
.from('profiles')
.update({ full_name: 'Jane Doe' })
.eq('id', user.id);
Upload File (Logo)
const { data, error } = await supabase.storage
.from('logos')
.upload(`${user.id}/logo.png`, file);
Troubleshooting
"Invalid API key"
Double-check you're using the anon key, not service_role
"Permission denied"
Check RLS policies - make sure user is authenticated and policies match
"Table doesn't exist"
Make sure you created the table in the correct project
Resources