How the Celeris Web Monorepo Architecture Works with pnpm Workspaces
Celeris Web uses a single-repo monorepo powered by pnpm workspaces to link dozens of interdependent packages via workspace:* specifiers, centralize third-party versions through the catalog: protocol, and orchestrate builds across apps and services with a single pnpm-lock.yaml file.
The Celeris Web project (available at kirklin/celeris-web) organizes its frontend components, utilities, and applications into a scalable monorepo structure. By leveraging pnpm workspaces, the architecture eliminates dependency duplication while enabling atomic updates across shared libraries and consumer applications. This setup allows developers to run the admin UI, mock API, and shared packages simultaneously using a unified command interface.
Workspace Layout and Configuration
The foundation of the Celeris Web monorepo rests in the root pnpm-workspace.yaml file, which defines glob patterns for all workspace packages. This configuration tells pnpm which directories to treat as independent packages while maintaining them within a single dependency graph.
# pnpm-workspace.yaml
packages:
- packages/shared/*
- packages/web/*
- packages/ai/**
- apps/*
- services/*
- scripts
The workspace is divided into logical groups:
packages/shared/*– Common tooling, Vite plugins, and shared TypeScript configurationspackages/web/*– UI components, composables, directives, locale files, and request utilitiespackages/ai/**– Future-proof placeholder for AI-related packagesapps/*– Full-stack applications such as the admin dashboardservices/*– Backend-like services including the mock admin APIscripts– Utility scripts such as the dependency tree generator
The root package.json marks the repository as private to prevent accidental publishing and pins the pnpm version for consistency:
{
"private": true,
"packageManager": "pnpm@10.10.0"
}
Dependency Management with workspace:* and Catalogs
Internal dependencies between workspace packages use the workspace:* version specifier. This protocol instructs pnpm to resolve the package from the local filesystem rather than the npm registry, ensuring that changes in shared code propagate immediately to dependent applications.
In packages/web/components/package.json (and similar packages), internal references follow this pattern:
"dependencies": {
"@celeris/ca-components": "workspace:*",
"@celeris/constants": "workspace:*",
"@celeris/styles": "workspace:*",
"@celeris/utils": "workspace:*"
}
For third-party dependencies, the architecture employs the catalog: protocol. Rather than scattering version numbers across individual package.json files, versions are centralized in the catalog: section of pnpm-workspace.yaml. This ensures that every package uses identical versions of Vue, Vite, Axios, and other shared libraries:
"devDependencies": {
"vue": "catalog:",
"vite": "catalog:"
}
pnpm creates hard-links from each package's node_modules to a central content-addressable store, eliminating duplicate installations of common dependencies across the monorepo.
Monorepo Scripts and Orchestration
The root package.json provides convenience scripts utilizing pnpm's --filter flag to target specific workspaces or run commands across multiple packages. These scripts abstract the complexity of working with multiple interdependent codebases.
| Script | Function | Implementation Detail |
|---|---|---|
pnpm bootstrap |
Installs all dependencies across the monorepo | Equivalent to pnpm install at root |
pnpm dev |
Launches both admin UI and mock API concurrently | Uses run-p to execute filtered commands in parallel |
pnpm dev:admin |
Starts the admin UI development server | pnpm --filter @celeris/admin dev targeting apps/admin |
pnpm dev:mock |
Starts the mock API service | pnpm --filter @celeris/admin-api dev targeting services/admin-api |
pnpm build |
Builds the admin UI for production | pnpm --filter @celeris/admin build |
pnpm clean |
Removes all node_modules and dist directories |
Ensures fresh install across entire workspace |
When packages declare peerDependencies (such as Vue in @celeris/components), pnpm hoists compatible versions to the root node_modules directory, reducing disk usage and ensuring consistent runtime behavior across applications.
Development Workflow
Installing the Entire Monorepo
From the repository root, run:
pnpm bootstrap
# or simply:
pnpm i
pnpm reads the workspace configuration, resolves all workspace:* links to local paths, installs catalog-defined versions of third-party libraries, and generates a single pnpm-lock.yaml file at the root.
Running Development Servers
To start both the frontend application and its corresponding mock API simultaneously:
pnpm dev
This command executes pnpm --filter @celeris/admin dev (launching the Vite dev server for the admin UI) alongside pnpm --filter @celeris/admin-api dev (starting the mock service). Both processes share the same source tree, enabling hot-reload when modifying shared packages like @celeris/utils or @celeris/styles.
Importing Workspace Packages
Any package within the monorepo can import from siblings using standard module resolution:
// Inside apps/admin or packages/web/components
import { formatDate } from '@celeris/utils'
import { Button } from '@celeris/components'
TypeScript resolves these imports through the monorepo's unified node_modules structure without requiring additional path mapping configuration, as the workspace:* protocol ensures proper linking during installation.
Adding a New Package
To extend the monorepo with new functionality:
- Create a directory matching one of the glob patterns in
pnpm-workspace.yaml(e.g.,packages/web/new-feature) - Add a
package.jsonwith"name": "@celeris/new-feature"and declare internal dependencies using"workspace:*" - Run
pnpm ito automatically register the new workspace and update the lockfile
Benefits of the pnpm Workspace Architecture
This architecture delivers several technical advantages for large-scale frontend development:
- Zero-install duplication: Hard-linked content stores reduce disk usage by storing identical dependency versions once regardless of how many packages reference them.
- Consistent versioning: The
catalog:section centralizes third-party version management, whileworkspace:*guarantees internal packages remain synchronized without manual version bumping. - Deterministic CI/CD: A single lockfile ensures reproducible builds across development and production environments.
- Scalable code sharing: Shared utilities (
@celeris/utils), UI component libraries (@celeris/components), and build tooling (@celeris/vite) can be consumed by any application without publishing to npm or managing complex relative imports. - Atomic upgrades: Updating a dependency version in the catalog or modifying a shared utility immediately propagates to all dependents after a single install command.
Summary
- The Celeris Web monorepo is defined by
pnpm-workspace.yaml, which groups packages intoapps/,packages/,services/, andscripts/directories. - Internal dependencies use the
workspace:*protocol to link local packages, while thecatalog:protocol centralizes third-party version management. - Root scripts utilize
pnpm --filterto run commands against specific workspaces, enabling commands likepnpm devto orchestrate multiple services simultaneously. - pnpm's content-addressable store eliminates duplicate dependencies through hard-linking, significantly reducing disk usage compared to traditional node_modules structures.
- The architecture supports hot-reloading across package boundaries, allowing changes in shared libraries to immediately reflect in consuming applications without rebuilds or republishing.
Frequently Asked Questions
What is the purpose of the workspace:* prefix in package.json files?
The workspace:* prefix tells pnpm to resolve the dependency from the local monorepo rather than fetching it from the npm registry. In Celeris Web, this ensures that when @celeris/components imports from @celeris/utils, it always uses the current source code from the repository rather than a potentially outdated published version, enabling real-time development across package boundaries.
How does the catalog: protocol manage dependency versions?
The catalog: protocol references versions defined in the catalog: section of the root pnpm-workspace.yaml file. Instead of specifying "vue": "^3.4.0" in every package that requires Vue, developers write "vue": "catalog:", and pnpm substitutes the version defined centrally. This guarantees that all packages use identical versions of shared frameworks and libraries, preventing version drift and conflicting peer dependencies.
How do I add a new package to the Celeris Web monorepo?
Create a new directory under one of the glob patterns defined in pnpm-workspace.yaml (such as packages/web/new-tool/), add a package.json with a scoped name like "@celeris/new-tool", and declare any internal dependencies using "workspace:*". Running pnpm i from the root automatically detects the new workspace, links it into the monorepo's dependency graph, and makes it available for filtering via pnpm --filter @celeris/new-tool.
What is the difference between apps/* and packages/* in this architecture?
The apps/* directory (such as apps/admin) contains deployable applications with entry points, build configurations, and environment-specific code. The packages/* directory contains library code—reusable components, utilities, and tooling—that multiple applications import. While both are valid workspaces, applications typically depend on many packages, whereas packages should remain agnostic of specific application implementations to maintain proper separation of concerns.
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 →