Commands And Scripts
Common pnpm tasks across the monorepo.
The kit is a pnpm + Turborepo workspace. Most commands run from the repo root and Turbo dispatches them to the right package; a few live only inside the package that owns them. This page lists both.
Most-used
The commands that cover daily work.
Tests
The test tiers and their commands.
Database
The db:* tasks for migrate, seed, and inspect.
Turbo caching
Which tasks are cached and which always re-run.
Most-Used
Nine commands cover 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 |
pnpm db:migrate:dev | Apply pending migrations to the dev database |
pnpm setup:init | Ask which features to turn on, merge apps/web/.env, then offer Postgres, migrate, and seed |
pnpm setup:doctor | Diagnose missing or invalid env config |
pnpm format | Prettier write across the workspace |
Development
| Command | Does | Where |
|---|---|---|
pnpm dev | Next.js dev on :3000 (turbo dev --filter=@syntaxkit/web) | Root |
pnpm docs:dev | Fumadocs site on :3001 | Root |
pnpm email:dev | React Email preview server | Root |
pnpm --filter @syntaxkit/<package> dev | Same, but explicit (rarely needed) | Root |
Build
| Command | Does |
|---|---|
pnpm build | turbo build across the workspace (web + docs + 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 always regenerates first. You never 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 across the docs MDX |
pnpm deploy:check-build-args | Drift-check NEXT_PUBLIC_* build args across configs |
lint and check-types are Turbo-cached: an unchanged graph is a no-op (FULL TURBO, done in milliseconds).
Billing
Both scripts read BILLING_PROVIDER (default stripe) from the shell and apps/web/.env and act on the active provider only. See Billing.
| Command | Does |
|---|---|
pnpm billing:check-prices | Compare each declared catalog price with its live Stripe Price, Polar Product, or Creem product. Stripe and Polar compare amount, currency, and archived state (interval and trial for Polar). Creem compares amount, currency, and interval; Creem product prices are integer cents and the catalog amount is major units. Skips cleanly when the active provider is not configured or only placeholders are set. Exits non-zero on drift. |
pnpm billing:check-prices --strict | Same, and promote Stripe interval mismatches from warnings to failures (equivalent to BILLING_PRICE_SYNC_STRICT_INTERVAL=1). No effect for Polar, which has one interval per product. |
pnpm billing:reconcile | Re-fetch every non-terminal subscription owned by the active provider and heal drift through the canonical recency-guarded write; a subscription the provider no longer knows is marked canceled. Requires DATABASE_URL and the provider's credentials. |
pnpm billing:reconcile --dry-run | Report drift without writing anything. |
Tests
Four tiers, each with its own command and file convention. See Testing for the full layering story.
| Tier | 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 plus per-package thresholds | same |
| Integration | pnpm test:integration | Vitest with real Postgres (loads .env.test) | *.integration.test.ts |
| Live Stripe | pnpm test:stripe | Vitest against Stripe test-mode; gated on RUN_STRIPE_LIVE=1 | *.live.test.ts |
| Live Polar | RUN_POLAR_LIVE=1 POLAR_SERVER=sandbox pnpm --filter @syntaxkit/payments test:live | Vitest against the Polar sandbox; skipped unless the sandbox token and POLAR_PRODUCT_ID_PRO_MONTHLY are set | packages/payments/src/polar/*.live.test.ts |
| E2E | pnpm test:e2e | Playwright + Chromium | apps/web/e2e/*.spec.ts |
| E2E (UI mode) | pnpm test:e2e:ui | Playwright UI for time-travel debugging | same |
test:integration, test:stripe, and test:e2e set cache: false. They hit
live infra (Postgres, Stripe, Polar, or Creem, Chromium), so every invocation actually
runs. The .next-test build they run against is the cached
test:e2e:build task, so an unchanged app skips next build. There is no
root test:polar script; the Polar live test runs through
the payments package's test:live task with the env vars above.
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 dev migration (destructive on drift, dev only) |
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 (.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, and migrate (no seed) |
pnpm db:reset:demo | Drop, recreate, migrate, seed demo data |
pnpm db:validate | Validate the Prisma schema |
Setup, Tooling, And Deploy
| Command | Does |
|---|---|
pnpm setup:init | Interactive first-run setup. Merges apps/web/.env, runs the doctor, then optionally starts Postgres, applies migrations, and loads demo seed. No flags. Does not reset the database. Named setup:init because pnpm setup is pnpm's own command. |
pnpm setup:doctor | Diagnose env file, optional integrations (including the active billing provider and whether live subscriptions belong to it), and DB reachability |
pnpm setup:test | Typecheck and unit-test pnpm setup:init. Runs on pre-push. |
pnpm auth:generate | Regenerate auth.generated.prisma from Better Auth config |
pnpm admin:bootstrap --email <email> | Promote a user to platform admin (one-shot, only when no admin exists) |
pnpm deploy:check-build-args | Drift-check NEXT_PUBLIC_* across Dockerfile, compose, fly.toml, render.yaml, and the GHA workflow |
pnpm clean | Remove all node_modules, .next, .turbo, dist, coverage, .source (full reset) |
pnpm --filter @syntaxkit/docs diagrams:build | Re-render Mermaid diagrams to SVG |
Per-Package Tasks
Anything you run from the root also runs inside its package: the root scripts just proxy via pnpm --filter or turbo.
Every package follows the same pattern:
| Command (run 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 shared and api, which emit declarations) |
Plus the per-package extras:
| Package | Extra commands |
|---|---|
apps/web | dev, build, start, test:live, test:e2e, 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 preview server) |
packages/payments | test:live |
packages/i18n, ui, typescript-config, and eslint-config only define lint and check-types, no tests yet.
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, Polar, or Creem credential change busts only the live-test cache, not the build cache. Tasks that hit live infra (dev, test, every db:*, test:integration, test:live, test:e2e) set cache: false and re-run every time. See Working With The Codebase for the full pipeline.
Where To Go Next
Database
The db:* commands in context, plus the seed modes.
Testing
The four test tiers in detail, plus parallelization.
Working With The Codebase
Turbo caching, the build pipeline, and workspace conventions.
Setup
The doctor's job and the env-var matrix these commands lean on.
Deployment
Which scripts CI invokes per host (Vercel, Fly, Render, Docker).