Supabase Setup — Project, tables, Row Level Security
Now you'll create a real database. By the end of this lesson you'll have a Supabase project, your first table, and — most importantly — security rules that keep each user's data private. You won't write any SQL by hand; the dashboard and Claude handle that.
Create Your Supabase Account
- Go to supabase.com
- Click Start your project → Sign up
- Sign up with GitHub (recommended — keeps your tools connected) or email
- Verify your email if prompted
Create a New Project
- Once logged in, click New project
- Fill in the details:
- Organization: Supabase creates one automatically; your name is fine
- Project name: Match your app (e.g.,
focus-dashboard) - Database Password: Click Generate for a strong one. Save it somewhere safe — you'll need it later and Supabase won't show it again
- Region: Pick the one closest to you (e.g., Southeast Asia – Singapore, US East, EU West) so your app feels fast
- Click Create new project
Supabase takes 1–2 minutes to provision the database. Let it finish before moving on.
A Tour of the Dashboard
Once the project is ready, you'll land on the dashboard. The sections you'll actually use:
| Section | What it's for |
|---|---|
| Table Editor | A spreadsheet-like view of your tables. Create tables, add rows, and browse data — no SQL needed. |
| SQL Editor | Write and run SQL directly. Useful for advanced operations; Claude often hands you SQL to paste here. |
| Authentication | Manage users, configure login methods, see who's signed up. |
| Storage | Store files (images, documents). Not needed yet, handy later. |
| API | Auto-generated docs showing how to query your data. |
Getting Your API Keys
Your app needs two values to connect to Supabase:
- In the dashboard, open Settings (the gear icon)
- Click API
- You'll see:
- Project URL — looks like
https://abcdefgh.supabase.co - Project API keys →
anonpublic — a long string of characters
- Project URL — looks like
Keep this tab open; you'll copy both values into your app in the next lesson.
Security — the most important rule in this module. The
anon(publishable) key is safe to expose in frontend code; it's designed for the browser. Theservice_rolekey is a master key that bypasses every security rule — it must never appear in browser code, in aNEXT_PUBLIC_*variable, or anywhere a visitor could read it. Treat it like a root password and keep it server-only. We won't use it at all in these lessons.
Creating Your First Table
Let's build the main table for your app using the Table Editor — no SQL required.
- Click Table Editor → New table
- Fill in:
- Name:
tasks(or whatever your main table is) - Enable Row Level Security (RLS): ✅ Yes — always. We'll configure the rules in a moment.
- Enable Realtime: optional for now
- Name:
- Supabase automatically adds
idandcreated_at. Add your own columns with Add column:
| Column name | Type | Default | Notes |
|---|---|---|---|
title | text | — | Not null |
done | bool | false | Not null |
user_id | uuid | — | References auth.users.id |
- Click Save
Linking Tasks to Users (Foreign Key)
The user_id column connects each task to the person who owns it. When adding that column:
- Set the type to
uuid - Find the Foreign key relationship option
- Choose: schema
auth, tableusers, columnid
This means every task must point to a real user in Supabase's authentication system — which is exactly how, later, your app shows each person only their own tasks.
Row Level Security (RLS): The Heart of Safe Data
RLS is the rule that stops one user from reading or deleting another user's data. It runs inside the database itself, so even if your app code has a bug, the database refuses to hand over rows a user shouldn't see.
- Without RLS: any logged-in user could read, edit, or delete everyone's tasks.
- With RLS: you define rules like "a user can only
SELECTrows whereuser_idequals their own id."
This is why you enabled RLS when creating the table. Now you add the policies — the specific permissions.
Setting Up the Four Policies
In the Table Editor, open your tasks table → Policies (or RLS). Add one policy per operation:
| Policy name | Operation | Expression |
|---|---|---|
| Users can read own tasks | SELECT | USING: auth.uid() = user_id |
| Users can insert own tasks | INSERT | WITH CHECK: auth.uid() = user_id |
| Users can update own tasks | UPDATE | USING: auth.uid() = user_id |
| Users can delete own tasks | DELETE | USING: auth.uid() = user_id |
auth.uid() is Supabase's shorthand for "the currently logged-in user's id." So every rule reads: only touch rows that belong to me.
You don't have to click through these by hand. Hand the job to Claude:
Set up Row Level Security policies for the
taskstable in Supabase. Users should only be able to read, insert, update, and delete their own tasks — rows whereuser_id = auth.uid(). Give me the SQL to paste into the Supabase SQL Editor.
Paste the SQL it produces into SQL Editor and run it.
Remember: enabling RLS on a table with no policies means no one can access anything (deny by default). That's a safe starting point — you open access deliberately by adding the four policies above, not accidentally.
Turning On Login Methods
By default Supabase enables email/password authentication, which is enough for most apps.
To check or adjust:
- Go to Authentication → Providers
- Email is on by default — leave it
- Optional: enable Google or GitHub for one-click sign-in
Google sign-in is nicer for users but needs a Google Cloud project and OAuth credentials. Supabase links to a setup guide right in the provider settings — we'll come back to it in the authentication lesson.
Summary
- Create a Supabase account and project at supabase.com; save the database password.
- Grab your Project URL and anon key from Settings → API for the next lesson.
- Build tables in the Table Editor — no SQL needed for the basics.
- Always enable Row Level Security on every table.
- Add RLS policies (read/insert/update/delete) so users only touch their own rows; Claude can generate the SQL.
- The
anonkey is browser-safe; theservice_rolekey is server-only and must never reach the browser.