Skip to content

Code Architecture

An overview of the EreoJS monorepo structure, package relationships, and build conventions.

Monorepo Overview

EreoJS is a monorepo with 25 packages managed by Bun workspaces. Each package is published to npm under the @ereo scope. The repository uses:

  • Package manager: Bun (workspace:* for internal dependencies)
  • Module format: ESM only ("type": "module" in every package)
  • Language: TypeScript throughout
  • Current version: 0.1.24

Core Dependency Graph

Packages build on each other in a layered architecture. Lower layers have no knowledge of higher layers:

@ereo/state          (no deps — standalone signal library)
    |
@ereo/core           (app foundation, plugins, environment, caching)
    |
@ereo/router         (file-based routing, middleware, validation)
    |
@ereo/data           (loaders, actions, caching, revalidation)
    |
@ereo/client         (React hooks, Link, Form, navigation, islands)
    |
@ereo/server         (Bun HTTP server, streaming SSR, middleware runner)
    |
@ereo/cli            (dev, build, start commands)

Additional packages extend the core:

@ereo/forms          (depends on @ereo/state, @ereo/client)
@ereo/bundler        (depends on @ereo/core)
@ereo/plugin-auth    (depends on @ereo/core, @ereo/server)
@ereo/plugin-images  (depends on @ereo/core, @ereo/server)
@ereo/plugin-tailwind (depends on @ereo/core, @ereo/bundler)

Package Conventions

Every package follows the same structure:

packages/example/
  src/
    index.ts           # Public API exports
    ...                # Implementation files
    __tests__/         # Test files
  dist/
    index.js           # Built JavaScript (ESM)
    index.d.ts         # TypeScript declarations
  package.json
  tsconfig.json

package.json

json
{
  "name": "@ereo/example",
  "version": "0.1.24",
  "type": "module",
  "main": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  },
  "scripts": {
    "build": "bun build ./src/index.ts --outdir ./dist --target browser --external ...",
    "build:types": "tsc --emitDeclarationOnly",
    "test": "bun test",
    "typecheck": "tsc --noEmit"
  }
}

tsconfig.json

Each package extends the root tsconfig.json and configures path aliases to reference sibling package type declarations:

json
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist",
    "paths": {
      "@ereo/core": ["../core/dist/index.d.ts"],
      "@ereo/state": ["../state/dist/index.d.ts"]
    }
  },
  "include": ["src"]
}

Build Order

Packages must be built in dependency order. The build script handles this automatically, but if building manually:

  1. @ereo/state (no dependencies)
  2. @ereo/core
  3. @ereo/router
  4. @ereo/data
  5. @ereo/client
  6. @ereo/server
  7. @ereo/forms, @ereo/bundler (parallel, depend only on earlier packages)
  8. @ereo/cli, plugins (depend on multiple earlier packages)

Key Design Patterns

Signal-Based State

@ereo/state provides the Signal<T> primitive used throughout the framework:

ts
const count = signal(0)
count.get()            // 0
count.set(5)
count.subscribe(v => console.log(v))

React integration via useSyncExternalStore:

ts
const value = useSignal(mySignal) // Re-renders when signal changes

Request/Response Model

The server layer uses standard Web API Request and Response objects. Middleware, loaders, and actions all operate on these standard types, avoiding framework-specific abstractions.

Plugin Architecture

Plugins hook into the application lifecycle via ereo.config.ts:

ts
export default defineConfig({
  plugins: [
    tailwindPlugin(),
    authPlugin({ provider: 'github' }),
  ],
})

Plugins can add middleware, modify the build pipeline, register virtual modules, and extend the development server. See the Plugin Development guide for the full API.

Islands Architecture

Components marked with .island.tsx extension or 'use client' directive are hydrated on the client. Everything else renders as static HTML on the server. This minimizes client-side JavaScript while allowing interactivity where needed.

Where to Find Things

WhatWhere
Route resolution logicpackages/router/src/
Loader/action executionpackages/data/src/
React hooks (useLoaderData, etc.)packages/client/src/hooks/
Island hydrationpackages/client/src/islands/
HTTP serverpackages/server/src/
CLI commandspackages/cli/src/commands/
Form validation enginepackages/forms/src/
Signal implementationpackages/state/src/
Cache systempackages/core/src/cache/

Released under the MIT License.