Zeno

Monorepo

Turborepo-powered monorepo for scalable TypeScript development

Zeno uses Turborepo for monorepo management, providing fast builds, intelligent caching, and a clean separation of concerns across packages.

Why a Monorepo?

Even if you only ship a single application, a monorepo brings real benefits:

  • Shared tooling — TypeScript configs, Tailwind presets, Vitest setup, and linting rules live in dedicated packages. Every app inherits them without copy-pasting.
  • Atomic changes — Update a UI component and the app that consumes it in a single commit, with a single CI run that validates everything together.
  • Incremental adoption — Start with one app. When a second project appears (a marketing site, an admin panel, a mobile BFF), it plugs into the same workspace instantly.
  • Enforced boundaries — Packages expose explicit public APIs, preventing accidental coupling between unrelated parts of the codebase.

In short, the monorepo is not about having many apps today — it is about keeping your codebase modular and ready to grow.

Turborepo & Remote Caching

Turborepo analyses the dependency graph declared in turbo.json and runs only the tasks whose inputs have actually changed. Locally, results are stored in a file-system cache so repeated builds are nearly instant.

The same mechanism extends to CI through Turborepo Remote Caching. When enabled, build artifacts are stored in a shared cloud cache (hosted by Vercel or self-hosted). This means:

  • A task that was already computed on another developer's machine or in a previous CI run is never re-executed — the cached output is downloaded instead.
  • CI pipelines become significantly faster because only genuinely new work is performed.
  • The cache is content-addressed and scoped to your team, so it is both safe and deterministic.

Structure

zeno/
├── apps/               # Applications
│   └── docs/           # Documentation site (@zeno-lib/docs)
├── packages/           # Shared libraries
│   ├── ui/             # React components (@zeno-lib/ui)
│   ├── typescript/     # TypeScript configs (@zeno-lib/typescript)
│   ├── tailwind/       # Tailwind config (@zeno-lib/tailwind)
│   ├── supabase/       # Supabase integration (@zeno-lib/supabase)
│   ├── vitest/         # Vitest config (@zeno-lib/vitest)
│   └── e2e/            # Playwright E2E tests (@zeno-lib/e2e)
├── turbo.json          # Turborepo task configuration
└── pnpm-workspace.yaml # Workspace definition

Commands

# Development
pnpm dev              # Start all dev servers

# Building
pnpm build            # Build all packages

# Type checking
pnpm types:check      # Check TypeScript across all packages

# Testing
pnpm test             # Run unit tests
pnpm e2e              # Run E2E tests

# Linting
pnpm lint             # Check code quality
pnpm lint:fix         # Auto-fix issues

# CI
pnpm ci               # Run full CI pipeline

Filtering

Run commands for a specific package using Turborepo filters:

pnpm turbo run dev --filter @zeno-lib/docs
pnpm turbo run build --filter @zeno-lib/ui

Adding Dependencies

# Add to the root workspace
pnpm add -D <package> -w

# Add to a specific package
pnpm add <package> --filter @zeno-lib/ui

Workspace References

Reference internal packages in any package.json using workspace:*:

package.json
{
  "dependencies": {
    "@zeno-lib/ui": "workspace:*",
    "@zeno-lib/typescript": "workspace:*"
  }
}