calcom/cal.com
Architecture
Cal.diy is a Yarn 4 + Turborepo monorepo containing three deployable apps and ~30 shared workspace packages. The default deployment is the Next.js web app (apps/web) connected to a PostgreSQL database; everything else is optional.
Top-level layout
cal.com/
├── apps/
│ ├── web/ # Next.js 13+ App Router — the main product
│ ├── api/v2/ # NestJS REST API (Cal.com Platform v2)
│ ├── api/index.js # Thin proxy entry for legacy API routing
│ └── docs/ # MintLify documentation site
├── packages/
│ ├── features/ # 70+ feature modules (bookings, eventtypes, slots, ...)
│ ├── lib/ # Shared utilities (CalendarService, dayjs, crypto, ...)
│ ├── ui/ # Shared design system (Button, Form, Dialog, ...)
│ ├── prisma/ # Database schema, migrations, seed scripts
│ ├── trpc/ # tRPC routers + client wiring
│ ├── app-store/ # 100+ integrations (calendars, video, payments, CRM, ...)
│ ├── app-store-cli/ # Code generator that wires apps into the registry
│ ├── embeds/ # embed-core, embed-react, embed-snippet
│ ├── platform/ # NestJS API SDK + React "atom" components
│ ├── emails/ # Transactional email templates
│ ├── dayjs/ # Pre-configured Day.js bundle with plugins
│ ├── debugging/ # Logger, troubleshooter helpers
│ ├── di/ # Dependency injection helpers
│ ├── kysely/ # Generated Kysely types from Prisma
│ ├── i18n/ # next-i18next locales (en is canonical)
│ ├── sms/ # SMS providers (Twilio, etc.)
│ ├── trpc/ # tRPC server + client
│ ├── types/ # Shared TypeScript types
│ ├── tsconfig/ # Shared tsconfig presets
│ └── ... (config, coss-ui, embeds, testing, kysely)
├── example-apps/ # Sample integrations
├── deploy/ # Deployment helpers
├── scripts/ # SQL helpers + seeding scripts
└── specs/ # Spec-driven-development specsRuntime architecture
graph TD
subgraph Browser
WebApp[apps/web Next.js client]
Embeds[embed-core / embed-react]
Atoms[platform/atoms]
end
subgraph "Next.js server (apps/web)"
AppRouter[App Router routes]
PagesRouter[pages/ legacy routes]
TRPCServer[tRPC routers @calcom/trpc]
NextAuth[NextAuth.js]
end
subgraph "NestJS server (apps/api/v2)"
REST[REST controllers]
OAuthClients[OAuth clients module]
PlatformSDK[Platform SDK endpoints]
end
subgraph "Background"
Trigger[Trigger.dev jobs]
Cron[GitHub Actions crons]
Tasker[features/tasker queue]
end
subgraph Data
Postgres[(PostgreSQL via Prisma)]
Redis[(Redis cache + rate limit)]
end
subgraph "Third party"
Calendars[Calendar APIs]
Video[Video providers]
Payments[Stripe / PayPal / HitPay]
Email[SendGrid / SMTP]
SMS[Twilio]
end
WebApp -->|tRPC HTTP| TRPCServer
WebApp -->|NextAuth| NextAuth
Embeds -->|loads| WebApp
Atoms -->|REST| REST
TRPCServer --> Postgres
REST --> Postgres
NextAuth --> Postgres
TRPCServer --> Redis
REST --> Redis
TRPCServer --> Calendars
REST --> Calendars
Trigger --> Postgres
Tasker --> Postgres
Cron -->|HTTP| AppRouter
AppRouter --> Email
AppRouter --> SMS
AppRouter --> Payments
REST --> VideoThe web app is the primary entry point for end users and embeds. It serves marketing pages, booking pages, the authenticated dashboard, and a tRPC HTTP endpoint at /api/trpc/[trpc] (see apps/web/pages/api/trpc/[trpc].ts and packages/trpc/server/createNextApiHandler.ts). The NestJS API in apps/api/v2 is deployed separately and powers the official REST API plus the Platform SDK ("atoms"). Background jobs run through Trigger.dev and cron-style GitHub Actions workflows that hit internal HTTP endpoints.
Request lifecycle: a public booking
sequenceDiagram
participant Visitor
participant Web as apps/web
participant TRPC as packages/trpc
participant Slots as features/slots
participant Calendars as features/calendars
participant Booking as features/bookings
participant DB as PostgreSQL
Visitor->>Web: GET /[username]/[eventType]
Web->>TRPC: viewer.public.event + slots.getSchedule
TRPC->>Slots: getAvailableSlots
Slots->>Calendars: getBusyTimes (Google/MS/Apple/CalDAV)
Calendars-->>Slots: busyIntervals
Slots-->>TRPC: timeSlots
TRPC-->>Web: render slot picker
Visitor->>Web: POST /api/book/event
Web->>Booking: handleNewBooking
Booking->>DB: create Booking + BookingReference
Booking->>Calendars: create event in destination calendar
Booking->>Web: emit webhooks, send emails, schedule reminders
Web-->>Visitor: redirect to /booking/[uid]The end-to-end flow lives mostly in packages/features/bookings/lib/handleNewBooking/ (split into many submodules) and packages/features/slots. Calendar federation is handled through adapters in packages/app-store/<provider>/lib/CalendarService.ts, all conforming to the shared Calendar interface in packages/types/Calendar.d.ts.
Core architectural patterns
- Repository / service split.
packages/features/<domain>/repositories/*Repository.tswrap Prisma queries and never contain business logic.packages/features/<domain>/services/*Service.tsorchestrate repositories and external calls. tRPC handlers and REST controllers stay thin and delegate to services. The convention is documented inAGENTS.mdand reinforced byagents/rules/quality-architecture.md. - Dependency injection. Each domain has a
di/directory (e.g.,packages/features/bookings/di) using a small homegrown container inpackages/features/di/. This decouples handlers from repository implementations and makes testing simpler. - Generated app metadata.
packages/app-store-cliwalkspackages/app-store/*and emits the*.generated.tsfiles (apps.metadata.generated.ts,apps.server.generated.ts,bookerApps.metadata.generated.ts, etc.).AGENTS.mdcalls out that these files must never be hand-edited. - Path-based imports. The codebase deliberately avoids barrel
index.tsre-exports —AGENTS.mdmandatesimport { Button } from "@calcom/ui/components/button"rather thanimport { Button } from "@calcom/ui". - Type-safe API. tRPC carries TypeScript types from server to client without code generation, while
apps/api/v2uses Zod schemas (packages/platform/types) shared between request validation and the Platform SDK. - Feature flags.
packages/features/flagsprovides a database-backed flag service used to gate experimental code (e.g.,packages/features/flags/features.repository.ts).
Two API surfaces
The repo intentionally exposes two API layers, each with its own audience:
| Surface | Path | Used by | Auth |
|---|---|---|---|
| tRPC | packages/trpc/server/routers/ mounted at apps/web/pages/api/trpc/[trpc].ts |
The web app and embeds | NextAuth session cookie |
| REST v2 | apps/api/v2/src/modules/** |
Platform SDK consumers, third-party integrators | API keys, OAuth, JWT |
A legacy pages/api/v1/ directory under apps/web/pages/api mirrors a subset of the REST surface for backward compatibility. The proxy in apps/web/proxy.ts decides how requests are routed across these surfaces.
Where to look next
- Apps overview — the three deployable units
- Packages overview — every workspace package
- Features overview — cross-cutting capabilities (bookings, slots, scheduling, ...)
- Primitives —
EventType,Booking,User,Schedule,Credential - API — tRPC vs REST v2
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.