Skip to main content

Monorepo Approach

Goal: keep client, server, jobs, and docs in one repo for atomic changes, shared contracts, and simple CI/CD.

Why monorepo (now)

  • Atomic PRs: UI ↔ API ↔ jobs change together.
  • Shared contracts: one source of truth for DTOs, error codes, OpenAPI.
  • One local stack: DB/Redis/S3 once; run all services with a single command.
  • Simple releases: path-filtered CI so only affected parts ship.

When to split later

  • Team > 6–8 backend/ML engineers working in parallel.
  • Different deploy cadences (e.g., GPU stylization daily vs API weekly).
  • Reg/PII isolation requirements.
  • CI times > ~15 min even with caching.

Repo layout (baseline)

otherwhere/
├─ apps/
│ ├─ mobile/ # React Native (iOS)
│ ├─ admin/ # (optional) Next.js mod/admin
│ └─ docs/ # Docusaurus (Cloudflare Pages)
├─ server/ # Fastify monolith (REST + WS + jobs)
│ ├─ src/
│ │ ├─ app.ts # bootstrap
│ │ ├─ config/ # env, flags
│ │ ├─ plugins/ # auth, swagger, rate-limit…
│ │ ├─ lib/ # db, redis, s3, apns, logger
│ │ ├─ modules/ # auth, profiles, avatars, feed, matches, story, intents, reveal, safety, labels, analytics
│ │ ├─ ws/ # chat service
│ │ ├─ jobs/ # BullMQ processors
│ │ ├─ middleware/ # errors, request-id
│ │ └─ test/ # http/ws tests
│ ├─ prisma/ # migrations (or sql/)
│ ├─ openapi/ # generated json
│ └─ scripts/ # seed, smoke
├─ workers/
│ └─ avatar-python/ # PyTorch stylization worker
├─ packages/
│ ├─ shared-types/ # DTOs, error codes, analytics events
│ ├─ eslint-config/
│ └─ tsconfig/
├─ infra/
│ ├─ docker-compose.dev.yml # postgres, redis, minio
│ └─ (iac later)
├─ .github/workflows/ # CI per surface
├─ pnpm-workspace.yaml
└─ README.md

Workspaces & path filters

Use pnpm workspaces; CI runs only where files changed.

# example path filters in GitHub Actions
on:
push:
branches: [main]
paths:
- "apps/docs/**"
- ".github/workflows/docs.yml"

Module contract (server)

Each feature in server/src/modules/<feature>/:

  • routes.ts — Fastify routes (wire Zod schemas)
  • schemas.ts — Zod request/response DTOs (→ OpenAPI)
  • service.ts — business logic
  • repo.ts — DB access only

Local dev flow

docker compose -f infra/docker-compose.dev.yml up -d
pnpm -w install

# server
cd server && pnpm dev

# mobile
cd apps/mobile && pnpm start

# docs
cd apps/docs && pnpm start

Shared contracts

  • packages/shared-types/ exports DTOs, error codes, analytics events.
  • server generates OpenAPI from Zod → copied into apps/docs/static/api/ (build step).
  • Mobile imports types from shared-types to avoid drift.

Conventions

  • TypeScript strict, Zod validation, explicit error codes.
  • Conventional commits; trunk-based flow.
  • Feature flags in server/src/config/flags.ts.
  • PR checklist: schemas, tests, analytics, docs, rollback notes.