WORK INDEX
BOOK A CALLEMAIL ME
OWN PRODUCT  ·  IN BETA  ·  2026

The clientnever signs in.

PRODUCT
Sightline
ROLE
Everything
AUTH
Magic link, no passwords
STACK
Next.js 16 · Prisma
DATA
Postgres · Neon
A Sightline client page, showing the decision and the requests waiting on the client
01  THE PROBLEM

Nobody opens the project management tool you invited them to.

A client wants to know three things: is it moving, what happens next, and is it waiting on them. A board with columns answers none of that until someone opens it, and they never open it. So the answer gets retyped into an email every week, until the week it doesn't, and then the silence starts reading as trouble.

The constraint arrived before the design did. The client cannot be asked to make an account. That deletes the obvious answers in one go: no invitations, no seats, no notification settings, no second product for them to learn. Everything else in the system follows from it.

The constraint I set: if the client has to remember anything to read this page, it has already failed. Not a password, not a login, not which tool the project lives in.
02  ARCHITECTURE

Two surfaces, one database, and a password on neither.

The studio side sits behind a magic link. The client side is one server-rendered page at /p/<slug>. The slug carries four random bytes, so a private link cannot be guessed from the project name. There is no API tier. The studio's own pages are server-rendered already, so an HTTP layer in front of Postgres would have been a second place to write the same authorisation check.

That makes authorisation the design. The client can do exactly two things: mark a request done and decide an approval. Both take the slug instead of a session, so there is no path where a forgotten session check hands back someone else's project. On the studio side, every child-row write carries the owning project and user in the same where clause. The permission check and the write are one query, so they cannot drift apart.

The sign-in email links to a page with a button on it, not straight to the verify endpoint. That is not a design preference. Mailbox scanners prefetch every URL they are sent, Outlook Safe Links among them, and a scanner reaching the endpoint first burns the link before its owner has clicked anything. One extra click buys immunity to that. Tokens are stored hashed for the same reason: read access to one table should not be enough to sign in as anybody.

FIG. 02.1 / SYSTEM
CLIENT PAGE
no account
SERVER ACTIONS
slug-scoped
PRISMA
typed
POSTGRES
source of truth
THE CLIENT'S ONLY TWO WRITES TAKE A SLUG AND NEVER A SESSION
EVERY STUDIO WRITE CARRIES ITS OWN AUTHORISATION IN THE WHERE CLAUSE
03  DATA MODEL

Five tables, and the rules worth having are constraints.

A client reads the page as a record of what was agreed. The schema's job is to stop that record and the interface disagreeing. Anything derivable is derived, and anything that has to happen together happens in one transaction.

projects
The slug is unique and carries four random bytes, so a private link cannot be worked out from the client's name. Progress is derived from the milestones, never stored. The override column exists and is deliberately nullable.
approvals
One row per project, and a unique constraint on the project id is what enforces it, not a check in the app. Two decisions competing for the same answer cannot be stored.
project_updates
The history the client reads. Deciding an approval writes the decision and its history entry in one transaction, so a decision can never exist without the line that explains it.
milestones
Ordered, each with one line of description and a done, active or todo state. Progress scores a complete milestone one and an active one a half, so the percentage cannot disagree with the timeline printed under it.
requests
What the studio is waiting on, marked blocking or when-you-can. Completing one is an update guarded on the done timestamp still being null, so a second tap from the client changes nothing.
04  STACK MANIFEST
CLIENT
Next.js 16 · React 19 · Server Components · Tailwind 4
SERVER
Server Actions · Better Auth · magic link
DATA
Postgres · Prisma 7 · Neon
SERVICES
Vercel · Resend
Need something your users can use without an account?