# Plane Project Monorepo Structure: A Deep Dive into the pnpm and Turbo Architecture

> Explore the Plane project monorepo structure. Discover how pnpm and TurboRepo efficiently manage frontend apps, backend services, and shared TypeScript libraries in one repository.

- Repository: [Plane/plane](https://github.com/makeplane/plane)
- Tags: deep-dive
- Published: 2026-08-22

---

**Plane uses a pnpm-managed monorepo that consolidates frontend applications, backend services, and shared TypeScript libraries under a single repository coordinated by TurboRepo.**

The makeplane/plane repository organizes a complex product ecosystem—including the main web UI, admin panels, real-time collaboration servers, and reusable utility libraries—into a unified workspace. Understanding this Plane project monorepo structure helps developers navigate the codebase, run cross-application builds, and contribute new features efficiently.

## Workspace Configuration and Root Setup

The monorepo's foundation is defined in **[`pnpm-workspace.yaml`](https://github.com/makeplane/plane/blob/main/pnpm-workspace.yaml)** at the repository root. This file instructs pnpm which directories to include in the workspace while explicitly excluding certain backend services that ship as Docker containers.

```yaml

# https://github.com/makeplane/plane/blob/preview/pnpm-workspace.yaml

packages:
  - apps/*          # All UI apps (web, admin, space, live, etc.)

  - packages/*      # Shared TypeScript libraries (utils, logger, i18n, etc.)

  - "!apps/api"     # API server is built separately (Docker image)

  - "!apps/proxy"   # Proxy service is also excluded

```

The root directory also houses global configuration files including [`package.json`](https://github.com/makeplane/plane/blob/main/package.json) with workspace-wide scripts, [`turbo.json`](https://github.com/makeplane/plane/blob/main/turbo.json) for task orchestration, and shared linting configurations. These files ensure consistent tooling standards across all workspace members while allowing individual apps to customize their specific build pipelines.

## Apps Directory: The Application Layer

The **`apps/`** folder contains standalone, runnable applications that represent the various user-facing and service components of Plane. Each application maintains its own build configuration, dependencies, and deployment strategy.

### Web Application

The primary user interface lives in **`apps/web/`** and is built with Vite. It uses `@react-router/dev/vite` for the development server and `vite-tsconfig-paths` to resolve TypeScript path aliases relative to its local [`tsconfig.json`](https://github.com/makeplane/plane/blob/main/tsconfig.json).

```typescript
// https://github.com/makeplane/plane/blob/preview/apps/web/vite.config.ts
import { defineConfig } from "vite";
import { reactRouter } from "@react-router/dev/vite";
import tsconfigPaths from "vite-tsconfig-paths";
import path from "path";

export default defineConfig(() => ({
  plugins: [
    reactRouter(), 
    tsconfigPaths({ projects: [path.resolve(__dirname, "tsconfig.json")] })
  ],
  // …
}));

```

### Admin and Space Interfaces

- **Admin UI** (`apps/admin/`): Provides administrative controls with its own Vite configuration and MobX state management stores located in `apps/admin/store/`
- **Space UI** (`apps/space/`): Handles workspace-specific functionality as a separate deployable unit

### Live Collaboration Service

The **`apps/live/`** directory contains a Node.js-based real-time server that handles WebSocket connections for collaborative features. Unlike the frontend apps, this service runs its own TypeScript build process and test suite independently.

### Excluded Services

Both **`apps/api`** and **`apps/proxy`** are excluded from the JavaScript workspace because they are designed to run as containerized services with their own dependency management and build lifecycles.

## Packages Directory: Shared Libraries

The **`packages/`** directory houses reusable TypeScript libraries consumed by multiple applications. These modules enforce the **Don't Repeat Yourself (DRY)** principle across the Plane project monorepo structure.

### Core Shared Modules

- **`packages/utils/`**: Generic helpers for workspace handling, date manipulation, and data transformation
- **`packages/logger/`**: Express middleware used by both frontend and backend services, exported from [`packages/logger/src/middleware.ts`](https://github.com/makeplane/plane/blob/main/packages/logger/src/middleware.ts)
- **`packages/i18n/`**: Centralized internationalization containing locale JSON files (such as [`packages/i18n/src/locales/zh-CN/workspace.json`](https://github.com/makeplane/plane/blob/main/packages/i18n/src/locales/zh-CN/workspace.json)) and translation utilities
- **`packages/hooks/`**: Shared React hooks for data fetching and state synchronization
- **`packages/editor/`**: Rich text editing components and utilities
- **`packages/decorators/`**: TypeScript decorators for cross-cutting concerns

### Cross-Cutting Logger Example

The logger package demonstrates how shared infrastructure code bridges frontend and backend concerns:

```typescript
// https://github.com/makeplane/plane/blob/preview/packages/logger/src/middleware.ts
import { Request, Response, NextFunction } from "express";

export function requestLogger(req: Request, res: Response, next: NextFunction) {
  console.log(`${req.method} ${req.path}`);
  next();
}

```

## Build Orchestration with TurboRepo

Plane leverages **TurboRepo** to execute tasks across the workspace in parallel while respecting dependency graphs. The root [`package.json`](https://github.com/makeplane/plane/blob/main/package.json) defines high-level orchestration scripts that delegate to individual package scripts.

```json
// https://github.com/makeplane/plane/blob/preview/package.json
{
  "scripts": {
    "dev": "turbo run dev --concurrency=18",
    "build": "turbo run build",
    "check": "turbo run check",
    "fix": "turbo run fix"
  }
}

```

Running `pnpm dev` initiates development servers for all workspace applications simultaneously—typically binding `web` to port 3000, `admin` to port 3001, and others—while watching for changes in shared `packages/*` dependencies. The `--concurrency=18` flag ensures adequate parallel process allocation for the workspace size.

Linting, type-checking, and code formatting are similarly coordinated through Turbo. The `pnpm check` command runs validation across every package, while `pnpm fix` applies automated corrections using tools like oxlint throughout the repository.

## Working with the Monorepo

### Adding New Workspace Members

To extend the Plane project monorepo structure with new functionality:

1. Create a directory under `apps/` (for applications) or `packages/` (for libraries)
2. Initialize a [`package.json`](https://github.com/makeplane/plane/blob/main/package.json) with a unique scoped name (e.g., `"@plane/new-lib"`)
3. Reference workspace dependencies using the **`workspace:*`** protocol
4. Execute `pnpm install` to generate symlinks automatically

### Importing Workspace Dependencies

Applications consume shared libraries via the workspace protocol, ensuring they always receive the local version during development:

```typescript
// apps/web/src/components/example.tsx
import { formatDate } from "@plane/utils";

export const Example = () => <div>{formatDate(new Date())}</div>;

```

### Targeted Script Execution

Developers can run commands for specific packages without navigating to their directories:

```bash

# Build only the admin UI

pnpm --filter @plane/admin run build

# Run type checking on the logger package only

pnpm --filter @plane/logger run check

```

## Summary

- **pnpm workspaces** define the monorepo boundaries in [`pnpm-workspace.yaml`](https://github.com/makeplane/plane/blob/main/pnpm-workspace.yaml), including the `apps/*` and `packages/*` glob patterns while excluding containerized services like `apps/api`
- **Application isolation** allows `web`, `admin`, `space`, and `live` to maintain independent Vite or Node.js build configurations while sharing code
- **Library reusability** is enforced through `packages/*` modules including `utils`, `logger`, `i18n`, and `hooks` that export TypeScript code consumed via the `workspace:*` protocol
- **TurboRepo orchestration** provides parallel execution of `dev`, `build`, `check`, and `fix` commands across the entire graph with intelligent caching
- **Developer ergonomics** support filtering commands to specific packages and automatic symlink management when adding new workspace members

## Frequently Asked Questions

### How does Plane handle dependency management between apps and packages?

Plane uses pnpm's workspace protocol to link packages internally. When an app like `web` depends on `@plane/utils`, it specifies `"@plane/utils": "workspace:*"` in its [`package.json`](https://github.com/makeplane/plane/blob/main/package.json). During `pnpm install`, pnpm creates symlinks pointing to the local `packages/utils` directory, ensuring changes to shared code immediately reflect across consuming applications without publishing to npm.

### Why are the API and Proxy services excluded from the pnpm workspace?

The `apps/api` and `apps/proxy` directories are excluded via the `!apps/api` and `!apps/proxy` patterns in [`pnpm-workspace.yaml`](https://github.com/makeplane/plane/blob/main/pnpm-workspace.yaml) because they are designed to run as containerized services with distinct runtime environments. These services manage their own dependencies and build processes within Docker images, separate from the JavaScript/TypeScript toolchain that powers the frontend applications and shared libraries.

### What is the purpose of the `live` application in the monorepo?

The `apps/live/` directory contains a Node.js real-time collaboration server that handles WebSocket connections for live editing and synchronization features. Unlike the static frontend applications built with Vite, this service requires a persistent Node process and is developed as a first-class workspace member, allowing it to import shared utilities like `@plane/logger` while maintaining its own TypeScript compilation and testing pipeline.

### How can I run development servers for specific applications only?

Use pnpm's filter flag combined with Turbo to target specific workspace members. For example, `pnpm --filter @plane/web run dev` starts only the web application, while `pnpm --filter @plane/web --filter @plane/admin run dev` starts both the web and admin interfaces simultaneously. This approach conserves system resources when you only need to work on a subset of the Plane project monorepo structure.