Run it yourself
Reading only goes so far. Everything in these notes can be made to happen on your machine.
Start it
Needs Bun, and Docker running.
bun installbun run db:upbun run db:migratebun run devThe app is at localhost:5200, and these notes are at localhost:5200/notes. There's nothing to sign in to. The first domain you enter gives this browser a prufy_session cookie, and every claim after that belongs to it.
Fake DNS: try every failure
DNS_MODE=fixtures bun run devEnter <name>.prufy-demo.dev on the landing page and press I've added it. To see a transfer, verify verified.prufy-demo.dev, then do it again in a private window. A private window has no cookie, so it becomes a second account.
| Name | What you'll see |
|---|---|
verified | Verified |
lookalike | One character looks alike |
truncated | Part of the value is missing |
quotes | Quote marks in the value |
whitespace | An extra space |
prefix | Only the code, without its prefix |
different | Another code |
stale | An older code. Get a new code first |
nothing | Nothing at the name |
doubled | Domain in the host field twice |
wrong-name | Saved at the apex |
no-underscore | Saved without the underscore |
wrong-provider | Added where the nameservers don't point |
cname | A CNAME is using the name |
no-such-zone | Domain doesn't exist |
propagating | Waiting on public DNS, verified on the 3rd check |
disagree | Waiting on the provider, verified on the 3rd check |
unreachable | Try again later |
servfail | One of the provider's servers is failing |
lame | Nameservers are listed but don't work |
parked | The domain is parked at a parking service |
typo-then-fixed | A typo, verified on the 2nd check |
record-removed | Verified, at risk, restored on the 4th check |
mail.subzone | A subdomain inside a parent zone |
one-click | One-click available |
one-click-not-enabled | Supported, not enabled |
Time travel
Dev only. Moves the server's clock, so time-based states can be reached by hand.
curl -X POST localhost:5200/api/dev/clock -H 'content-type: application/json' -d '{"advanceMs":90000000}'curl -X POST localhost:5200/api/dev/run-worker| To see | advanceMs |
|---|---|
| A verified claim re-checked (25 hours) | 90000000 |
| An at-risk re-check (6 hours) | 21600000 |
| A code expire, or grace end (8 days) | 691200000 |
Turn on alerts
Both channels are off until their keys are set, and the alerts card on the claim page only offers what's on. With neither, the card doesn't render. Set these in apps/web/.env.local.
| Variable | Turns on |
|---|---|
RESEND_API_KEY | Email: alerts, invites and address confirmation. EMAIL_FROM's domain has to be verified in Resend |
VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY | Push notifications. Both are needed |
bunx web-push generate-vapid-keysLook at the globe without a browser
Renders the shader's scenes to PNG files in apps/web/.globe-frames, so a change to globe.wgsl can be looked at in seconds.
node apps/web/scripts/render-globe.mjsLook at real DNS
bun run dns:probe example.comLook inside the database
docker compose exec postgres psql -U prufy -d prufySELECT domain_ascii, status, version, next_check_at FROM domain_claims;SELECT type, actor_kind, at FROM claim_events ORDER BY at DESC LIMIT 20;SELECT resolver, qname, rcode, answers FROM observations LIMIT 20;SELECT account_id, left(token_hash, 12) AS hash, last_seen_at, expires_at FROM sessions;SELECT claim_id, invited_email, opened_at, expires_at FROM claim_shares;Checks before committing
bun run typecheckbun run testbun run checkbun run buildbun run check skips these notes because they're gitignored, and Turbo can replay a cached result for the others. The publish script below checks them directly.
Two sites, one repo
.vercelignore leaving these notes out.Deploy the app
Vercel deploys from GitHub, so pushing is usually all it takes.
To deploy by hand, run this from the repo root, because the app needs the workspace packages. Migrations never run on deploy, so when the schema changes, apply them first to both the production and preview databases, using Neon's direct connection.
vercel deploy . --prod --yes --project prufy --scope personal-d39c1b49DATABASE_URL="$DATABASE_URL_UNPOOLED" bun run db:migratePublish these notes
This is how the copy on your phone gets updated. The app's API and worker need a server and its globe needs a shader build, so the published site contains only the notes, with no git connection. The script stops if the notes import anything the static copy can't build.
bash apps/web/app/notes/_deploy/deploy.sh