Database
Drizzle, PGlite, and the migrations workflow
Tables
| Table | Purpose |
|---|---|
wishlist_signups | Landing-page wishlist (email unique, source, referrer) |
invites / invite_redemptions | Invitations |
user_achievements | Canonical achievement unlocks |
user, session, account, verification | better-auth core tables — shape is dictated by better-auth's drizzle adapter, don't restructure casually |
All defined in apps/api/src/db/schema.ts.
Changing the schema
# 1. Edit apps/api/src/db/schema.ts
# 2. Generate the SQL migration
pnpm --filter api db:generate
# 3. Commit the new file in apps/api/drizzle/Migrations apply automatically the next time the server boots (dev, test, and prod all run the same migrator). There is no separate "migrate" deploy step.
Local data
The embedded database lives in apps/api/.data/pglite (gitignored). Nuke the folder for a fresh start:
rm -rf apps/api/.dataGotchas
- PGlite doesn't create parent directories —
createDbdoesmkdir -pfirst. Keep that if you touch it. - The
account.accountIdcolumn doubles as the steamId64 for accounts withproviderId = "steam"— achievement mirroring depends on this. - Postgres unique-violation code
23505is used to detect double-redemption of invites; drizzle wraps errors, so the check walkserror.cause.