# Understanding the `packages/` Directory in the Plane Monorepo

> Discover the purpose of the packages/ directory in the Plane monorepo. Learn how it manages shared code libraries with pnpm workspaces for efficient development.

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

---

**The `packages/` directory houses self‑contained, version‑controlled libraries that share code across Plane’s applications using scoped `@plane/*` imports managed by pnpm workspaces.**

The `packages/` folder serves as the architectural backbone of [Plane](https://github.com/makeplane/plane), an open‑source project management platform. This directory contains reusable libraries that power the web frontend, admin dashboards, and API services through a modular, type‑safe monorepo structure. Understanding how the Plane monorepo organizes its `packages/` directory is essential for contributors extending functionality or consuming shared components.

## Architectural Purpose of the Packages Directory

The `packages/` directory implements a **library layer** that isolates shared business logic, UI components, and infrastructure utilities from runnable applications. Located at the repository root alongside `apps/`, this folder contains standalone npm packages that compile to `dist/` directories for distribution. Each package operates under the `@plane` npm scope, enabling clean imports like `@plane/utils` or `@plane/ui` without code duplication across services.

## Workspace Configuration with pnpm

Plane leverages **pnpm workspaces** to manage cross‑package dependencies and linking. The `pnpm‑workspace.yaml` file at the repository root defines the glob pattern `packages/*`, treating every subdirectory as a distinct workspace entry. This configuration enables single‑install dependency hoisting and automatic cross‑package linking via `workspace:*` protocol references in [`package.json`](https://github.com/makeplane/plane/blob/main/package.json) files.

### Scoped Package Imports

During development, pnpm resolves `@plane/*` imports to local source directories, while production builds reference compiled bundles. For example, importing from `@plane/utils` resolves to `packages/utils/src/` in development and `packages/utils/dist/` after building.

## Domain Separation and Package Structure

The `packages/` directory organizes code by technical concern rather than by feature. Key packages include:

- **@plane/utils**: Generic helper functions for data transformation and validation. The `orderWorkspacesList` function in [`packages/utils/src/workspace.ts`](https://github.com/makeplane/plane/blob/main/packages/utils/src/workspace.ts) provides workspace sorting logic consumed by multiple frontend applications.
- **@plane/ui**: Reusable React components compiled with TypeScript. This package declares React as a peer dependency in [`packages/ui/package.json`](https://github.com/makeplane/plane/blob/main/packages/ui/package.json) to ensure compatible versions across consuming apps.
- **@plane/shared-state**: MobX stores for global state management, providing consistent state patterns across the web and admin interfaces.
- **@plane/hooks**: Custom React hooks for shared logic like data fetching and form handling.
- **@plane/logger**: Request‑logging middleware used by API services.
- **@plane/constants**: Static values including workspace themes and view definitions referenced throughout the codebase.

## Practical Usage Examples

### Consuming Utility Functions

Import workspace utilities directly from the `@plane/utils` scope:

```typescript
import { orderWorkspacesList } from '@plane/utils';
import type { IWorkspace } from '@plane/types';

const workspaces: IWorkspace[] = [
  { id: '2', name: 'Beta' },
  { id: '1', name: 'Alpha' },
];

// Sorts alphabetically by name using the implementation in packages/utils/src/workspace.ts
const sorted = orderWorkspacesList(workspaces);
console.log(sorted);
// → [{ id: '1', name: 'Alpha' }, { id: '2', name: 'Beta' }]

```

### Rendering Shared UI Components

Import React components from the centralized UI library:

```tsx
import { Button } from '@plane/ui';

function SaveButton({ onClick }: { onClick: () => void }) {
  return <Button variant="primary" onClick={onClick}>Save</Button>;
}

```

## Type Safety and Build Configuration

Each package inherits compiler settings from a root `typescript‑config` package while maintaining individual [`tsconfig.json`](https://github.com/makeplane/plane/blob/main/tsconfig.json) files for specific build targets. This inheritance model guarantees consistent type definitions across the monorepo while allowing package‑specific optimizations.

Build scripts defined in individual [`package.json`](https://github.com/makeplane/plane/blob/main/package.json) files (such as `build`, `dev`, and `storybook` for UI components) output to local `dist/` directories. The compiled artifacts support both CommonJS and ES Module formats for maximum compatibility.

## Summary

- The `packages/` directory in Plane functions as a **library layer** containing version‑controlled packages shared across `apps/*`.
- **pnpm workspaces** defined in `pnpm‑workspace.yaml` enable automatic linking and dependency management for all `@plane/*` scoped packages.
- **Domain‑driven packages** like `@plane/utils`, `@plane/ui`, and `@plane/shared-state` isolate technical concerns for better maintainability.
- **TypeScript configurations** are shared across packages to ensure consistent type safety and compilation standards.
- **Build outputs** in `dist/` directories allow independent package development while supporting integrated application builds.

## Frequently Asked Questions

### How do I add a new package to the Plane monorepo?

Create a new folder under `packages/` with a [`package.json`](https://github.com/makeplane/plane/blob/main/package.json) declaring the name as `@plane/[package‑name]` and specifying appropriate dependencies. Ensure the package follows the existing TypeScript configuration pattern, then reference it from applications using `workspace:*` in the consumer’s [`package.json`](https://github.com/makeplane/plane/blob/main/package.json). The existing `packages/*` glob in `pnpm‑workspace.yaml` automatically includes new directories.

### What distinguishes packages from apps in the Plane repository?

The `packages/` directory contains **library code** intended for import and reuse, while the `apps/` directory contains **runnable applications** like the web frontend or API server. Packages export functions and components, whereas apps define entry points, routing, and deployment configurations. This separation ensures that business logic remains testable and framework‑agnostic.

### How does pnpm resolve `@plane/*` imports during development?

pnpm treats each folder in `packages/` as a workspace, creating symbolic links that resolve `@plane/utils` to `packages/utils/src/` during local development. After running `pnpm build`, imports resolve to the compiled `packages/utils/dist/` directory. This resolution strategy ensures consistent behavior between development and production environments without manual path aliasing.

### Why does Plane use a monorepo structure instead of separate repositories?

The monorepo approach enables **atomic changes** across multiple packages and applications, ensures version consistency between shared libraries and consumers, and simplifies the contribution workflow. As demonstrated in the `packages/` directory structure, this model supports scalable development where new packages can be added without altering existing application code or managing cross‑repository versioning.