Files
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

4.9 KiB

Repository Structure

Detailed guidance on structuring a Turborepo monorepo.

Workspace Configuration

# pnpm-workspace.yaml
packages:
  - "apps/*"
  - "packages/*"

npm/yarn/bun

// package.json
{
  "workspaces": ["apps/*", "packages/*"]
}

Root package.json

{
  "name": "my-monorepo",
  "private": true,
  "packageManager": "pnpm@9.0.0",
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint",
    "test": "turbo run test"
  },
  "devDependencies": {
    "turbo": "latest"
  }
}

Key points:

  • private: true - Prevents accidental publishing
  • packageManager - Enforces consistent package manager version
  • Scripts only delegate to turbo run - No actual build logic here!
  • Minimal devDependencies (just turbo and repo tools)

Always Prefer Package Tasks

Always use package tasks. Only use Root Tasks if you cannot succeed with package tasks.

// packages/web/package.json
{
  "scripts": {
    "build": "next build",
    "lint": "eslint .",
    "test": "vitest",
    "typecheck": "tsc --noEmit"
  }
}

// packages/api/package.json
{
  "scripts": {
    "build": "tsc",
    "lint": "eslint .",
    "test": "vitest",
    "typecheck": "tsc --noEmit"
  }
}

Package tasks enable Turborepo to:

  1. Parallelize - Run web#lint and api#lint simultaneously
  2. Cache individually - Each package's task output is cached separately
  3. Filter precisely - Run turbo run test --filter=web for just one package

Root Tasks are a fallback for tasks that truly cannot run per-package:

// AVOID unless necessary - sequential, not parallelized, can't filter
{
  "scripts": {
    "lint": "eslint apps/web && eslint apps/api && eslint packages/ui"
  }
}

Root turbo.json

{
  "$schema": "https://turborepo.dev/schema.v2.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"]
    },
    "lint": {},
    "test": {
      "dependsOn": ["build"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

Directory Organization

Grouping Packages

You can group packages by adding more workspace paths:

# pnpm-workspace.yaml
packages:
  - "apps/*"
  - "packages/*"
  - "packages/config/*"    # Grouped configs
  - "packages/features/*"  # Feature packages

This allows:

packages/
├── ui/
├── utils/
├── config/
│   ├── eslint/
│   ├── typescript/
│   └── tailwind/
└── features/
    ├── auth/
    └── payments/

What NOT to Do

# BAD: Nested wildcards cause ambiguous behavior
packages:
  - "packages/**"  # Don't do this!

Package Anatomy

Minimum Required Files

packages/ui/
├── package.json    # Required: Makes it a package
├── src/            # Source code
│   └── button.tsx
└── tsconfig.json   # TypeScript config (if using TS)

package.json Requirements

{
  "name": "@repo/ui",           // Unique, namespaced name
  "version": "0.0.0",           // Version (can be 0.0.0 for internal)
  "private": true,              // Prevents accidental publishing
  "exports": {                  // Entry points
    "./button": "./src/button.tsx"
  }
}

TypeScript Configuration

Shared Base Config

Create a shared TypeScript config package:

packages/
└── typescript-config/
    ├── package.json
    ├── base.json
    ├── nextjs.json
    └── library.json
// packages/typescript-config/base.json
{
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "module": "ESNext",
    "target": "ES2022"
  }
}

Extending in Packages

// packages/ui/tsconfig.json
{
  "extends": "@repo/typescript-config/library.json",
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src"
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}

No Root tsconfig.json

You likely don't need a tsconfig.json in the workspace root. Each package should have its own config extending from the shared config package.

ESLint Configuration

Shared Config Package

packages/
└── eslint-config/
    ├── package.json
    ├── base.js
    ├── next.js
    └── library.js
// packages/eslint-config/package.json
{
  "name": "@repo/eslint-config",
  "exports": {
    "./base": "./base.js",
    "./next": "./next.js",
    "./library": "./library.js"
  }
}

Using in Packages

// apps/web/.eslintrc.js
module.exports = {
  extends: ["@repo/eslint-config/next"],
};

Lockfile

A lockfile is required for:

  • Reproducible builds
  • Turborepo to understand package dependencies
  • Cache correctness

Without a lockfile, you'll see unpredictable behavior.