# Login That Works — the PocketBase route

Login fails in beginner projects for a boring reason: the AI invents a
different auth design every session — its own password table one day, a
half-connected service the next — and each redesign breaks the last.
PocketBase removes the design question. Accounts, password hashing,
sessions, and password-reset emails are built into the one file. Your
job is setup and rules, in this order, ONCE.

## Step 1 — Run it and make your admin account

1. Unzip the download. In that folder, run:
   `./pocketbase serve` (Windows: `pocketbase.exe serve`)
2. Open the address it prints (ends in `/_/`). Create the superuser
   account when asked — this is YOUR admin login for the backend
   screen. It is not an account inside your app; don't share it.
3. Leave it running while you build. Your app talks to it at
   `http://127.0.0.1:8090` on your own machine.

## Step 2 — The users collection (PocketBase makes most of it)

PocketBase ships an auth collection called `users` — email, password
(hashed by PocketBase, never stored readable), and verified status.
Use it as-is for a first app. Do NOT let an AI create a second,
hand-rolled "accounts" or "passwords" table: two sources of truth for
login is the exact shape of the 260-credit bug.

Add your app's own fields (display name, avatar) TO the users
collection, or make a separate `profiles` collection that points at
the user — never a second password anywhere.

## Step 3 — Access rules: the part that makes it safe

Every collection has API rules in the admin screen. For any collection
holding a user's own things (notes, saves, orders), set:

- **List / View rule:** `owner = @request.auth.id`
  (with an `owner` field on the collection pointing at the user)
- **Create rule:** `@request.auth.id != ""` and set `owner` from the
  logged-in user on create
- **Update / Delete rule:** `owner = @request.auth.id`

In plain words: a logged-in person can only ever see and touch rows
marked as theirs. This rule — not the login form — is what makes the
two-account test pass. An empty rule means "anyone", and "anyone"
includes people who never logged in.

## Step 4 — Wire the app with ONE bounded prompt

Snapshot first (the snapshot rule: a restorable copy BEFORE the
session). Then give your AI this prompt, filled in, instead of
"add login":

> Add email + password login to this app using the PocketBase
> JavaScript SDK (`pocketbase` package) pointed at
> http://127.0.0.1:8090. Use ONLY PocketBase's built-in `users`
> auth collection — no custom password handling, no second auth
> library. Deliver exactly: a register form, a login form, a logout
> button, and the current user's email shown when logged in.
> Keep the session with the SDK's built-in auth store. Change
> nothing else in the app. When done, list what you changed and
> how you verified register, login, and logout each work.

One prompt, one sitting, checkable end state. If it fails, fix inside
the same design — switching auth designs mid-project is how the
credit bonfire starts.

## Step 5 — Prove it (from the acceptance template)

- Register account A, log out, register account B.
- As B, confirm you cannot see any of A's things (the two-account
  test). If you can, the Step 3 rules are wrong — fix the rules,
  not the interface.
- Wrong password is refused; logout actually ends the session
  (refresh the page — you should still be logged out).

## Failure modes this route fences off

- **"It works in the preview but not live"** — the app is pointing at
  127.0.0.1, which only exists on your machine. Hosting step: point
  the app at the hosted PocketBase address (see hosting-and-costs.md).
- **Reset emails never arrive** — PocketBase sends mail only after
  mail settings are filled in (admin screen → Settings → Mail). Until
  then, password reset can't work; say so in your app or set it up.
- **Users can see everything** — a collection rule left empty. Step 3.
- **AI rebuilt auth again** — refuse the redesign. The design is
  "PocketBase users collection"; repairs happen inside it.
