Supabase
Your tool works, but the data sits in a file on your own machine. A real database moves it to a server that decides who may see which row.
The moment a tool holds someone else’s data, the question changes. It stops being can I build this, and becomes can they trust it.
This is one project of the building course, lifted out on its own. The whole build is The AI Building Course →
Rows
Data on a server, not in a file
Every Supabase project gets a full Postgres database, not a cut-down version of one.
Your tool stops holding the data and starts asking for it.
- Where does your data live today: a file, a sheet, the browser?
- Does more than one person need to see it?
- What happens the day that laptop dies?
A table is a spreadsheet with rules. Rows, columns, and one column saying whose row it is.
Sign-in
The database learns who is asking
Supabase Auth checks that a person is who they say they are.
Your code calls one function, and gets a signed-in user back.
- Who should be able to open this at all?
- A password, or a link emailed to them?
- What should a signed-out visitor see?
Supabase names password, magic link, one-time code, social login and single sign-on. A magic link works once and expires after an hour.
Row Level Security
The guard lives inside the database
A policy is a rule the database runs every time the table is touched.
Supabase describes it as adding a WHERE clause to every query you make.
- Which rows belong to exactly one person?
- Which rows are genuinely meant to be public?
- Who may write to them, not only read?
Switch it on and nothing comes back through a publishable key until you write a policy. That empty screen means it is working.
The keys
One is safe in a browser, one never is
The publishable key is meant to be seen: anyone can read it, so it only reaches what your policies allow.
The secret key skips every policy, so it stays on a server you control.
- Where does this code run: on a device, or on your server?
- Has a secret key ever gone into front-end code?
- Are your policies written down, or only intended?
A long key starting eyJ is an old one. Supabase is retiring the anon and service role keys in favour of short publishable and secret keys.
Prove it with two accounts
You cannot trust a rule you have never tried to break. This takes five minutes and one inbox.
- 1
Sign up as the first account. Use yourname+a@gmail.com, and write two or three rows.
- 2
Log out, sign up as the second. Use yourname+b@gmail.com. Its list should be empty.
- 3
Write a row as the second account. Then log out again.
- 4
Log back in as the first. Your rows, all of them, and none of theirs.
Now search the code. There is no filter by user anywhere in it. The database refused on its own, and that is the whole point.
Three things that go wrong first
All three look alarming and all three are ordinary. Read the symptom, not the panic.
Everything is empty
on, but no rule yet- The guard is on and has nothing to let you through.
- Add the policy, then reload.
You see another account
never switched on- The table was left unlocked.
- Run the setup again and check the policy landed.
A long key starting eyJ
written for the old keys- That instruction predates the current ones.
- Take the short publishable key from your dashboard.
Two accounts, one inbox: yourname+a@gmail.com and yourname+b@gmail.com both land in yourname@gmail.com.
- Rows: your data on a server, not a file beside your code.
- Sign-in: Supabase checks who is asking before a row moves.
- Row Level Security: a rule inside the database, on every read.
- The keys: the publishable one ships, the secret one never does.
This week: if any tool of yours holds someone else’s data, run the two-account test on it today.
Which keys may be seen and which must not: API keys → Put the finished thing on the internet: Netlify →
Do it with someone. Everything here is free and you can run it alone. If you would rather work through it with me, one to one, book a free 30-minute chat. No pitch.