Litestore · Developer guide

Commands

Learn what every script in package.json runs — dev, database, the lint checks and the verify gate.

Every command on this page is a script in package.json and runs with bun run <name> from the repository root.

packageManager pins bun@1.2.2, and .github/workflows/verify.yml installs that version, so the CI run and your local run are the same tool at the same version.

Daily

bun run dev

next dev -p 3000 --turbopack — the storefront on :3000, the admin at /admin.

bun run build

next build under NODE_OPTIONS=--max-old-space-size=6144. The prebuild hook runs icons first.

bun run start

next start -p 3000.

bun run icons

scripts/build-icons.ts — writes the icon sprite and types/icons.d.ts.

Both outputs are gitignored, so a fresh clone needs this before typecheck or the sprite contract test passes.

bun run email

SKIP_ENV_VALIDATION=1 email dev — the React Email preview server for the templates in emails/.

bun run format

biome format --write ..

bun run clean:next

Deletes the .next-build and .next-dev directories.

bun run scaffold:analytics-card

scripts/scaffold-analytics-card.ts <kebab-key> "<Human Title>" — prints ready-to-paste snippets for the six places an analytics card has to be wired: query, service, action, row builder, table registry, dashboard card and module registry.

Database

bun run db:generate

prisma generate. The postinstall hook already runs it after bun install.

bun run db:migrate

prisma migrate dev.

bun run db:push

Also prisma migrate devthe same command as db:migrate, not prisma db push.

bun run db:deploy

prisma migrate deploy — applies committed migrations without generating new ones.

bun run db:reset

prisma migrate reset — drops, re-applies every migration, then runs the seed through the prisma.seed hook (bun prisma/seed.ts).

bun run db:seed

tsx prisma/seed.ts.

bun run db:studio

prisma studio --port 5556.

bun run db:guarantees:audit

scripts/check-db-guarantees.ts — a read-only audit of the constraints, indexes, triggers and views the migrations install. It fails when a drift view or a pre-index duplicate probe returns rows.

bun run db:guarantees:audit:strict

The same audit with --strict, which also fails on any unvalidated CHECK.

db:push is not a schema push

db:push and db:migrate are both prisma migrate dev, so either one writes a migration file. prisma/migrations/ holds a committed history — 20260726143000_baseline_with_db_guarantees (the schema plus every CHECK constraint and case-insensitive unique index) and 20260730090000_performance_indexes.

db:seed has a matching trap. tsx is not a dependency in package.json, so bun run db:seed fails when tsx is not installed globally. Run the file directly instead:

bun prisma/seed.ts

That is the same file — it is what the prisma.seed hook uses, and what db:reset invokes.

Checks

bun run lint

The short working loop, in order:

  1. biome check --write .
  2. lint:cache
  3. lint:discipline
  4. lint:dead
  5. lint:flex
  6. lint:critical-tests
  7. lint:no-as-any
  8. lint:cleanliness

This one writes fixes. It is the only command in this file that changes your working tree without being asked.

bun run lint:discipline

scripts/check-discipline.ts — icons, table factory, CRUD routing and the other on-pattern rules.

bun run lint:critical-tests

scripts/check-critical-tests.ts — fails when a money or correctness-critical file has no test.

bun run lint:cleanliness

Thirteen checks in sequence:

  1. orphan exports
  2. dead server actions
  3. dead Prisma fields
  4. field balance
  5. duplicate utils
  6. unused deps
  7. hacks
  8. events
  9. cache tags
  10. guarantees contract
  11. client/server boundary
  12. client bundle
  13. discipline hygiene
bun run lint:knip

knip — unreferenced files and exports. Not part of verify.

bun run test

vitest in watch mode.

bun run vitest run

One pass of the unit and contract suite. vitest here is the binary in node_modules/.bin, not a package.json script.

bun run test:integration

vitest run --config vitest.integration.config.ts — the files under test/integration/ against a real litestore_test Postgres, run sequentially. Override the connection with TEST_DATABASE_URL.

bun run typecheck

tsc --noEmit under NODE_OPTIONS=--max-old-space-size=12288.

bun run typecheck:strict

The same with --strict --noImplicitAny --noImplicitReturns --noImplicitThis --noUnusedLocals --noUnusedParameters.

Typecheck memory

typecheck asks Node for a 12 GB heap. On smaller machines, close the dev server and run it alone.

The verify gate

bun run verify

verify is the one command that decides whether a change is mergeable. .github/workflows/verify.yml runs it on every push to main and every pull request.

It is a single && chain in package.json, run sequentially and stopping at the first failure. The legs are:

  1. biome check .
  2. lint:discipline
  3. lint:cache
  4. lint:dead
  5. lint:flex
  6. lint:theme-boundaries
  7. lint:no-as-any
  8. lint:critical-tests
  9. lint:event-completeness
  10. lint:nested-soft-delete
  11. lint:public-feed-visibility
  12. lint:nested-hidden
  13. lint:cleanliness
  14. vitest run
  15. typecheck

Biome runs there without --write, unlike in lint. Between it and the typechecker sit twelve lint checks and the test suite.

Every leg is its own script, so you can run one in isolation rather than re-running the chain.

How the 25 checks map onto the gate

Eleven of the legs execute exactly one scripts/check-*.ts file each:

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-hidden

lint:cleanliness chains 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:hygiene

That is 24 of the 25 scripts/check-*.ts files.

The twenty-fifth, check-db-guarantees.ts, is not in the gate because it needs a live database. It runs through db:guarantees:audit.

Running the gate in parallel

bun run verify:parallel

scripts/verify.ts spawns the same fifteen legs concurrently, capped at cpus − 1. Override that with VERIFY_CONCURRENCY.

It reports per-leg pass/fail and timing, and surfaces every failure instead of stopping at the first — which is what makes it the better choice when several things are broken at once.

The same gate locally

Lefthook enforces it on your machine, and bun install installs the hooks through the prepare script.

pre-commit runs lint:discipline, lint:critical-tests and vitest run.

pre-push runs verify.

commit-msg rejects messages under 10 characters or 2 words, exempting messages starting with Merge, Revert, fixup! or squash!.

When Prisma disagrees with the schema

If TypeScript claims a model does not exist and you can see it in schema.prisma, the generated client is stale. Regenerate it:

bun run db:generate

This commonly happens after pulling a branch that changed the schema.

Which command to run

For the working loop, run lint — it writes the fixes it can, and it is the shorter chain.

Before you push, run verify, because that is what CI runs and what pre-push runs. Reach for verify:parallel when you already know several legs are failing and want the whole list in one pass.

The one thing neither gate covers is the database audit, since it needs a live connection:

If you changed a migration, verify passing is not evidence that the guarantees still hold — run db:guarantees:audit against the database.

Next Steps

On this page