Database
One SQLite base per project
Authentication
Email and password, magic links and invitations — with who-sees-what decided by the table rather than by your front end.
| Preset | List / read | Create | Update | Delete |
|---|---|---|---|---|
| privatepriveEach user only sees their own rows. | owner | users | owner | owner |
| sharedpartageEveryone reads everything; each user edits only their own rows. | users | users | owner | owner |
| collaborativecollaboratifEveryone reads and edits everything. | users | users | users | users |
| spacesespacesRows belong to a space; only its members can access them. | space | space | space | space |
| moderated spacesespace_modereMembers read and create; only the author or the space admin can edit. | space | space | owner / admin | owner / admin |
| public readlecture_publiqueReadable without an account. | anon | users | owner | owner |
| journaljournalAppend-only — no end user can edit or delete, ever. | owner | users | nobody | nobody |
| formformulaireAnyone can submit; submissions are readable only with your own key. | nobody | anon | nobody | nobody |
private
prive
Each user only sees their own rows.
shared
partage
Everyone reads everything; each user edits only their own rows.
collaborative
collaboratif
Everyone reads and edits everything.
spaces
espaces
Rows belong to a space; only its members can access them.
moderated spaces
espace_modere
Members read and create; only the author or the space admin can edit.
public read
lecture_publique
Readable without an account.
journal
journal
Append-only — no end user can edit or delete, ever.
form
formulaire
Anyone can submit; submissions are readable only with your own key.
Refusal is the default: anything not explicitly allowed is refused, and a table with no declared preset is private. owner_id is set by the API, never read from the client. Files follow the same matrix. Your own keys ignore it.
A rule your front end enforces — one check-in per day — is a display convention. Server-side rules belong in an edge function; the only preset with a server-side limit of its own is the form preset, which caps submissions at ten a minute per address.
The session comes back in the body, never in a cookie: this API has no ambient identity. A person is an id, an email and a date — no password hash, no provider token. And a seat is taken at the first sign-in, never at sign-up.
10 routes served · sessions 30 rolling days · invites single-use, 7 days · 3 or 1,000 seats
No social login. Email and password, magic links and password reset — for the people who use your apps, and for the dashboard.
No custom roles and no fine-grained permissions. Eight presets, and two space roles. They cannot be misconfigured, which is the point.
No switch that closes sign-up. An invitation attributes and shares; it closes nothing. The seat cap bounds the rest.
No. Every table carries one of eight access presets that says who may list, read, create, update and delete its rows, and the API applies it to every request. Refusal is the default: a table with no declared preset is private.
Someone who signs in to one of your apps. A seat is taken at the first successful sign-in, not at sign-up — so a pool of dormant accounts never closes an app. Anonymous visitors of a public table take no seat, and joining a space takes no extra one.
Not alone. A publishable key created by an agent does everything except let people sign up. A human issues the active one from the dashboard: it is the one visit an agent cannot spare you.
One SQLite base per project
Server code with no server to run
Files, signed links, no egress
Give it a backend.