Set Up Your Database in 5 Minutes

🎯 Why Supabase? It's like Firebase but open source, with a real PostgreSQL database. Free tier is generous, and it's perfect for member dashboards, auth, and file storage.

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

  1. Go to supabase.com
  2. Click "Start your project"
  3. Sign up with GitHub or email
  4. Verify your email

Step 2: Create a New Project

  1. Click "New Project"
  2. Name: Your project name (e.g., "AI Orchestrator")
  3. Database Password: Generate a strong password (save it!)
  4. Region: Choose closest to you (e.g., us-east-2 for Idaho)
  5. Plan: Free tier (perfect for starting)
  6. Click "Create new project"
⏱️ Wait time: 2-5 minutes while Supabase provisions your database

Step 3: Get Your API Keys

  1. In your project dashboard, click Settings (left sidebar)
  2. Click API
  3. 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

  1. In Supabase dashboard, click Table Editor
  2. Click "New table"
  3. Name: profiles
  4. Enable RLS: ✅ Checked (important!)
  5. 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