# Project Structure of Cordis: Modular Monorepo Architecture Explained

> Explore the Cordis project structure, a modular monorepo architecture. Discover how independent TypeScript packages organize features, with core runtime, dynamic loading, and HMR.

- Repository: [Cordiverse/cordis](https://github.com/cordiverse/cordis)
- Tags: architecture
- Published: 2026-09-13

---

**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](https://github.com/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`](https://github.com/cordiverse/cordis/blob/main/tsconfig.json), [`package.json`](https://github.com/cordiverse/cordis/blob/main/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`](https://github.com/cordiverse/cordis/blob/main/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`](https://github.com/cordiverse/cordis/blob/main/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.ts`](https://github.com/cordiverse/cordis/blob/main/packages/logger-console/src/browser.ts) for debugging output.
- **timer**: Offers scheduled callback functionality through the `Timer` class.
- **utils**: Contains miscellaneous helpers like `isObject` and `deepClone` in [`packages/utils/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/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`](https://github.com/cordiverse/cordis/blob/main/packages/group/src/index.ts).

## Core Architecture and Data Flow

Understanding the Cordis project structure requires following the initialization sequence across packages:

1. **Initialization** – The host application creates a `Cordis` instance from the `core` package.
2. **Loading** – The `loader` resolves plugin entry points, isolates them in separate contexts, and registers them with the core runtime.
3. **HMR** – When plugin files change, the `hmr` package swaps the old module for the new implementation without restarting the process.
4. **Utilities** – Plugins leverage `utils`, `timer`, or `logger-console` for 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.json`](https://github.com/cordiverse/cordis/blob/main/package.json) defines Yarn workspaces and dependency relationships.
- **Core entry**: [`packages/core/bin.js`](https://github.com/cordiverse/cordis/blob/main/packages/core/bin.js) serves as the primary executable.
- **Loader implementation**: [`packages/loader/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/loader/src/index.ts) contains the dynamic resolution logic.
- **HMR engine**: [`packages/hmr/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/hmr/src/index.ts) handles module swapping.
- **Utility functions**: [`packages/utils/src/index.ts`](https://github.com/cordiverse/cordis/blob/main/packages/utils/src/index.ts) exports shared helper methods.

Each package follows the convention of placing source code in `src/` and corresponding tests in `tests/` using the [`.spec.ts`](https://github.com/cordiverse/cordis/blob/main/.spec.ts) suffix.

## Working with the Cordis Project Structure

The following example demonstrates how the packages interact to load plugins dynamically:

```typescript
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 **`core`** package provides the central `Cordis` class and plugin coordination APIs via [`packages/core/bin.js`](https://github.com/cordiverse/cordis/blob/main/packages/core/bin.js).
- **`loader`** and **`hmr`** packages handle dynamic module resolution and hot reloading respectively.
- Each package maintains independent **TypeScript** configuration, [`package.json`](https://github.com/cordiverse/cordis/blob/main/package.json), and **Vitest** test suites in `tests/` directories.
- Supporting packages like **`utils`**, **`timer`**, and **`logger-console`** provide 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`](https://github.com/cordiverse/cordis/blob/main/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`](https://github.com/cordiverse/cordis/blob/main/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`](https://github.com/cordiverse/cordis/blob/main/.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`](https://github.com/cordiverse/cordis/blob/main/src/index.ts) file exports the `Loader` class, which creates isolated contexts for plugins, resolves dependencies, and interfaces with the `hmr` system for reloading.