Plane is an open-source, AGPL-3.0 project management platform (a Jira/Linear/ClickUp alternative) with a Django/Python API, React Router v7 frontend apps, and a dedicated Hocuspocus/Yjs service for realtime collaborative editing.
- Language
- TypeScript
- Database
- PostgreSQL
- Hosting
- Docker
- License
- AGPL-3.0
- Running for
- 3 years
- Team
- 6-20 people
Why this architecture
Splitting web, admin, space, live, and api into independently buildable pnpm/Turborepo packages, and moving Yjs-based collaborative editing into its own Hocuspocus service, keeps the Django API and Node frontends decoupled while still shipping from a single monorepo.
Tech stack by layer
12 technologies · audited Sep 17, 2026- React Routerapps/web, apps/admin, and apps/space each run react-router dev/build (framework mode), not Next.js.
- Tiptappackages/editor wraps Tiptap extensions (mention, task list, collaboration) into the shared rich text editor.
- MobXapps/web depends on mobx, mobx-react, and mobx-utils for client state instead of Redux or Zustand.
- Djangoapps/api is a Python/Django service; pyproject.toml names the project "Plane" and configures ruff for it.
- Yjsapps/live depends on yjs and y-prosemirror to represent the collaborative Tiptap document as a CRDT.
- Hocuspocusapps/live wires @hocuspocus/server with the database, redis, and logger extensions as the realtime editor backend.
- PostgreSQLplane-db runs postgres:15.7-alpine as the primary datastore for the Django API.
- Valkeyplane-redis runs valkey/valkey:7.2.11-alpine, a Redis-compatible store used for caching and pub/sub.
- RabbitMQplane-mq runs rabbitmq:3.13.6-management-alpine as the task/message broker alongside the Celery-style workers.
- MinIOplane-minio provides S3-compatible object storage for uploads in the self-hosted stack.
- DockerEvery service (web, admin, space, api, worker, beat-worker, migrator, live, proxy) has its own Dockerfile wired through docker-compose.yml.
- Turborepoturbo.json defines the build/dev/check task graph shared by all pnpm workspace packages.
Plane architecture diagram
Open SVGDiagram as text
- Web app (React Router · MobX) → Proxy (apps/proxy): HTTPS
- Space & admin (React Router) → Proxy (apps/proxy): HTTPS
- Proxy (apps/proxy) → API (Django): /api
- Proxy (apps/proxy) → Live (Hocuspocus · Yjs): collab
- API (Django) → PostgreSQL (primary DB): Django ORM
- API (Django) → RabbitMQ (task broker): tasks
- RabbitMQ (task broker) → Workers (worker · beat-worker): consume
- Live (Hocuspocus · Yjs) → Valkey (cache · pub/sub): pub/sub
- API (Django) → MinIO (uploads): uploads
Key architectural decisions
7 decisions- 01
Five deployable apps share one pnpm/Turborepo monorepo
web, admin, space, live, and api sit as separate directories under apps/ with their own package.json (or pyproject.toml for api), coordinated by a root pnpm-workspace.yaml and turbo.json rather than being split into separate repositories.
- 02
Frontend apps use React Router v7 framework mode, not Next.js
apps/web, apps/admin, and apps/space all define "dev": "react-router dev" and "build": "react-router build" in their package.json scripts, with Vite only present as the underlying bundler (vite-tsconfig-paths) rather than driving routing directly.
- 03
Realtime collaborative editing is its own Node service, not part of the Django API
apps/live is a standalone Express/express-ws service that combines @hocuspocus/server, yjs, y-prosemirror, and the shared @plane/editor package to sync Tiptap documents, keeping CRDT and websocket concerns out of apps/api entirely.
- 04
The Python backend is Django, decoupled from the JS workspace
apps/api/pyproject.toml declares the Plane project and its ruff lint config, and apps/api/requirements.txt simply points at requirements/production.txt, so the API dependency chain is managed with pip/requirements files rather than being part of the pnpm workspace.
- 05
Self-hosting ships four separate deployment methods
The deployments/ directory contains aio (all-in-one image), cli, kubernetes, and swarm subfolders in addition to the docker-compose.yml at the repo root, giving operators a choice of install path instead of a single supported method.
- 06
The local/self-hosted stack composes four separate stateful services behind a proxy
docker-compose.yml defines plane-db (Postgres 15.7), plane-redis (Valkey 7.2.11), plane-mq (RabbitMQ 3.13.6 with the management plugin), and plane-minio (S3-compatible storage), all sitting behind a custom proxy container built from apps/proxy.
- 07
Shared UI and domain logic are split into scoped workspace packages
packages/ui, packages/hooks, packages/types, packages/utils, packages/services, packages/constants, packages/i18n, and packages/editor are each independent @plane/* workspace packages consumed by web, admin, and space via workspace:* dependencies rather than duplicated per app.
How Plane is built
How Plane is structured
Plane is organized as a pnpm workspace (pnpm-workspace.yaml) coordinated by Turborepo (turbo.json), with apps/ holding five independently deployable services — web, admin, space, live, and api — and packages/ holding shared, scoped @plane/* libraries (ui, hooks, types, utils, services, constants, i18n, editor, decorators, logger, codemods, shared-state, plus the tailwind-config and typescript-config presets). The root package.json requires Node >=22.22.0 and pins packageManager to pnpm@11.10.0; linting runs through oxlint/oxfmt rather than ESLint/Prettier. apps/api breaks from this JS workspace entirely: it is a Python project with its own pyproject.toml (ruff-configured) and a requirements.txt that simply forwards to requirements/production.txt.
Frontend
apps/web, apps/admin, and apps/space are all React Router v7 apps in framework mode: their package.json scripts run react-router dev and react-router build rather than next dev/next build. State management leans on MobX (mobx, mobx-react, mobx-utils in apps/web/package.json) instead of Redux or a query-cache library, though SWR is also present for data fetching. Styling goes through Tailwind CSS via @tailwindcss/postcss. The rich text editor is a separate workspace package, packages/editor, built on Tiptap (@tiptap/core plus extensions for mentions, task lists, headings, and collaboration) and shared across web and space. Drag-and-drop uses Atlassian's @atlaskit/pragmatic-drag-and-drop family, and PDF export goes through @react-pdf/renderer.
Backend & APIs
apps/api is the Django service: apps/api/pyproject.toml names the project "Plane" (currently version 0.24.0) and configures ruff for linting/formatting with Django-aware per-file ignores (e.g. excluding **/migrations/*). The README's "Built with" section explicitly badges Django alongside React Router and Node.js, corroborating what the manifests show. Background processing is split into three containers built from the same apps/api Dockerfile but with different entrypoints: worker (docker-entrypoint-worker.sh), beat-worker (docker-entrypoint-beat.sh), and a one-shot migrator (docker-entrypoint-migrator.sh), all sharing the same .env file and depending on plane-db and plane-redis.
Data & persistence
docker-compose.yml defines plane-db running postgres:15.7-alpine with max_connections=1000, plane-redis running valkey/valkey:7.2.11-alpine (a Redis-compatible fork, not Redis itself), plane-mq running rabbitmq:3.13.6-management-alpine for the worker/beat-worker queue, and plane-minio running MinIO for S3-compatible file uploads. All four are declared as separate services with named volumes (pgdata, redisdata, uploads, rabbitmq_data), so a full self-hosted deployment runs four stateful containers in addition to the application services.
Realtime / collaboration
Collaborative document editing is isolated in apps/live, a standalone Express service (express, express-ws) that mounts @hocuspocus/server together with its extension-database, extension-logger, and extension-redis add-ons. It shares the @plane/editor package with the frontend apps so both sides speak the same Tiptap schema, and uses yjs and y-prosemirror to convert between Yjs CRDT updates and ProseMirror/Tiptap document state. @effect/platform and effect (Effect-TS) appear in its dependencies for structured async/error handling, and zod validates messages.
Build, test & deploy
CI workflows include pull-request-build-lint-web-apps.yml and pull-request-build-lint-api.yml for per-stack linting, migration-check.yml and i18n-sync-check.yml for Django migrations and translation consistency, codeql.yml for security scanning, copyright-check.yml, and react-doctor.yml for a React health-check tool run via npx react-doctor@latest. apps/live builds with tsdown and tests with vitest; the React Router apps type-check via react-router typegen && tsc --noEmit and lint via oxlint.
Self-hosting notes
Beyond the root docker-compose.yml, deployments/ contains four separate install paths: aio (an all-in-one community image, see deployments/aio/community/Dockerfile), cli, kubernetes, and swarm. A dedicated proxy service, built from apps/proxy with Dockerfile.ce, fronts web, api, space, and admin and exposes the configurable LISTEN_HTTP_PORT/LISTEN_HTTPS_PORT ports, with a note in the compose file that it can be omitted if the operator already runs a reverse proxy.
What to copy (and what not to)
Pulling realtime collaborative editing into its own service (apps/live) that shares only the editor schema package with the frontend, rather than embedding Hocuspocus inside the main API process, is a pattern worth copying for any app that needs CRDT-based collaboration without coupling its scaling characteristics to the primary backend. Running a Django API alongside a pnpm/Turborepo-managed set of React Router frontends works here because the boundary is clean (HTTP/REST, no shared build tooling), but teams without a reason to mix Python and Node should be cautious about adopting that split just for its own sake — it adds two toolchains, two dependency managers, and two sets of CI jobs to maintain.
Sources & repo audit
- Root package.json (pnpm workspace, Turborepo scripts, husky)
- apps/api/pyproject.toml (Django/Python API, ruff config)
- apps/live/package.json (Hocuspocus + Yjs + Tiptap realtime server)
- docker-compose.yml (Postgres, Valkey, RabbitMQ, MinIO, proxy services)
- README.md (Built with: React Router, Django, Node.js badges)
Independent analysis of repository at github.com/makeplane/plane. Spotted an inaccuracy? Use the claim form to request a correction.
Show this stack on your README or website
[](https://stackitfast.com/project/plane)Paste it into your README. It shows your current stack and links to this page.
Scaffold it with your agent
Paste this prompt into Claude Code, Cursor, Windsurf or AGY to start a project with Plane's architecture.
- 1Copy the promptThe full markdown spec, with every layer and decision.
- 2Open your AI toolClaude Code, Cursor, Windsurf or Copilot, in a new repo.
- 3Paste and scaffoldUse it as the first instruction; review before you ship.
# MISSION: Scaffold "Plane" Production Architecture
You are an expert Senior Staff Software Architect and Full-Stack Engineer. Your mission is to scaffold and implement a production-grade, highly reliable, and modular codebase following the proven architecture of **Plane**.
---
## 1. PROJECT SPECIFICATIONS & BENCHMARK
- **Reference Architecture**: Plane
- **What It Does**: Plane is an open-source, AGPL-3.0 project management platform (a Jira/Linear/ClickUp alternative) with a Django/Python API, React Router v7 frontend apps, and a dedicated Hocuspocus/Yjs service for realtime collaborative editing.
- **Domain & Category**: Project Management
- **Production Scale**: 6-20 people
- **Development Mode**: CLASSIC
- **Architectural Rationale**: Splitting web, admin, space, live, and api into independently buildable pnpm/Turborepo packages, and moving Yjs-based collaborative editing into its own Hocuspocus service, keeps the Django API and Node frontends decoupled while still shipping from a single monorepo.
- **Live Website Reference**: https://plane.so
- **Source Repository**: https://github.com/makeplane/plane
---
## 2. PRODUCTION TECH STACK
- **Full Stack Array**: TypeScript, Python, Django, React Router, PostgreSQL, Valkey, RabbitMQ, MinIO, Docker, MobX, Tiptap, Turborepo
- **Primary Language(s)**: TypeScript, Python
- **License of the reference repo**: AGPL-3.0
- **Frontend**: React Router — apps/web, apps/admin, and apps/space each run react-router dev/build (framework mode), not Next.js.; Tiptap — packages/editor wraps Tiptap extensions (mention, task list, collaboration) into the shared rich text editor.; MobX — apps/web depends on mobx, mobx-react, and mobx-utils for client state instead of Redux or Zustand.
- **Backend & APIs**: Django — apps/api is a Python/Django service; pyproject.toml names the project "Plane" and configures ruff for it.; Yjs — apps/live depends on yjs and y-prosemirror to represent the collaborative Tiptap document as a CRDT.; Hocuspocus — apps/live wires @hocuspocus/server with the database, redis, and logger extensions as the realtime editor backend.
- **Data & persistence**: PostgreSQL — plane-db runs postgres:15.7-alpine as the primary datastore for the Django API.; Valkey — plane-redis runs valkey/valkey:7.2.11-alpine, a Redis-compatible store used for caching and pub/sub.
- **Infrastructure & deploy**: RabbitMQ — plane-mq runs rabbitmq:3.13.6-management-alpine as the task/message broker alongside the Celery-style workers.; MinIO — plane-minio provides S3-compatible object storage for uploads in the self-hosted stack.; Docker — Every service (web, admin, space, api, worker, beat-worker, migrator, live, proxy) has its own Dockerfile wired through docker-compose.yml.; Turborepo — turbo.json defines the build/dev/check task graph shared by all pnpm workspace packages.
---
## 3. KEY ARCHITECTURAL DECISIONS (audited from https://github.com/makeplane/plane @ f9ced58)
1. **Five deployable apps share one pnpm/Turborepo monorepo**: web, admin, space, live, and api sit as separate directories under apps/ with their own package.json (or pyproject.toml for api), coordinated by a root pnpm-workspace.yaml and turbo.json rather than being split into separate repositories.
2. **Frontend apps use React Router v7 framework mode, not Next.js**: apps/web, apps/admin, and apps/space all define "dev": "react-router dev" and "build": "react-router build" in their package.json scripts, with Vite only present as the underlying bundler (vite-tsconfig-paths) rather than driving routing directly.
3. **Realtime collaborative editing is its own Node service, not part of the Django API**: apps/live is a standalone Express/express-ws service that combines @hocuspocus/server, yjs, y-prosemirror, and the shared @plane/editor package to sync Tiptap documents, keeping CRDT and websocket concerns out of apps/api entirely.
4. **The Python backend is Django, decoupled from the JS workspace**: apps/api/pyproject.toml declares the Plane project and its ruff lint config, and apps/api/requirements.txt simply points at requirements/production.txt, so the API dependency chain is managed with pip/requirements files rather than being part of the pnpm workspace.
5. **Self-hosting ships four separate deployment methods**: The deployments/ directory contains aio (all-in-one image), cli, kubernetes, and swarm subfolders in addition to the docker-compose.yml at the repo root, giving operators a choice of install path instead of a single supported method.
6. **The local/self-hosted stack composes four separate stateful services behind a proxy**: docker-compose.yml defines plane-db (Postgres 15.7), plane-redis (Valkey 7.2.11), plane-mq (RabbitMQ 3.13.6 with the management plugin), and plane-minio (S3-compatible storage), all sitting behind a custom proxy container built from apps/proxy.
7. **Shared UI and domain logic are split into scoped workspace packages**: packages/ui, packages/hooks, packages/types, packages/utils, packages/services, packages/constants, packages/i18n, and packages/editor are each independent @plane/* workspace packages consumed by web, admin, and space via workspace:* dependencies rather than duplicated per app.
---
## 4. NON-NEGOTIABLE ARCHITECTURAL GUARDRAILS
1. **Monorepo & Modular Separation**:
- Structure as a Turborepo monorepo with strict package boundaries:
- `apps/web`: Application UI, routing, layouts, and server endpoints.
- `packages/ui`: Shared design tokens, CSS variables, and Radix UI primitive components.
- `packages/db`: Database schemas, client singleton, declarative migrations, and seed scripts.
- `packages/config`: Shared TypeScript, ESLint, and build configurations.
2. **Strict Type Safety & Zero `any` Policy**:
- Enable `strict: true`, `noImplicitAny: true`, and `strictNullChecks: true`.
- Validate ALL external inputs, API request bodies, and query parameters with **Zod** schemas before execution.
3. **Frontend & Rendering Guidelines**:
- Isolate interactive UI state to leaf components. Keep core pages lightweight and performant.
4. **Design System & Aesthetics**:
- Keep every color, radius, shadow and font in a single token file (CSS variables) and consume tokens everywhere; never hardcode hex values in components.
- Prefer crisp 1px borders and one subtle shadow scale over blurry default shadows. Pair one sans-serif for body/headings with one monospace for tags, badges, metrics, and code.
5. **Data Layer & Reliability**:
- Write declarative schema definitions with foreign keys, composite indexes on queried filters, and automated timestamp triggers.
- Use connection pooling and prepared statements for serverless database execution.
---
## 5. STEP-BY-STEP SCAFFOLDING ROADMAP
- **Phase 1: Workspace & Root Config**: Initialize package manager, monorepo configuration (`turbo.json`, `tsconfig.base.json`, `package.json`).
- **Phase 2: Database Schema & Client**: Set up the data layer (PostgreSQL, Valkey): client, connection pool, models, and migration scripts.
- **Phase 3: Design Tokens & UI Primitives**: Build accessible `Button`, `Input`, `Card`, `Badge`, and layout wrappers inside `packages/ui`.
- **Phase 4: Core Application Routes & Handlers**: Implement primary authentication, user session handling, and application routes.
- **Phase 5: Quality Assurance & Build Verification**: Run `tsc --noEmit`, ESLint, Prettier, and smoke test suites to ensure zero compilation or runtime errors.
---
## 6. EXECUTION INSTRUCTIONS
1. Review all specifications, architectural guardrails, and stack choices above.
2. Present the full monorepo directory tree structure.
3. Systematically generate the complete, production-ready codebase according to the 5-phase roadmap above — starting with the root workspace setup, followed by the database schema, UI design system package, and full-stack application routes until the repository is fully scaffolded and ready to run.Frequently asked about Plane
What is Plane built with?
A Django/Python REST API (apps/api), React Router v7 frontends for the main app, admin, and space apps, a separate Hocuspocus/Yjs Node service for realtime editing (apps/live), and PostgreSQL, Valkey, RabbitMQ, and MinIO for storage and messaging.
Does Plane use Next.js?
No. apps/web, apps/admin, and apps/space all run React Router v7 in framework mode (react-router dev/build), not Next.js, despite Vite appearing as a devDependency.
Can Plane be self-hosted?
Yes. The repository ships a root docker-compose.yml plus four deployment methods under deployments/: an all-in-one image (aio), a CLI installer, Kubernetes manifests, and a Docker Swarm setup.
How does Plane handle realtime collaborative editing?
A dedicated service, apps/live, runs @hocuspocus/server with its database, redis, and logger extensions, syncing Yjs CRDT documents for the Tiptap-based editor in packages/editor, separate from the Django API.
What database and queue does Plane use?
PostgreSQL 15.7 is the primary datastore and Valkey 7.2.11 (a Redis-compatible fork) handles caching, per the plane-db and plane-redis services in docker-compose.yml. RabbitMQ 3.13.6 backs the worker and beat-worker background job services.
One email a month: new deep dives and stack trends
New source-audited architectures, head-to-head comparisons and the monthly stack report. No spam, unsubscribe anytime.
Similar architectures
- DocumensoAI-agentE-signature SaaS · 2-5 peopleShares TypeScript · React Router · PostgreSQL
- TwentyHybridCRM SaaS · 6-20 peopleShares TypeScript · PostgreSQL · Docker
- ImmichHybridPhoto & Video Management Platform · 6-20 peopleShares TypeScript · Python · PostgreSQL
- FormbricksAI-agentSurvey & Feedback SaaS · 2-5 peopleShares TypeScript · PostgreSQL
- MattermostClassicTeam Collaboration Suite · 20+ peopleShares TypeScript · PostgreSQL · MinIO
- Cal.comClassicScheduling SaaS · 6-20 peopleShares TypeScript · PostgreSQL · Turborepo