Daily Workflows
The commands and sequences you will run over and over.
Starting your day
git pull
pnpm install # only if package.json or the lockfile changed
docker compose up -d db redis
pnpm build # only if packages/* changed; Turbo cache makes it cheap
pnpm devIf someone added a migration, also run:
cd packages/database && pnpm db:migrate && cd ../..Adding a REST endpoint
The API is layered. Touch the files in this order:
Route —
apps/api/src/router/<domain>Routes.tstsrouter.get("/widgets/:id", authenticated, widgetController.getWidget);Register it — add the router to
apps/api/src/router/index.tsif it is a new file. Everything mounted there sits under/api/v1.Controller —
apps/api/src/controllers/widget.ts. Parse and validate input (zod schemas live inapps/api/src/schemas/), call a service, shape the response. No Prisma calls here.Service —
apps/api/src/services/widget.ts. Business logic and database access.Document it — add the route to the matching page under API Reference.
Mobile client — if the app consumes it, add the call in
apps/mobile/api/<domain>.tsand a TanStack Query hook inapps/mobile/hooks/<domain>/. See Data Layer.
Changing the database
cd packages/database
# 1. edit prisma/schema.prisma
pnpm db:migrate # prompts for a migration name, applies it, regenerates the clientdb:migrate runs prisma migrate dev, which creates the SQL migration, applies it to your local database, and regenerates the client. Commit the generated folder under prisma/migrations/.
Then rebuild the package so consuming services pick up the new types:
cd ../.. && pnpm build --filter=@playpals/dbNever edit an applied migration
Once a migration has run anywhere other than your laptop, it is immutable. Fix mistakes with a new migration. Editing history means the next migrate deploy in production will fail its checksum.
More detail in Migrations & Seeding.
Adding a realtime event
Realtime is a contract between three places, and all three must agree:
packages/types/src/socket-events.ts— add the event toClientToServerEvents,ServerToClientEvents, orInterServiceEvents.apps/esu/src/socket/handlers.ts— handle it (client→server) or emit it (server→client).- The producer — if the API triggers the fan-out, add it to the
/admininterservice router inapps/esu/src/interservice/adminRoutes.tsand call it from the API.
Then rebuild @playpals/types so both sides compile against the new shape. See Socket Events.
Working on the mobile app
pnpm --filter @playpals/mobile ios # iOS simulator
pnpm --filter @playpals/mobile android # Android emulator
pnpm --filter @playpals/mobile start # Metro only; pick a target interactivelyMetro caches aggressively. When you see stale code or a module resolution error that makes no sense:
pnpm --filter @playpals/mobile start -- --clearIf you add a native dependency or change a config plugin, a JS reload is not enough — you need a new development build. See Builds & Releases.
Before you open a pull request
pnpm check-types # tsc --noEmit across the workspace
pnpm lint
pnpm format # prettier --write "**/*.{ts,tsx,md}"
cd apps/ogun && pnpm test # apps/api has no test files yet
cd apps/anansi && pnpm testAlso confirm:
- New or changed endpoints are reflected in API Reference.
- New environment variables are added to the service's
.env.example, the matchinginfra/k8s/*-deployment.yaml, and Environment Variables. - Migrations are committed.
Shipping
Building and pushing images, and rolling them out to the cluster, is covered in Deploying.
Useful one-liners
# Follow one service's logs in the Turbo TUI without the noise of the others
pnpm --filter @playpals/api dev
# Reset the local database completely
docker compose down -v && docker compose up -d db redis
cd packages/database && pnpm db:migrate && pnpm db:seed
# Inspect what is in the media queue
docker exec -it playpals-redis redis-cli -a playpalz KEYS 'bull:media-processing:*'
# Open Prisma Studio against your local database
cd packages/database && pnpm exec prisma studio