Transform hub-guide from a single-skill Hub monorepo guide into a comprehensive programming best-practice plugin covering all situations. Skills (26): - Core: engineering-principles, clean-code, clean-architecture, design-patterns, testing, error-handling, security, api-design, git-workflow, documentation, logging-observability, performance - Languages: typescript, python, rust, go - Frameworks: react-frontend, elysiajs, hono-backend, drizzle-database, nextjs - Infrastructure: docker, ci-cd, monitoring - Monorepo: monorepo, hub-guide (existing) Hooks: - SessionStart: auto-detect project type and activate relevant skills - PreToolUse (Write|Edit): inject language-specific rules per file type Reference files for deep dives: - clean-architecture/references/solid.md (SOLID + component principles) - design-patterns/references/catalog.md (full GoF catalog with examples) - testing/references/mocks.md (test double taxonomy) Restructure plugin to modern skills/ directory format.
4.9 KiB
4.9 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, or whenever the user mentions "monorepo," "workspace," "pnpm workspace," "moon," "turborepo," "nx," "shared package," "dependency management," or "submodule." |
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