Project Structure of Cordis: Modular Monorepo Architecture Explained
Cordis organizes its codebase as a Yarn workspace monorepo where each feature lives as an independent TypeScript package under packages/, with core providing the central runtime, loader handling dynamic module resolution, and hmr enabling hot-module replacement.
The Cordis project structure follows a strict modular design that separates concerns into discrete, composable units. As implemented in cordiverse/cordis, this monorepo architecture allows developers to import only the functionality they need while maintaining consistent TypeScript configuration across the entire codebase. The repository root houses standard configuration files alongside a packages/ directory containing nine distinct functional modules.
High-Level Repository Layout
The root directory contains standard CI and tooling configuration, while all source code resides within the packages/ workspace.
/ (repo root)
├─ .github/ – CI workflows
├─ .yarnrc.yml – Yarn configuration
├─ .eslintrc.yml – Linting rules
├─ tsconfig*.json – TypeScript build configs
├─ vitest.config.ts – Vitest test runner config
├─ package.json – Workspace definition
└─ packages/
├─ core/ – Core runtime (loader, HMR, plugin API)
├─ loader/ – Dynamic module loader & isolation utilities
├─ hmr/ – Hot‑module‑replacement implementation
├─ logger-console – Console logger implementation
├─ timer/ – Simple timer utility
├─ utils/ – General-purpose utility functions
├─ include/ – Runtime code‑inclusion helpers
├─ group/ – Helpers for grouping plugins
└─ create/ – Project scaffolding (currently empty)
Each package maintains its own tsconfig.json, package.json, and a tests/ folder containing Vitest unit tests.
Core Packages and Responsibilities
Core
The core package provides the central Cordis class that coordinates plugins and exposes the loader and HMR APIs. Located at packages/core/, this module serves as the primary entry point for applications. The main executable is packages/core/bin.js, which initializes the runtime environment.
Loader
The loader package at packages/loader/ implements a configurable module loader supporting isolation, dependency resolution, and hot reloading. The primary interface is packages/loader/src/index.ts, which exports the Loader class responsible for resolving plugin entry points and registering them with the core.
HMR
Located in packages/hmr/, the hot-module-replacement package supplies the logic that allows plugins to be swapped without restarting the host application. This enables development workflows where code changes propagate instantly while preserving application state when possible.
Supporting Utilities
- logger-console: Provides simple console logging via
packages/logger-console/src/browser.tsfor debugging output. - timer: Offers scheduled callback functionality through the
Timerclass. - utils: Contains miscellaneous helpers like
isObjectanddeepCloneinpackages/utils/src/index.ts. - include: Supplies runtime code-inclusion helpers that let plugins inject additional source files.
- group: Utilities for organizing multiple plugins into logical groups, implemented in
packages/group/src/index.ts.
Core Architecture and Data Flow
Understanding the Cordis project structure requires following the initialization sequence across packages:
- Initialization – The host application creates a
Cordisinstance from thecorepackage. - Loading – The
loaderresolves plugin entry points, isolates them in separate contexts, and registers them with the core runtime. - HMR – When plugin files change, the
hmrpackage swaps the old module for the new implementation without restarting the process. - Utilities – Plugins leverage
utils,timer, orlogger-consolefor common tasks without external dependencies.
This modular layout enables tree-shaking and selective imports, allowing production applications to exclude unused functionality.
Navigating Key Source Files
When exploring the Cordis repository, target these critical paths:
- Workspace definition:
package.jsondefines Yarn workspaces and dependency relationships. - Core entry:
packages/core/bin.jsserves as the primary executable. - Loader implementation:
packages/loader/src/index.tscontains the dynamic resolution logic. - HMR engine:
packages/hmr/src/index.tshandles module swapping. - Utility functions:
packages/utils/src/index.tsexports shared helper methods.
Each package follows the convention of placing source code in src/ and corresponding tests in tests/ using the .spec.ts suffix.
Working with the Cordis Project Structure
The following example demonstrates how the packages interact to load plugins dynamically:
import { Cordis } from 'cordis/core';
import { Loader } from 'cordis/loader';
// Create a loader that watches a directory for plugins
const loader = new Loader({
root: './plugins', // folder containing plugin entry files
watch: true, // enable HMR for changes
});
// Initialise Cordis with the loader
const cordis = new Cordis({ loader });
// Load all plugins
await cordis.loadAll();
// Now you can interact with the registered plugins
cordis.plugins.forEach(p => console.log(p.name));
This code imports from cordis/core and cordis/loader, reflecting the package boundaries within the monorepo. The Loader class resolves files from the filesystem while the Cordis instance manages the plugin lifecycle.
Summary
- Cordis uses a Yarn workspace monorepo structure with nine specialized packages under
packages/. - The
corepackage provides the centralCordisclass and plugin coordination APIs viapackages/core/bin.js. loaderandhmrpackages handle dynamic module resolution and hot reloading respectively.- Each package maintains independent TypeScript configuration,
package.json, and Vitest test suites intests/directories. - Supporting packages like
utils,timer, andlogger-consoleprovide isolated utility functions without external dependencies.
Frequently Asked Questions
What is the main entry point for the Cordis core package?
The primary entry point is packages/core/bin.js, which initializes the Cordis runtime and exposes the CLI interface. This file coordinates with the Loader class from packages/loader/src/index.ts to resolve and register plugins.
How does Cordis implement hot module replacement?
The hmr package located at packages/hmr/ contains the hot-module-replacement implementation. It monitors file changes and swaps plugin modules dynamically without requiring a full application restart, preserving state when the implementation allows.
Where are the unit tests located in the Cordis project structure?
Each package contains its own tests/ directory with Vitest unit tests using the .spec.ts extension. For example, loader tests reside in packages/loader/tests/ while utility tests are in packages/utils/tests/.
Which package manages plugin loading and isolation?
The loader package at packages/loader/ handles all dynamic module resolution. Its src/index.ts file exports the Loader class, which creates isolated contexts for plugins, resolves dependencies, and interfaces with the hmr system for reloading.
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 →