- Add principle 27: 'Language-Agnostic Auto-Trigger' to engineering-principles - Remove hardcoded English-only keyword lists from all 26 skill descriptions - Replace with concept-based detection: triggers from code context, project files, and file types regardless of spoken language - Update detect-project.sh hook output with language-agnostic message
4.8 KiB
4.8 KiB
name, description
| name | description |
|---|---|
| monorepo | Monorepo best practices — tooling, workspace configuration, shared dependencies, CI/CD, and dependency management. Use when working in monorepos (pnpm workspaces, moon, turborepo, Nx), managing shared packages. Triggers from project files and configuration, not just keyword matching." |
Monorepo Best Practices
Tool Selection
| Tool | Best For | Why |
|---|---|---|
| pnpm workspaces | Package management | Strict, fast, disk-efficient |
| moon | Monorepo orchestration | Task orchestration + caching |
| turborepo | Task orchestration | Simple caching, good for JS/TS |
| Nx | Full monorepo framework | Generators, dependency graph, affected commands |
| Git submodules | Multi-repo coordination | Separate repos imported together (this repo's pattern) |
Workspace Structure (pnpm + moon)
├── apps/
│ ├── hub/ # Next.js app (submodule)
│ └── scraper/ # Rust API (submodule)
├── packages/ # Shared libraries (when not submodules)
├── infra/ # Shared infra config
├── pnpm-workspace.yaml
├── moon.yml
└── package.json
pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
moon.yml (root)
$schema: 'https://moonrepo.dev/schemas/project.json'
language: 'typescript'
type: 'application'
Shared Dependencies
# Install a shared dependency
pnpm add -w typescript
# Install in a specific package
pnpm add --filter @scope/package zod
# Run in all packages
pnpm -r run build
Rules:
- One version of a dependency across the monorepo — use
pnpm overridesorresolution. - Root
devDependenciesfor shared tooling (TypeScript, Biome, ESLint). - Explicit
dependencies— never rely on hoisting. - Lock file (
pnpm-lock.yaml) committed — immutable installs.
Git Submodules (this repo's pattern)
asepharyana-hub/
├── apps/
│ ├── hub/ → asepharyana/asepharyana-hub-hub
│ └── scraper/ → asepharyana/asepharyana-hub-scraper
Submodule Workflow
# Init after clone
git submodule update --init --recursive
# Update all submodules to latest
git submodule foreach git pull origin main
# Update one submodule
cd apps/hub && git checkout main && git pull
cd ../.. && git add apps/hub && git commit -m "chore(deps): update hub submodule"
git push
State indicators:
(HEAD)— detached at committed pointer (normal state).(main)— on a branch (you've donecd apps/name && git checkout main).- Dirty — uncommitted changes inside submodule.
When to Use Submodules vs Workspaces
| Need | Use |
|---|---|
| Independent repos, separate deploy | Submodules |
| Shared code within one repo | Workspaces |
| Tightly coupled, always deploy together | Workspaces |
| Loosely coupled, different teams | Submodules |
CI/CD for Monorepos
Selective Builds
# Only run relevant workflows based on changed paths
on:
push:
branches: [main]
paths:
- 'apps/hub/**'
- 'infra/docker/hub.Dockerfile'
Affected Commands (Nx/Turborepo/Moon)
moon ci # Runs affected tasks based on changes
npx nx affected:test # Nx style
turbo run build # Turborepo — leverages cache
Caching
- moon/turborepo cache task outputs by file hash + env.
- pnpm caches node_modules.
- Docker layer caching — Registry-based caching for Docker builds.
Shared Configuration
TypeScript
// tsconfig.base.json at root — extended by all packages
{
"compilerOptions": {
"strict": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"moduleResolution": "bundler"
}
}
ESLint / Biome
// biome.json at root — shared config for all packages
{
"formatter": { "indentStyle": "tab", "lineWidth": 120 },
"linter": { "rules": { "recommended": true } }
}
Dependency Management
- Dependabot / Renovate — automate dependency updates.
pnpm dedupe— deduplicate after updates.- Check for duplicates —
pnpm ls -rorpnpm why <package>. - When to upgrade:
- Patch: auto-merge.
- Minor: update weekly.
- Major: scheduled migration, document breaking changes.
Anti-patterns
- ❌ Different dependency versions across packages — inconsistent builds
- ❌ Hoisting assumptions — code works in dev but not in CI because of missing deps
- ❌ Monolithic
package.json— each package declares its own dependencies - ❌ No
.npmrcwithshamefully-hoist=true— defeats pnpm's strictness - ❌ Circular dependencies between packages — extract shared code
- ❌ Every change rebuilds everything — use affected commands and caching
- ❌ Submodule pointer drift — always commit after updating submodules