Local Development
First run
npm install- Populate
.env.local— see environment.md. npm run db:push— creates tables in your Neon branch.npm run dev— starts Next.js on port 3000.- Visit
/registerto create user + org, then/overview.
Minimum env to boot without errors
To run the dev server and hit the dashboard:
DATABASE_URLNEXTAUTH_SECRET(any random string)NEXTAUTH_URL=http://localhost:3000
Stripe/AWS/Upstash envs only matter when you hit code paths that use them (send email, upgrade billing, rate limit).
Testing the API without AWS
Create a test API key from /overview/api-keys. Test keys (sok_test_*) skip AWS provider calls and usage limit checks — they only write to the messages table.
curl -X POST http://localhost:3000/api/v1/emails \
-H "Authorization: Bearer sok_test_..." \
-H "Content-Type: application/json" \
-d '{"from":"a@example.com","to":["b@example.com"],"subject":"Hi","text":"Hi"}'
Drizzle Studio
npm run db:studio
Opens a browser-based DB inspector.
Dashboard auth
/register— createsuser+organization+org_memberrows./login— NextAuth credentials provider, bcrypt compare.- Proxy (
src/proxy.ts) redirects unauthenticated traffic on/overview/*to/login, and is also where 2FA confinement and/api/v1CORS live.
Next 16 renamed middleware.ts to proxy.ts, and the exported function must be
named proxy, not middleware. Two things about the location are worth knowing
before you move it:
- It must sit at
src/proxy.ts, besideapp/— not besidepackage.json. Next resolves it relative to the app root, so a root-level copy type-checks, lints, and never runs. It sat there once and the org 2FA mandate, whose only enforcement point is this file, was unenforced in production the whole time. next buildprintsƒ Proxy (Middleware)in the route table when it is wired up. If that line is absent, the file is not being loaded.src/proxy.location.test.tsasserts the placement so the mistake fails a test run rather than a deploy.