Monorepo Structure
Understanding the Data Pod codebase
Overview
Data Pod uses a monorepo with pnpm workspaces.
synap-backend/
├── apps/ # Deployable applications
├── packages/ # Reusable libraries
└── services/ # Example services
Key principle: Packages are building blocks, apps combine them.
Apps (Deployable)
apps/api/
Main Data Pod API server.
What it does:
- Serves tRPC endpoints
- Handles webhooks
- Provides SSE for real-time
- Runs event processors
Key files:
src/index.ts- Server setupsrc/webhooks/- Webhook handlers
Run locally:
cd apps/api
pnpm dev
Packages (Libraries)
packages/api/
tRPC router definitions and business logic.
Contains:
src/routers/- API endpointssrc/event-handlers/- Event processorssrc/plugins/- Plugin system
Example:
// packages/api/src/routers/notes.ts
export const notesRouter = router({ ... });
packages/database/
Database schema and migrations.
Contains:
src/schema/- Drizzle table definitionsmigrations/- SQL migration filessrc/projectors/- Event sourcing projections
Example:
// packages/database/src/schema/notes.ts
export const notes = pgTable('notes', { ... });
packages/events/
Event type definitions.
Contains:
src/domain-events.ts- Typed eventssrc/publisher.ts- Event publishingsrc/payloads.ts- Zod schemas
Example:
// packages/events/src/domain-events.ts
export type NoteCreatedEvent = BaseEvent<...>;
packages/client/
TypeScript SDK for frontends.
Contains:
src/index.ts- Main client classsrc/facades/- High-level APIs- Auto-generated from packages/api
Example:
const client = new SynapClient({ url: '...' });
await client.notes.create({ content: '...' });
packages/core/
Shared utilities.
Contains:
- Config management
- Logging
- Utilities
Services (Examples)
services/intelligence/
Example intelligence service (optional).
Shows how to build a remote service that integrates with Data Pod.
Package Dependencies
apps/api
├─→ packages/api
├─→ packages/database
├─→ packages/events
└─→ packages/core
packages/api
├─→ packages/database
├─→ packages/events
└─→ packages/core
packages/client
└─→ packages/api (types only)
Rule: Packages can depend on other packages, apps depend on packages.
Building Order
When changing code, build in dependency order:
# 1. Database (no dependencies)
cd packages/database && pnpm build
# 2. Events (no dependencies)
cd ../events && pnpm build
# 3. API (depends on database, events)
cd ../api && pnpm build
# 4. Client (depends on API types)
cd ../client && pnpm build
# 5. Apps (depend on everything)
cd ../../apps/api && pnpm build
Or build all:
pnpm build # From root, builds in correct order
Common File Patterns
Adding a Router
- Create in
packages/api/src/routers/ - Register in
packages/api/src/index.ts - Client automatically gets types
Adding Schema
- Create in
packages/database/src/schema/ - Export from
packages/database/src/schema/index.ts - Create migration in
packages/database/migrations/
Adding Events
- Define in
packages/events/src/domain-events.ts - Add builder in
packages/events/src/publisher.ts - Export from
packages/events/src/index.ts
Development Tips
Hot reload: Apps auto-reload on changes
cd apps/api && pnpm dev # Watches for changes
Type checking: TypeScript checks across packages
pnpm typecheck # Check all packages
Linting: ESLint + Prettier
pnpm lint
pnpm format
Next Steps
- Add router → Router Development
- Change schema → Database Migrations
- Work with events → Event System