Architecture Overview
The big-picture map of the Emofy Platform — apps, the backend pipeline, data, auth, and the ecosystem.
A high-level map of the platform for engineers. For the exhaustive System
Architecture Definition (SAD), see docs/001_SYSTEM_ARCHITECTURE_DEFINITION.md
in the repo. The pages in this section drill into each layer:
Backend
The NestJS API: module grouping and the global guard/interceptor pipeline.
Request lifecycle
One request traced end to end, guard by guard.
Data model
Dual databases, Drizzle, org-scoped repositories, and prefixed IDs.
Tech stack
Every technology in the platform, and what it's used for.
The shape of the system
┌──────────────────────────────────────┐
│ account (Next.js) │
sign in ──────────▶│ Better Auth — issues RS256 JWT │
└──────────────────┬───────────────────┘
│ JWT (+ JWKS for verification)
┌───────────────┬─────────────────┼──────────────────┐
▼ ▼ ▼ ▼
consumer (web) admin (web) native (Expo) EMAs (iframes)
│ │ │ │
└───────────────┴────────┬────────┴──────────────────┘
│ REST (Bearer JWT + X-Org-Id)
▼
┌───────────────────────┐ ┌──────────────┐
│ backend (NestJS) │◀────▶│ Convex │ real-time
│ the only DB writer │ │ (messaging) │
└───────────┬───────────┘ └──────────────┘
┌─────────────┬───────┼────────┬─────────────┐
▼ ▼ ▼ ▼ ▼
Postgres Redis BullMQ Meilisearch R2 / S3
(auth+core) (cache) (queues) (search) (files/EMA bundles)Everything funnels through one backend. The frontends never touch the database; they authenticate via the account app and call the backend over REST.
Apps
The platform is a Turborepo monorepo (pnpm workspaces). apps/ holds
deployables, packages/ holds shared code — see the
Repository tour for the full list.
| App | Stack | Role |
|---|---|---|
backend | NestJS REST API | The single API surface; deployed to Railway. |
account | Next.js + Better Auth | Sign-in, account, and credential management. |
admin | Next.js | Super-admin console. |
consumer | Next.js | Parent / org web experience (/w/{orgId}/*). |
native | Expo / React Native | Mobile app (demo-stage). |
docs | Next.js / Fumadocs | This developer portal. |
landing, marketing | Next.js | Public sites. |
Backend pipeline
The backend is the only service that talks to the database. Every request flows through a global pipeline — authentication → org context → authorization → validation → handler → response envelope — built from an ordered chain of guards and interceptors. The exact order and what each stage does is on the Backend and Request lifecycle pages.
The backend publishes three OpenAPI documents from one shared
DocumentBuilder (apps/backend/src/config/openapi-documents.ts):
- Internal — the full surface used by the web/mobile dashboards
(
{ success, data }envelope). - Developer — the public partner API (
{ data, meta }/{ error }V1 envelope). A deterministic snapshot is committed and powers the Developer API Reference. - EMA — the surface available to Embedded Mini Apps.
See API conventions for how the three surfaces differ.
Auth & multi-tenancy
Authentication is Better Auth (RS256 JWT bearer tokens), issued by the
account app and verified by the backend against a JWKS endpoint. The
organization plugin models multi-tenancy: a user can hold roles in multiple
organizations, and every request carries org context. Tenant isolation is
enforced in the data layer by OrgScopedRepository — raw db.select() on
tenant tables is forbidden.
Read the trust model in depth: Authentication, Authorization (RBAC), and Multi-tenancy.
Data & infrastructure
- Database: Postgres via Drizzle ORM — two databases,
emofyplatform_authandemofyplatform_core(ADR-001). - Real-time: Convex powers live messaging and presence.
- Cache & queues: Redis, with BullMQ for durable background jobs.
- Search: Meilisearch (full-text across feed, messages, tasks).
- Files: Cloudflare R2 (immutable EMA bundles) + S3 (org uploads).
- Hosting: Frontends on Vercel; backend on Railway (GHCR image, CI
deploy.yml), environments development / staging / main. - Infra as code: OpenTofu owns Vercel + Railway wiring; secrets sync from Infisical (ADR-016/017).
Ecosystem: EMAs and webhooks
Third-party and domain-specific features are built as EMAs (Embedded Mini Apps) that request scoped permissions (see EMA Scopes), and as webhook consumers that receive signed events (see Webhooks). The concept and lifecycle are covered in The EMA ecosystem.