Files
agent-skills/skills/turborepo/references/best-practices/RULE.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06:00

242 lines
4.8 KiB
Markdown

# Monorepo Best Practices
Essential patterns for structuring and maintaining a healthy Turborepo monorepo.
## Repository Structure
### Standard Layout
```
my-monorepo/
├── apps/ # Application packages (deployable)
│ ├── web/
│ ├── docs/
│ └── api/
├── packages/ # Library packages (shared code)
│ ├── ui/
│ ├── utils/
│ └── config-*/ # Shared configs (eslint, typescript, etc.)
├── package.json # Root package.json (minimal deps)
├── turbo.json # Turborepo configuration
├── pnpm-workspace.yaml # (pnpm) or workspaces in package.json
└── pnpm-lock.yaml # Lockfile (required)
```
### Key Principles
1. **`apps/` for deployables**: Next.js sites, APIs, CLIs - things that get deployed
2. **`packages/` for libraries**: Shared code consumed by apps or other packages
3. **One purpose per package**: Each package should do one thing well
4. **No nested packages**: Don't put packages inside packages
## Package Types
### Application Packages (`apps/`)
- **Deployable**: These are the "endpoints" of your package graph
- **Not installed by other packages**: Apps shouldn't be dependencies of other packages
- **No shared code**: If code needs sharing, extract to `packages/`
```json
// apps/web/package.json
{
"name": "web",
"private": true,
"dependencies": {
"@repo/ui": "workspace:*",
"next": "latest"
}
}
```
### Library Packages (`packages/`)
- **Shared code**: Utilities, components, configs
- **Namespaced names**: Use `@repo/` or `@yourorg/` prefix
- **Clear exports**: Define what the package exposes
```json
// packages/ui/package.json
{
"name": "@repo/ui",
"exports": {
"./button": "./src/button.tsx",
"./card": "./src/card.tsx"
}
}
```
## Package Compilation Strategies
### Just-in-Time (Simplest)
Export TypeScript directly; let the app's bundler compile it.
```json
{
"name": "@repo/ui",
"exports": {
"./button": "./src/button.tsx"
}
}
```
**Pros**: Zero build config, instant changes
**Cons**: Can't cache builds, requires app bundler support
### Compiled (Recommended for Libraries)
Package compiles itself with `tsc` or bundler.
```json
{
"name": "@repo/ui",
"exports": {
"./button": {
"types": "./src/button.tsx",
"default": "./dist/button.js"
}
},
"scripts": {
"build": "tsc"
}
}
```
**Pros**: Cacheable by Turborepo, works everywhere
**Cons**: More configuration
## Dependency Management
### Install Where Used
Install dependencies in the package that uses them, not the root.
```bash
# Good: Install in the package that needs it
pnpm add lodash --filter=@repo/utils
# Avoid: Installing everything at root
pnpm add lodash -w # Only for repo-level tools
```
### Root Dependencies
Only these belong in root `package.json`:
- `turbo` - The build system
- `husky`, `lint-staged` - Git hooks
- Repository-level tooling
### Internal Dependencies
Use workspace protocol for internal packages:
```json
// pnpm/bun
{ "@repo/ui": "workspace:*" }
// npm/yarn
{ "@repo/ui": "*" }
```
## Exports Best Practices
### Use `exports` Field (Not `main`)
```json
{
"exports": {
".": "./src/index.ts",
"./button": "./src/button.tsx",
"./utils": "./src/utils.ts"
}
}
```
### Avoid Barrel Files
Don't create `index.ts` files that re-export everything:
```typescript
// BAD: packages/ui/src/index.ts
export * from './button';
export * from './card';
export * from './modal';
// ... imports everything even if you need one thing
// GOOD: Direct exports in package.json
{
"exports": {
"./button": "./src/button.tsx",
"./card": "./src/card.tsx"
}
}
```
### Namespace Your Packages
```json
// Good
{ "name": "@repo/ui" }
{ "name": "@acme/utils" }
// Avoid (conflicts with npm registry)
{ "name": "ui" }
{ "name": "utils" }
```
## Common Anti-Patterns
### Accessing Files Across Package Boundaries
```typescript
// BAD: Reaching into another package
import { Button } from '../../packages/ui/src/button';
// GOOD: Install and import properly
import { Button } from '@repo/ui/button';
```
### Shared Code in Apps
```
// BAD
apps/
web/
shared/ # This should be a package!
utils.ts
// GOOD
packages/
utils/ # Proper shared package
src/utils.ts
```
### Too Many Root Dependencies
```json
// BAD: Root has app dependencies
{
"dependencies": {
"react": "^18",
"next": "^14",
"lodash": "^4"
}
}
// GOOD: Root only has repo tools
{
"devDependencies": {
"turbo": "latest",
"husky": "latest"
}
}
```
## See Also
- [structure.md](./structure.md) - Detailed repository structure patterns
- [packages.md](./packages.md) - Creating and managing internal packages
- [dependencies.md](./dependencies.md) - Dependency management strategies