The database isthe application.
- PRODUCT
- Stencil
- ROLE
- Everything
- TENANCY
- Row level security
- STACK
- Next.js · Supabase
- DATA
- Postgres

A tattoo studio is several businesses sharing a calendar.
Artists take their own enquiries, quote their own work, keep their own clients and their own income, and share a studio, a diary and a front desk. Software that treats the studio as one account gets the calendar right and the money wrong. Software that treats each artist as an island cannot show the studio a week.
So the question is not what the screens look like. It is who is allowed to see which row, and whether that answer is enforced somewhere a missing filter cannot undo.
No API tier, on purpose.
A Next.js app talking to Postgres through Supabase, with no service of my own in between. That only works because the authorisation lives in the database: without row level security this shape would be one forgotten filter away from a leak, and I would have had to build the tier back. This is the opposite call to ClassPortal, where the domain was wide enough that a NestJS API earned its keep.
next.js
typed client
35 policies
source of truth
Thirteen tables, and the database says no.
Every table carries its own policies, its own checks and its own foreign keys with the deletion behaviour spelled out. A booking outlives the enquiry it came from; a client outlives the payment that referenced them.