System infrastructure
This page covers the parts of the system that matter when you need to run, debug, or deploy the app.
At a glance
WMA is a Next.js app backed by PostgreSQL, Redis, S3-compatible object storage, and SMTP for email.
graph TB
Client[Browser]
App[Next.js app]
DB[(PostgreSQL on Neon)]
Cache[(Redis)]
Storage[S3-compatible storage]
Email[SMTP]
Client --> App
App --> DB
App --> Cache
App --> Storage
App --> Email
Runtime services
App
- Runs in
wma-web - Built from
Dockerfile.prod - Exposes port
3000 - Runs as the
nextjsuser in production
Redis
- Runs in
wma-redis - Uses
redis:7.4-alpine - Shared with the app over the
wmaDocker network
Deployment files
Dockerfile.prod: production image builddocker-compose.staging.yml: staging containersdocker-compose.prod.yml: production containersTaskfile.yml: shorthand commands for build and deploy steps
Useful commands
# local app
pnpm install
pnpm dev
# database
pnpm db:push-dev
pnpm db:seed:dev
pnpm db:deploy-prod
# staging
task 01-build-staging
task 02-start-staging
task 03-stop-staging
# production
task 04-build-production
task 05-start-production
task 06-stop-production
Environment variables
Keep secrets out of git. The app depends on a few groups of variables:
- Database:
DATABASE_URL,DIRECT_URL - Auth:
NEXTAUTH_SECRET,NEXTAUTH_URL,HASH_SECRET - Redis:
REDIS_URLorREDIS_HOSTandREDIS_PORT - Storage:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_REGION,S3_ENDPOINT,BUCKET_NAME - Email:
GMAIL_APP_PASSWORD - Public config:
NEXT_PUBLIC_HOST_URL,NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITE_KEY - Private Turnstile config:
CLOUDFLARE_TURNSTILE_SECRET_KEY
Database notes
- PostgreSQL is hosted on Neon.
- Prisma is the only supported ORM path in the repo.
- Schema files live under
prisma/schema/. - Use
db:deploy-prodfor production migrations.
Storage and email
- File uploads use DigitalOcean Spaces through the AWS SDK.
- Outbound email uses Gmail SMTP.
Logs and checks
docker compose -f docker-compose.prod.yml logs -f wma-web
docker compose -f docker-compose.prod.yml logs -f wma-redis
Basic runtime checks:
- App responds on
http://localhost:3000 - Redis container is up
- Database migrations have been applied
Operational notes
- Production and staging both use
Dockerfile.prod. - The production image is a multi-stage build.
- Redis is internal-only in compose.
- Back up the database before risky production changes.