This monorepo uses Turborepo for orchestrating builds, tests, and other tasks across workspaces.
Install turbo globally for the best developer experience:
pnpm add turbo --globalTurbo manages these workspaces (defined in pnpm-workspace.yaml):
| Directory | Purpose | In CI |
|---|---|---|
packages/* |
Published libraries (lit-ui-router, etc.) | Yes |
apps/* |
Sample applications and e2e tests | Yes |
tools/* |
Internal build tools | Yes |
docs |
Documentation site | Yes |
Excluded from turbo:
| Directory | Purpose |
|---|---|
examples/ |
Standalone tutorial apps (helloworld, etc.) |
The examples/ directory contains tutorial applications (helloworld, hellogalaxy, hellosolarsystem) that are intentionally excluded from turbo. These are standalone Vite dev servers meant for learning - they have no turbo.json files and are not part of the CI pipeline. They use npm (not pnpm) for Stackblitz compatibility:
cd examples/helloworld
npm install
npm run devThe root turbo.json defines shared task configurations inherited by all workspaces:
ci
├── build (outputs: dist/**)
├── test (inputs: src/**/*.ts, vitest.config.ts, cypress.config.ts)
├── test:coverage (outputs: coverage/**)
├── lint (runs with //#lint:root)
└── format:check (runs with //#format:check:root)
build
└── ^build (depends on workspace dependencies' builds)
dev
└── ^build (persistent, not cached)
e2e
├── ^build
├── ^docs
└── ^e2e (persistent, not cached)
docs
├── ^build
└── ^docs:api (persistent, not cached)
Key concepts:
^taskmeans "run this task on dependencies first"dependsOndefines execution orderoutputsdefines cacheable artifactsinputsscopes cache invalidationwithruns root-level tasks alongside workspace tasks
Workspaces extend the root configuration using "extends": ["//"]:
| Workspace | Custom Configuration |
|---|---|
packages/lit-ui-router |
Adds build:custom-elements before build, configures docs:api |
apps/sample-app-lit |
Adds env vars for build (VITE_*) |
apps/sample-app-lit-e2e |
Disables test caching for e2e tests |
docs |
Adds docs:preview, wrangler:dev tasks, requires ^docs:api before build |
# Build all packages
turbo build
# Run all tests
turbo test
# Run tests with coverage
turbo test:coverage
# Lint all packages
turbo lint
# Check formatting
turbo format:check
# Fix formatting
turbo format
# Full CI pipeline (build + test + coverage + lint + format:check)
turbo ci
# Development server (persistent)
turbo dev
# E2E tests
turbo e2e# Single package
turbo build --filter=lit-ui-router
# Package and its dependencies
turbo build --filter=lit-ui-router...
# Package and its dependents
turbo build --filter=...lit-ui-router
# Only changed packages
turbo build --filter=[HEAD^1]
# Specific directory
turbo build --filter=./packages/*# Force rebuild (ignore cache)
turbo build --force
# Dry run (show what would run)
turbo build --dry-run
# Show cache status
turbo build --summarizeThe GitHub Actions workflow (.github/workflows/build-test.yml) runs the full CI pipeline:
- Checkout - Clone repository
- Setup - Install pnpm, Node.js 22.17.1, dependencies
- Install browsers - Playwright and Cypress for e2e tests
- Build and Test -
pnpm run ci(triggers turbo ci task) - Coverage reports - Vitest coverage for PR comments, Codecov upload
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} # Remote cache auth
TURBO_API: ${{ vars.TURBO_API }} # Cache API endpoint
TURBO_TEAM: ${{ vars.TURBO_TEAM }} # Team identifier| Turbo Task | CI Step |
|---|---|
build |
Part of ci task |
test |
Part of ci task |
test:coverage |
Part of ci task, feeds coverage reports |
lint |
Part of ci task |
format:check |
Part of ci task |
Turborepo remote caching accelerates CI builds by sharing cached artifacts across runs.
When to use remote cache:
- CI builds - automatically enabled when
TURBO_TOKENis set - Local development with slow rebuilds
- Team collaboration on large changes
Setup: See REMOTE_CACHE.md for detailed configuration.
Quick start for local development:
- Create
.turbo/config.jsonwith team config - Export
TURBO_TOKENin your shell - Run
turbo build- artifacts upload/download automatically
# Check what turbo sees as inputs
turbo build --dry-run --summarize
# Force fresh build
turbo build --force
# Clear local cache
rm -rf node_modules/.cache/turboIf tasks run in wrong order, check:
dependsOnin turbo.json- Workspace dependencies in
package.json - Use
--dry-runto verify execution order
Tasks may cache unexpectedly if:
inputsdon't include all source files- Environment variables aren't in
envarray - Outputs aren't in
outputsarray
# Debug cache keys
TURBO_LOG_VERBOSITY=debug turbo buildE2E tasks (e2e, dev, docs) are persistent: true and don't cache:
{
"e2e": {
"cache": false,
"persistent": true
}
}Run these separately from cached tasks.
Root tasks use //# prefix and require scripts in root package.json:
//#lint:root- lints examples directory//#format:root- formats root-level files//#format:check:root- checks root-level formatting
These run alongside workspace tasks via with configuration.