Architecture
Overview
This repository is a Turbo + Bun monorepo.
- Runtime:
apps/* - Shared and reusable code:
packages/*
apps/
api -> HTTP API (Express)
discord -> Discord bot + BullMQ workers
websocket -> WebSocket gateway + workers BullMQ
website -> Frontend
packages/
config -> env loading + Zod validation
schema -> Zod contracts (BullMQ + business schemas)
infra-* -> technical adapters (Redis, Prisma, BullMQ, etc.)
domain-* -> domain-oriented business logic
core -> cross-cutting logic / application services
Allowed Dependencies
General rule: only “downward” dependencies.
apps/*can depend onpackages/*.corecan depend ondomain-*,infra-*,config, andschema.domain-*can depend oninfra-*,config, andschema.infra-*must not depend onapps/*.schemashould only depend on validation libraries (zod).
Critical Boundaries
Discord Boundary
- Any Discord action triggered outside
apps/discordmust go through BullMQ. - Use
@gmod/infra-bullmq/discordQueueAdapters.js. - Define/update payloads in
packages/schema/src/bullmq.ts. - Implement worker handlers in
apps/discord/src/discord/workers/discordQueueWorkers.ts.
Config Boundary
- Single source of truth:
@gmod/config. @gmod/configloads workspace.envfiles and validates with Zod.- Avoid reading
process.envdirectly in business modules.
Data Boundary
- Prisma client is generated in
packages/infra-prisma/generated/prisma. - Import Prisma client through
@gmod/infra-prisma. - Do not duplicate Prisma clients in apps.
Composition Patterns
API Endpoint Pattern
- Route (
apps/api/src/routes/*) - Validation/Auth middleware (
apps/api/src/middleware/*) - Thin controller (
apps/api/src/controllers/*) - Extracted logic in
packages/core/src/models/*orpackages/domain-*
WebSocket Pattern
- Asynchronous sending through BullMQ queues (
@gmod/infra-websocket/queues.js). - Processing in the websocket app via workers.
Global Express Typing
Requestextensions (req.server,req.panelUser, etc.) are centralized in:packages/core/src/types/express.d.ts
Anti-Patterns to Avoid
- Importing
apps/discord/...from API/core/domain. - Heavy business logic in controllers/routes.
- Duplicating payload schemas outside
packages/schema. - Introducing new cycles between domain packages.