Understanding the `packages/` Directory in the Plane Monorepo

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, 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 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 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 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:

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:

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 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 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 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →