Commands And Scripts
pnpm and Turborepo tasks for the monorepo. Most run from the repo root; a few live only in the package that owns them.
Last updated on
5 min readOn This Page
Most-Used
These eight cover most daily work.
| Command | Does |
|---|---|
pnpm dev | Start the product app on port 3000 |
pnpm docs:dev | Start the docs site on port 3001 |
pnpm test:run | Single-pass unit tests with coverage gates |
pnpm test:integration | Postgres-backed integration tests |
pnpm test:e2e | Playwright E2E suite (build + run) |
pnpm db:migrate:dev | Create or apply migrations in development |
pnpm setup:doctor | Diagnose missing or invalid env config |
pnpm format | Prettier write across the workspace |
Development
| Command | Does | Where |
|---|---|---|
pnpm dev | Next.js product app on :3000 (turbo dev --filter=@syntaxkit/web) | Root |
pnpm docs:dev | Fumadocs site on :3001 | Root |
pnpm email:dev | React Email preview (@syntaxkit/email preview) | Root |
pnpm --filter @syntaxkit/<package> dev | Same filter form; rarely needed | Root |
dev depends on ^db:generate, so Turbo regenerates the Prisma client before the app starts.
Build
| Command | Does |
|---|---|
pnpm build | turbo build across the workspace (web, docs, and packages) |
pnpm --filter @syntaxkit/web build | Build only the product app |
pnpm --filter @syntaxkit/docs build | Build only the docs site |
build declares dependsOn: ["^build", "^db:generate"], so the Prisma client regenerates before packages that need it. You do not need pnpm db:generate by hand before a build.
Quality
| Command | Does |
|---|---|
pnpm lint | ESLint across every package |
pnpm check-types | TypeScript check across every package |
pnpm format | Prettier write across the workspace |
pnpm format:check | Prettier check (CI-friendly; non-zero exit on drift) |
pnpm docs:lint-links | Verify internal links in the docs MDX |
pnpm deploy:check-build-args | Drift-check NEXT_PUBLIC_* build args across deploy configs |
lint and check-types are Turbo-cached. An unchanged graph is a no-op (FULL TURBO, usually milliseconds).
Tests
Four layers, each with its own command and file pattern. See Testing for the full story.
| Layer | Command | What runs | File pattern |
|---|---|---|---|
| Unit (watch) | pnpm test | Vitest watch in every package | *.test.ts(x) co-located |
| Unit | pnpm test:run | Single Vitest run with coverage gates | *.test.ts(x) co-located |
| Unit + coverage | pnpm test:coverage | Same as test:run plus per-package thresholds | same |
| Integration | pnpm test:integration | Vitest with real Postgres (loads apps/web/.env.test) | *.integration.test.ts |
| Live Stripe | pnpm test:stripe | Vitest against Stripe test mode; gated on RUN_STRIPE_LIVE=1 | *.live.test.ts |
| E2E | pnpm test:e2e | Build the app, then Playwright + Chromium | apps/web/e2e/*.spec.ts |
| E2E (run only) | pnpm test:e2e:run | Playwright only (skips the build step; used in CI) | same |
| E2E (UI) | pnpm test:e2e:ui | Playwright UI for time-travel debugging | same |
Root test scripts that need a database load apps/web/.env.test through dotenvx before Turbo starts.
test:integration, test:stripe (Turbo test:live), and test:e2e / test:e2e:run set cache: false. They hit live infra (Postgres, Stripe, Chromium), so every invocation actually runs.
Database
Every db:* task lives in packages/database and is proxied at the root, so pnpm db:<task> works from anywhere. See Database for the workflows.
| Command | Does |
|---|---|
pnpm db:generate | Generate the typed Prisma client |
pnpm db:migrate:dev | Create and apply a migration in development |
pnpm db:migrate:deploy | Apply migrations non-interactively (production-safe) |
pnpm db:migrate:status | Check whether the DB matches prisma/migrations/ |
pnpm db:push | Push schema changes without a migration (prototype only) |
pnpm db:test:push | db:push against the test database (apps/web/.env.test) |
pnpm db:studio | Open Prisma Studio |
pnpm db:seed | Run the seed dispatcher (defaults to bootstrap mode) |
pnpm db:seed:bootstrap | Empty DB; first sign-up creates the personal org |
pnpm db:seed:demo | Sample orgs and an admin (admin@demo.syntaxkit.com / password123) |
pnpm db:seed:test | Test fixtures (4 deterministic users for Playwright) |
pnpm db:reset | Drop, recreate, migrate, then bootstrap seed (empty database) |
pnpm db:reset:demo | Drop, recreate, migrate, then seed demo data |
pnpm db:validate | Validate the Prisma schema |
db:reset and db:reset:demo run a destructive-guard script first, then the Prisma reset.
Setup, Tooling, And Deploy
| Command | Does |
|---|---|
pnpm setup:doctor | Diagnose env file, optional integrations, and DB reachability |
pnpm auth:generate | Regenerate auth.generated.prisma from Better Auth config |
pnpm admin:bootstrap --email <email> | Promote a user to platform admin (only when no admin exists) |
pnpm billing:check-prices | Compare catalog prices to live Stripe Prices; skips when billing is unset |
pnpm billing:reconcile | Re-sync non-terminal subscriptions from Stripe (--dry-run to report only) |
pnpm deploy:check-build-args | Drift-check NEXT_PUBLIC_* across Dockerfile, compose, fly.toml, render.yaml, and the GHA workflow |
pnpm skills:sync | Mirror .agents/skills into .claude/skills (--check for CI) |
pnpm clean | Remove node_modules, .next, .turbo, dist, coverage, and .source |
pnpm --filter @syntaxkit/docs diagrams:build | Re-render Mermaid diagrams to SVG |
Per-Package Tasks
Root scripts proxy into packages with pnpm --filter or Turbo. Inside a package you can run the same local names.
Most packages share this pattern:
| Command (inside a package) | Does |
|---|---|
pnpm test | Vitest watch mode |
pnpm test:run | Vitest single run |
pnpm test:coverage | Vitest run with coverage gates |
pnpm lint | eslint . |
pnpm check-types | tsc --noEmit (tsc -b for api, shared, analytics, and i18n) |
Useful extras by package:
| Package | Extra commands |
|---|---|
apps/web | dev, build, start, test:live, test:e2e, test:e2e:run, test:e2e:ui |
apps/docs | dev, build, start, lint:links, diagrams:build |
packages/api | test:integration, test:live |
packages/auth | test:integration |
packages/database | every db:* (canonical home; root proxies here) |
packages/email | preview (React Email; root exposes as email:dev) |
packages/payments | test:live |
Packages with unit tests but no extras: analytics, core, shared, storage. Lint and types only: brand, i18n, ui. Config packages (eslint-config, typescript-config) define no scripts.
Turbo Caching
lint, check-types, build, test:run, and test:coverage are cached. The cache key includes the dependency graph plus each task's env allowlist, so a Stripe-key change busts only the live-test cache, not the build cache.
Tasks that hit live infra set cache: false and re-run every time: dev, test, every db:*, test:integration, test:live, test:e2e, and test:e2e:run. See Conventions for the full pipeline.
Where To Go Next
Database
The db:* commands in context, plus the seed modes.
Testing
The four test layers in detail, plus parallelization.
Also useful: Conventions, Setup, and Deployment.
Testing
Four layers: Vitest unit and integration, opt-in Stripe live, and Playwright E2E. One command per layer. Coverage gates at 90% lines / 85% branches.
Environment Variables
Every variable the kit reads, where it is used, and what it controls. A fresh clone runs with three core vars (DATABASE_URL, NEXT_PUBLIC_APP_URL, BETTER_AUTH_SECRET). Optional groups degrade cleanly when blank.
