Internal membership management platform.
- Node.js 20+
- Docker
npm installcp .env.example .envAdd required credentials to .env (Slack, Google, Resend, etc.).
# Start PostgreSQL
npm run db:up
# Run migrations
npm run db:migratenpm run devOpens at http://localhost:3000. This runs both Next.js and Inngest dev server.
After running migrations on a fresh database, the following records must exist before anyone can log in. Use npm run db:studio or run the SQL directly against your database.
Every user requires a batch. Create at least one before creating any users.
INSERT INTO batch (number, start_date) VALUES (1, '2024-01-01');Add more rows for additional cohort years as needed.
Create the user record manually (via Drizzle Studio or SQL). The following field values are required for a clean setup — the user will see the full member dashboard with no payment prompts:
| Field | Value |
|---|---|
status |
member |
legal_membership_state |
active_member |
batch_number |
1 (or whichever batch you created) |
personal_email |
a real email address |
phone |
a phone number |
street, city, state, zip, country |
any valid address |
Why:
status = member+legal_membership_state = active_memberare required for the permissions system. The address and contact fields are required for the profile to read as complete, which gates payment setup visibility.
Replace <user_id> with the ID of the user created above.
INSERT INTO user_access_grant (id, user_id, grant, scope, department, created_at, updated_at)
VALUES ('aug_setup', '<user_id>', 'admin', 'global', NULL, NOW(), NOW());Without this record the home screen shows a "Set up payment" prompt that leads to a GoCardless checkout the admin user should not need. This creates a permanently-covered manual payment with no GoCardless integration.
INSERT INTO membership_payment (id, user_id, status, provider, paid_through_at, activated_at, created_at, updated_at)
VALUES ('mp_setup', '<user_id>', 'active', 'gocardless', '2099-12-31', NOW(), NOW(), NOW());The admin user can now log in and will see a clean member dashboard.
| Command | Description |
|---|---|
npm run db:studio |
Open Drizzle Studio (allow local connections in browser if prompted) |
npm run db:generate |
Generate migrations |
npm run db:dump |
Dump database to supabase.sql |
npm run db:restore |
Restore database from supabase.sql |
npm run email:dev |
Preview emails |
npm run lint |
Run Biome linter |
npm run format |
Format code |