Adr
ADR-004: Monorepo Structure
Combined Python backend and TypeScript frontend in single repository
ADR-004: Monorepo Structure
Status
Accepted
Context
Agent Studio consists of:
- Backend: Python FastAPI API + LiveKit worker
- Dashboard: Next.js web application
- Docs: Fumadocs documentation site
We need to decide how to organize these components.
Options Considered
- Separate repositories - Independent deployments, complex coordination
- Monorepo with shared types package - Type sharing via npm package
- Monorepo with OpenAPI generation - Generate TS types from Python
- Polyrepo with git submodules - Worst of both worlds
Decision
We will use a monorepo with separate package managers:
agent-studio/
├── src/agent_studio/ # Python backend (uv)
├── apps/
│ ├── dashboard/ # Next.js dashboard (pnpm)
│ └── docs/ # Fumadocs site (pnpm)
├── pyproject.toml # Python dependencies
├── uv.lock # Python lockfile
├── package.json # Root workspace config
├── pnpm-workspace.yaml # pnpm workspace
└── pnpm-lock.yaml # JS/TS lockfileType Sharing Strategy
Instead of a shared-types package, we use OpenAPI → TypeScript generation:
- FastAPI generates OpenAPI spec automatically
- Build step generates TypeScript types from spec
- Dashboard imports generated types
# Generate types during build
pnpm --filter @agent-studio/dashboard run generate-typesWhy Not shared-types Package?
- Adds complexity (publish, version, sync)
- Types are already defined in Python (Pydantic)
- OpenAPI is the source of truth for API contracts
- Generated types are always in sync
Workspace Configuration
# pnpm-workspace.yaml
packages:
- 'apps/*'// package.json (root)
{
"name": "agent-studio",
"private": true,
"scripts": {
"dev:dashboard": "pnpm --filter @agent-studio/dashboard dev",
"dev:docs": "pnpm --filter @agent-studio/docs dev",
"build": "pnpm -r build"
}
}Consequences
Positive
- Single repository for all code
- Atomic commits across frontend/backend
- Shared CI/CD configuration
- Easy local development
- Types always in sync via OpenAPI
Negative
- Two package managers (uv + pnpm)
- Larger repository size
- CI needs to handle both ecosystems
Neutral
- Clear separation of Python and TypeScript code
- Independent deployment possible
- Shared tooling where applicable (git hooks, CI)