The problem
At Berkeley you meet a lot of people quickly, and notes on them end up scattered. A tool for that has to answer one question before any other: can anyone else see my contacts?
What I did
- Built sign-up, sign-in, and a contact list with create, edit, delete, sort, filter, and search, in Next.js on Vercel.
- Stored contacts in Neon Postgres and isolated them with row-level security in the database, so even a direct call to the public Data API can't read someone else's rows.
- Proved it. Queried as the role the API uses while two rows existed, and got zero back.
- Validated input three times: in the form, on the server, and with a database constraint. The friendly message is a courtesy, not the defense.
- Designed all four list states: loading skeletons, two distinct empty states, a plain-language error with one-click retry, and success.
- Captured every screenshot in the write-up from the deployed app, not localhost.
Results
0rows visible to the wrong user
3layers of input validation
4list states designed
15screenshots from the live app
What I'd do differently
Check the security boundary on every push. The isolation test needs two real accounts and a live database, so today it runs on demand. Next: run it in CI against a throwaway database branch that seeds its own accounts.
Artifacts

