mcpField
M
monorepo

monorepo

github.com/epicenterhqDevelopment4.8k79 installsUpdated 2w ago
Repository

About monorepo

A repository skill documenting script conventions, local development workflows, and package setup for the monorepo. It is for contributors who need consistent commands and structure across packages.

Key features

  1. 01Formatting and lint scripts
  2. 02Type checking and test commands
  3. 03Local development script conventions
  4. 04New package setup guidance

Use cases

  1. 01Run checks before CI
  2. 02Start apps from the repository root
  3. 03Create a package in packages/

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/epicenterhq/epicenter --skill monorepo

After installing, type/monorepoin Claude Code to confirm it loaded.

Details

From the project README

Script Commands

The monorepo uses consistent script naming conventions.

Commands

CommandPurposeWhen to use
bun formatFix formatting (biome)Development
bun format:checkCheck formattingCI
bun lintFix lint issues (biome)Development
bun lint:checkCheck lint issuesCI
bun typecheckType checking (tsc, svelte-check, astro check)Both
bun testRun unit tests (*.test.ts only)Both
bun benchRun benchmarks (*.bench.ts; reports, no assertions)Manual

Convention

  • No suffix = fix (modifies files)
  • :check suffix = check only (for CI, no modifications)
  • typecheck alone = type checking (separate concern, cannot auto-fix)
  • test runs only *.test.ts; bench runs only *.bench.ts. A file is one or the other : never both. Benchmarks print reports; tests assert.

Dev Scripts

Start apps from the repo root, not by cd-ing into the app. Root bun dev:<app> runs every process the app needs; for apps that talk to the hosted API (honeycrisp, vocab, whispering, and the api dashboard), it also starts @epicenter/api on localhost:8787 via bun run --filter. Root bun dev:<app>:ui runs the app's frontend alone when that split exists; for Tauri apps, it maps to the package's dev:web. bun dev:api runs just the backend. Local Books, Local Mail, and Super Chat have their own multi-process flows documented in their READMEs; they have no root dev:* target.

Inside a single package, the conventions are:

Non-Tauri apps use a single dev script that runs the underlying tool directly (vite dev, astro dev, wrangler dev). Tauri desktop apps (honeycrisp, whispering, matter) have two dev surfaces and name them explicitly: dev launches the desktop shell (aliasing dev:desktop), and dev:web runs Vite alone, which each app's tauri.conf.json invokes as its beforeDevCommand. The suffix convention applies primarily to database commands:

ScriptMeaning
devThe default local workflow. May still require Infisical login for app secrets (e.g. API keys), but only ever talks to local infrastructure at runtime.
dev:webTauri apps: the Vite dev server alone, no desktop shell. Invoked by tauri.conf.json as beforeDevCommand.
dev:desktopTauri apps: launches the native desktop app (tauri dev). dev aliases this.
db:*:localRuns against local Postgres. Works without Infisical login.
db:*:remoteWraps with infisical run --env=prod. Production data; treat as admin.

There is no dev:remote. Production data is reached only through :remote db scripts and deploy, never through a development server.

After Completing Code Changes

Run type checking to verify:

bun typecheck

This runs bun run --filter '*' typecheck which executes the typecheck script in each package (e.g., tsc --noEmit, svelte-check).

New Package Boilerplate

When creating a new package in packages/, follow this exact structure.

package.json
{
  "name": "@epicenter/<package-name>",
  "version": "0.0.1",
  "exports": {
    ".": "./src/index.ts"
  },
  "license": "AGPL-3.0-or-later",
  "scripts": {
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {},
  "devDependencies": {
    "@types/bun": "catalog:",
    "typescript": "catalog:"
  }
}

Key conventions:

  • exports only, no main/types: modern resolvers ignore main/types when exports is present. The entry point is ./src/index.ts; there is no build step, consumers import the source directly.
  • Use "workspace:*" for internal deps (e.g., "@epicenter/workspace": "workspace:*").
  • Use "catalog:" for shared versions managed in the root package.json catalogs.
  • peerDependencies for packages consumers must also install (e.g., yjs).
  • license: default AGPL-3.0-or-later (everything Epicenter ships or runs). Use MIT only if the package is meant for third-party developers to embed in their own software (the toolkit). See docs/licensing/licensing-strategy.md; bun run check:licenses fails if an MIT package can reach an AGPL one.
tsconfig.json

A leaf config picks a tier and adds nothing that repeats a base. For a Bun library:

{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "types": ["bun"],
    "noUnusedLocals": true,
    "noUnusedParameters": true
  }
}

A Svelte or browser library extends ../../tsconfig.dom.json instead. For all eight leaf tiers, the never-redeclare list, and the module strategy, see the tsconfig skill.

After creating the package, run bun install from the repo root to register it in the workspace.

Comments

Markdown supported