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>
4.8 KiB
4.8 KiB
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
apps/for deployables: Next.js sites, APIs, CLIs - things that get deployedpackages/for libraries: Shared code consumed by apps or other packages- One purpose per package: Each package should do one thing well
- 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/
// 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
// 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.
{
"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.
{
"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.
# 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 systemhusky,lint-staged- Git hooks- Repository-level tooling
Internal Dependencies
Use workspace protocol for internal packages:
// pnpm/bun
{ "@repo/ui": "workspace:*" }
// npm/yarn
{ "@repo/ui": "*" }
Exports Best Practices
Use exports Field (Not main)
{
"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:
// 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
// Good
{ "name": "@repo/ui" }
{ "name": "@acme/utils" }
// Avoid (conflicts with npm registry)
{ "name": "ui" }
{ "name": "utils" }
Common Anti-Patterns
Accessing Files Across Package Boundaries
// 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
// 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 - Detailed repository structure patterns
- packages.md - Creating and managing internal packages
- dependencies.md - Dependency management strategies