Day 11 of 23 · Wednesday · Learning

Supabase — the database under Focaccia VoteConcept

Supabase is a hosted Postgres database with an admin dashboard and an instant API bolted on. Today you learn what that actually means — what Postgres is, what a table and a row are — by reading the real votes table Focaccia Vote has been writing to.

Catch-up progress
11/23
Why this matters to you

Last week you shipped Focaccia Vote and people actually voted — every tap landed as a row in a Postgres table you've never looked at directly. Right now that data is a black box you can only see through the app's own UI. After today you can open the database itself, count the rows, and answer questions the app doesn't have a screen for.

Postgres is a database engine — a program whose whole job is to store structured data and answer questions about it fast. Think of it as a folder of ruthlessly organized spreadsheets: each <strong>table</strong> is one sheet (votes, users, candidates), each <strong>column</strong> is a typed field (a timestamp, a piece of text, a number — and the type is enforced, you cannot put 'banana' in a date column), and each <strong>row</strong> is one record — one vote, one user, one event. That's 90% of the mental model.

Supabase is not a different database — it's Postgres that someone else runs for you, wrapped in three conveniences: a web dashboard so you can browse tables without writing code, an auto-generated API so your app can read/write rows over HTTPS with one JS call, and a bundled auth system. When Focaccia Vote 'saves a vote', it's really making an HTTPS call to Supabase's API, which inserts one row into the <code>votes</code> table. No server of your own anywhere — that's why it's the DB + Auth default in your stack doc.

The failure mode to respect: the API is reachable by anyone on the internet, and what stops a stranger from reading or spam-writing your table is <strong>Row Level Security (RLS)</strong> — per-table rules about who may do what. A table with RLS off and a public anon key is an open guestbook. You don't need to master RLS today; you need to know it exists and check whether your votes table has it on.

Worked example

Three queries to run in the Supabase SQL Editor (dashboard → SQL Editor → New query) — each answers something the app's UI can't:

-- 1. How many votes total?
select count(*) from votes;

-- 2. The five most recent votes, newest first
select * from votes
order by created_at desc
limit 5;

-- 3. What columns does the table actually have?
select column_name, data_type
from information_schema.columns
where table_name = 'votes';
▶ Do it now
  1. Open https://supabase.com/dashboard and sign in — pick the Focaccia Vote project.
  2. Go to Table Editor (left sidebar, grid icon) and click the votes table. Just look: each row is one real vote someone cast. Note the column names and which one holds the timestamp.
  3. Open SQL Editor → New query, paste query 1 from the worked example, hit Run. Does the count match what the app shows? If it does, you've just independently verified your own production data.
  4. Run query 2 and find the most recent vote. When was it? That single fact — 'when did this last get written to?' — is the health check for any system that's supposed to be live.
  5. Bonus: go to Authentication → Policies (or the shield icon on the votes table) and check whether RLS is enabled. Don't change anything — just note ON or OFF, and we'll handle what it means in a later lesson.

Gotchas

Go deeper: Supabase docs — Database overview · Supabase docs — Row Level Security · SQLBolt — interactive SQL basics (lessons 1–4 cover today's queries)
One-card takeaway

A database is just typed spreadsheets with rules — and you can always bypass the app and ask it directly: select count(*) is how you check the pulse of anything you've shipped.