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
orderWorkspacesListfunction inpackages/utils/src/workspace.tsprovides 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.jsonto 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 acrossapps/*. - pnpm workspaces defined in
pnpm‑workspace.yamlenable automatic linking and dependency management for all@plane/*scoped packages. - Domain‑driven packages like
@plane/utils,@plane/ui, and@plane/shared-stateisolate 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →