Commands
This page tells you what each script in package.json does and which one to run when.
Every command on this page is a script in package.json. You run each one with bun run <name> from the repository root.
packageManager pins bun@1.2.2, and .github/workflows/verify.yml installs that same version. CI and your machine therefore run the same tool at the same version.
Daily
bun run devThis runs next dev -p 3000 --turbopack. The storefront opens on :3000 and the admin at /admin.
bun run buildThis runs next build with NODE_OPTIONS=--max-old-space-size=6144. The prebuild hook runs icons first.
bun run startThis runs next start -p 3000.
bun run iconsThis runs scripts/build-icons.ts, which writes the icon sprite and types/icons.d.ts.
Git ignores both files. On a fresh clone, you need to run this before typecheck or the sprite contract test can pass.
bun run emailThis runs SKIP_ENV_VALIDATION=1 email dev, which starts the React Email preview server for the templates in emails/.
bun run formatThis runs biome format --write ..
bun run clean:nextThis deletes the .next-build and .next-dev directories.
bun run scaffold:analytics-cardThis runs scripts/scaffold-analytics-card.ts <kebab-key> "<Human Title>". It prints snippets you can paste into each place an analytics card has to be wired up. Those places are the query, service, action, row builder, table registry, dashboard card and module registry.
Database
bun run db:generateThis runs prisma generate. The postinstall hook already runs it for you after bun install.
bun run db:migrateThis runs prisma migrate dev.
bun run db:pushThis also runs prisma migrate dev. It is the same command as db:migrate, not prisma db push.
bun run db:deployThis runs prisma migrate deploy. It applies the migrations already committed and does not generate new ones.
bun run db:resetThis runs prisma migrate reset. It drops the database and re-applies every migration. Then it runs the seed through the prisma.seed hook (bun prisma/seed.ts).
bun run db:seedThis runs tsx prisma/seed.ts.
bun run db:studioThis runs prisma studio --port 5556.
bun run db:guarantees:auditThis runs scripts/check-db-guarantees.ts. It reads the database without changing it and checks the constraints, indexes, triggers and views that the migrations install. It fails when a drift view or a pre-index duplicate probe returns rows.
bun run db:guarantees:audit:strictThis runs the same audit with --strict. In strict mode it also fails on any CHECK constraint that is not validated.
db:push is not a schema push
db:push and db:migrate both run prisma migrate dev, so either one
writes a migration file. The committed history in prisma/migrations/
starts with 20260726143000_baseline_with_db_guarantees, which contains the
schema plus every CHECK constraint and case-insensitive unique index. After
it comes 20260730090000_performance_indexes.
db:seed has a similar trap. tsx is not a dependency in package.json, so bun run db:seed fails unless you have tsx installed globally. Run the file directly instead:
bun prisma/seed.tsThis is the same file. The prisma.seed hook uses it, and db:reset calls it.
Checks
bun run lintThis is the short check you run while working. It runs these steps in order:
biome check --write .lint:cachelint:disciplinelint:deadlint:flexlint:critical-testslint:no-as-anylint:cleanliness
lint writes fixes to your files. It is the only command on this page that changes your working tree without you asking for it.
bun run lint:disciplineThis runs scripts/check-discipline.ts. It checks that code follows the project's patterns for icons, the table factory, CRUD routing and similar rules.
bun run lint:critical-testsThis runs scripts/check-critical-tests.ts. It fails when a file that handles money or other critical logic has no test.
bun run lint:cleanlinessThis runs thirteen checks one after another:
- orphan exports
- dead server actions
- dead Prisma fields
- field balance
- duplicate utils
- unused deps
- hacks
- events
- cache tags
- guarantees contract
- client/server boundary
- client bundle
- discipline hygiene
bun run lint:knipThis runs knip, which finds files and exports that nothing references. It is not part of verify.
bun run testThis runs vitest in watch mode.
bun run vitest runThis runs the unit and contract tests once. Here vitest is the binary in node_modules/.bin, not a script in package.json.
bun run test:integrationThis runs vitest run --config vitest.integration.config.ts. It runs the files under test/integration/ one at a time against a real litestore_test Postgres database. You can point it at a different database with TEST_DATABASE_URL.
bun run typecheckThis runs tsc --noEmit with NODE_OPTIONS=--max-old-space-size=12288.
bun run typecheck:strictThis runs the same check with --strict --noImplicitAny --noImplicitReturns --noImplicitThis --noUnusedLocals --noUnusedParameters.
Typecheck memory
typecheck asks Node for a 12 GB heap. On a smaller machine, stop the dev
server and run it on its own.
The verify gate
bun run verifyverify decides whether a change can be merged. .github/workflows/verify.yml runs it on every push to main and on every pull request.
In package.json, verify is a single chain of commands joined with &&. They run one after another, and the chain stops at the first failure. These are the steps:
biome check .lint:disciplinelint:cachelint:deadlint:flexlint:theme-boundarieslint:no-as-anylint:critical-testslint:event-completenesslint:nested-soft-deletelint:public-feed-visibilitylint:nested-hiddenlint:cleanlinessvitest runtypecheck
Unlike in lint, Biome runs here without --write. Between Biome and the typechecker, the gate runs twelve lint checks and the test suite.
Each step is its own script. When one fails, you can run just that step instead of the whole chain.
How the 25 checks map onto the gate
Eleven of the steps each run exactly one scripts/check-*.ts file:
lint:discipline
lint:cache
lint:dead
lint:flex
lint:theme-boundaries
lint:no-as-any
lint:critical-tests
lint:event-completeness
lint:nested-soft-delete
lint:public-feed-visibility
lint:nested-hiddenlint:cleanliness runs thirteen more:
lint:orphans
lint:dead-actions
lint:dead-schema
lint:field-balance
lint:dupes
lint:deps
lint:hacks
lint:events
lint:cache-tags
lint:guarantees
lint:client-boundary
lint:client-bundle
lint:hygieneTogether they cover 24 of the 25 scripts/check-*.ts files.
The last one, check-db-guarantees.ts, is left out of the gate because it needs a live database. You run it with db:guarantees:audit.
Running the gate in parallel
bun run verify:parallelThis runs scripts/verify.ts, which starts the same fifteen steps at the same time. It runs at most cpus − 1 of them at once, and you can change that limit with VERIFY_CONCURRENCY.
It reports whether each step passed and how long it took. It shows every failure instead of stopping at the first one. That makes it the better choice when several things are broken at once.
The same gate locally
Lefthook runs the same checks on your machine. bun install sets up the hooks through the prepare script.
pre-commitrunslint:discipline,lint:critical-testsandvitest run.pre-pushrunsverify.commit-msgrejects messages shorter than 10 characters or 2 words. It lets through messages that start withMerge,Revert,fixup!orsquash!.
When Prisma disagrees with the schema
Sometimes TypeScript says a model does not exist even though you can see it in schema.prisma. That means the generated client is out of date. Regenerate it:
bun run db:generateThis usually happens after you pull a branch that changed the schema.
Which command to run
While you work, run lint. It fixes what it can, and it runs fewer checks.
Before you push, run verify, because CI and the pre-push hook both run it. If you already know several steps are failing, run verify:parallel to get the whole list in one pass.
Neither gate checks the database, because that needs a live connection.
If you changed a migration, a passing verify does not prove the guarantees still hold. Run db:guarantees:audit against the database.