Launch NowDocs

Scripts

Every pnpm script defined in package.json, what it runs, its flags, and when to use it.

Launch Now ships its tooling as pnpm scripts in package.json. Scripts that run TypeScript files use tsx and live in scripts/ (or drizzle/migrate.ts). Most of them load your .env file through dotenv/config, so run them from the project root.

Overview

ScriptRuns
pnpm devnext dev
pnpm buildnext build
pnpm build:deploypnpm db:migrate && next build
pnpm startnext start
pnpm linteslint .
pnpm formatprettier --write on **/*.{ts,tsx,js,jsx,json,md}
pnpm format:checkprettier --check on the same glob
pnpm typechecktsc --noEmit
pnpm knipknip
pnpm checkpnpm lint && pnpm typecheck && pnpm knip
pnpm releaserelease-it
pnpm release:dryrelease-it --dry-run
pnpm release:patchrelease-it patch
pnpm release:minorrelease-it minor
pnpm release:majorrelease-it major
pnpm commitgit-cz
pnpm db:generatedrizzle-kit generate
pnpm db:migratetsx drizzle/migrate.ts
pnpm db:baselinetsx scripts/db-baseline.ts
pnpm db:pushPrints a message; does nothing
pnpm db:pulldrizzle-kit pull
pnpm db:checkdrizzle-kit check
pnpm db:studiodrizzle-kit studio
pnpm db:exportdrizzle-kit export
pnpm stripe:productstsx scripts/stripe-create-products.ts
pnpm stripe:update-featurestsx scripts/stripe-update-features.ts
pnpm db:seed:planstsx scripts/seed-plans.ts
pnpm resource:generatetsx scripts/generate-resource.ts
pnpm db:seed:demotsx scripts/seed-demo.ts
pnpm reset-projecttsx scripts/reset-project.ts
pnpm legal:checktsx scripts/legal-check.ts
pnpm email:devemail dev

Development and build

pnpm dev

Starts the Next.js development server (next dev). Use it for local development.

pnpm build

Creates a production build with next build. It does not touch the database.

lib/env.ts validates environment variables at build time. The CI workflow (.github/workflows/ci.yml) sets SKIP_ENV_VALIDATION=1 so the build can run without secrets.

pnpm build:deploy

Runs pnpm db:migrate, then next build. Use it as the build command on your hosting provider so pending migrations are applied before each deploy.

If DATABASE_URL is not set, the migrate step logs a warning and exits with code 0, so the build still runs.

pnpm start

Serves the production build (next start). Run pnpm build first.

pnpm email:dev

Starts the React Email preview server (email dev, from the react-email package). Use it to preview the templates in emails/, such as emails/otp-email.tsx.

Code quality

pnpm lint

Runs ESLint on the whole project (eslint .). It also runs as a pre-commit hook through simple-git-hooks (configured in package.json).

pnpm format

Formats every ts, tsx, js, jsx, json and md file with Prettier, writing changes in place.

pnpm format:check

Checks formatting without writing anything. CI runs this step and fails on unformatted files.

pnpm typecheck

Runs the TypeScript compiler without emitting files (tsc --noEmit). Run it after moving or deleting code, for example after pnpm reset-project.

pnpm knip

Runs Knip to find unused files, exports and dependencies. The configuration is in knip.json: it treats scripts/*.ts and types/**/*.ts as entry points and ignores components/ui/**, components/spectrumui/**, the script templates and .claude/**.

pnpm check

Runs pnpm lint, pnpm typecheck and pnpm knip in sequence and stops at the first failure. Use it before opening a pull request.

Releases and commits

pnpm release

Runs release-it interactively. The configuration in .release-it.json:

  • Generates CHANGELOG.md from Conventional Commits (@release-it/conventional-changelog, preset conventionalcommits).
  • Commits with chore: release v${version} and tags v${version}.
  • Creates a GitHub release.
  • Does not publish to npm.

Good to know: The public /changelog page does not read CHANGELOG.md. It renders features/changelog/changelog-data.ts. See Content.

pnpm release:dry

Runs release-it --dry-run: shows what a release would do without changing anything.

pnpm release:patch

Releases the next patch version (release-it patch), for example 0.0.1 to 0.0.2.

pnpm release:minor

Releases the next minor version (release-it minor).

pnpm release:major

Releases the next major version (release-it major).

pnpm commit

Opens the Commitizen prompt (git-cz) with the cz-git adapter to write a Conventional Commit message. Commit messages are checked by commitlint (@commitlint/config-conventional) through the commit-msg git hook.

Database

drizzle.config.ts points Drizzle Kit at drizzle/auth-schema.ts and writes migrations to drizzle/. It reads DATABASE_URL from .env. See Database schema for the tables.

pnpm db:generate

Compares drizzle/auth-schema.ts with the last snapshot in drizzle/meta/ and writes a new SQL migration in drizzle/. Run it every time you change the schema, then commit the generated files.

pnpm db:migrate

Applies pending migrations from drizzle/ to the database in DATABASE_URL, using drizzle/migrate.ts (the drizzle-orm node-postgres migrator). Applied migrations are tracked in the drizzle.__drizzle_migrations table.

pnpm db:generate
pnpm db:migrate

The script runs with NODE_OPTIONS='--no-network-family-autoselection' and a 30 second connection timeout. If DATABASE_URL is missing, it prints a warning and exits with code 0 instead of failing.

pnpm db:baseline

Marks migrations as already applied on a database whose tables were created outside Drizzle's journal (for example with drizzle-kit push), so that pnpm db:migrate only runs the newer ones.

FlagRequiredDescription
--until <tag>YesThe last migration whose changes already exist in the database, for example 0014_cheerful_silhouette. Must match a tag in drizzle/meta/_journal.json.
--applyNoWrites the records. Without it, the script is a dry run and only prints the plan.
pnpm db:baseline --until 0014_cheerful_silhouette
pnpm db:baseline --until 0014_cheerful_silhouette --apply

For each migration up to --until, the script computes the same SHA-256 hash Drizzle's migrator records and inserts it into drizzle.__drizzle_migrations (creating the schema and table if needed). Migrations already recorded are skipped. It ends by listing the migrations the next pnpm db:migrate will run. It requires DATABASE_URL.

pnpm db:push

Does not push anything. It only prints:

Use db:generate + db:migrate instead. Neon does not support drizzle-kit push.

pnpm db:pull

Runs drizzle-kit pull to introspect the database and generate a schema from it. Use it to inspect drift, not as part of the normal workflow.

pnpm db:check

Runs drizzle-kit check to validate the consistency of the generated migrations and snapshots.

pnpm db:studio

Opens Drizzle Studio (drizzle-kit studio), a browser UI to browse and edit the database in DATABASE_URL.

pnpm db:export

Runs drizzle-kit export, which prints the SQL for the current schema without touching the database.

pnpm db:seed:plans

Upserts the three plans into the plan table: free, pro and ultra, with their display name, description, monthly price in cents (0, 1000, 5000), features, limits and sort order. Rows are matched on plan.name, so re-running the script updates them and sets active to true.

Edit the plans array in scripts/seed-plans.ts to change what is seeded. Requires DATABASE_URL.

pnpm db:seed:demo

Seeds the shared demo account. It is idempotent: existing rows are reused or updated.

It requires DEMO_EMAIL and DEMO_PASSWORD (at least 8 characters) and exits with an error if either is missing. It creates or updates:

  • The demo user (Demo User, email verified, onboarding completed) with a credential account whose password is hashed with Better Auth's hashPassword. The password is re-synced with DEMO_PASSWORD on every run.
  • A Demo Workspace organization (slug demo-workspace) owned by the demo user.
  • Three fake members (demo-member-1@example.invalid as admin, two others as member). They have no password and cannot sign in.
  • Two pending invitations that expire 30 days after the run.

The script writes directly to the database instead of calling auth.api.signUpEmail, because public email/password sign-up is disabled and going through auth would create a Stripe customer.

Good to know: pnpm reset-project removes this script and its package.json entry.

Stripe

Both Stripe scripts read STRIPE_SECRET_KEY and use siteConfig.slug from lib/config/site-config.ts to tag products and build price lookup keys (<slug>-pro-monthly, <slug>-ultra-monthly).

pnpm stripe:products

Creates the paid products and monthly USD prices in Stripe:

ProductMetadata planLookup keyAmount
Propro<slug>-pro-monthly1000 cents
Ultraultra<slug>-ultra-monthly5000 cents

It is safe to re-run: a price with the same lookup key is reused, and an active product with matching app and plan metadata is reused. At the end, it prints the lines to copy into your .env:

STRIPE_PRO_PRICE_ID=price_...
STRIPE_ULTRA_PRICE_ID=price_...

Run it once per Stripe account (test mode, then live mode).

pnpm stripe:update-features

Finds each paid product through its price lookup key and updates it with a description, Stripe marketing_features, and features and limits JSON strings in the product metadata. Plans with no matching price are skipped with a warning.

Run it after changing the feature lists in scripts/stripe-update-features.ts. Keep them in sync with scripts/seed-plans.ts.

Code generation

pnpm resource:generate

Scaffolds a CRUD resource with the resource-kit generator (scripts/generate-resource.ts). For each resource, it:

  • Appends a Drizzle table to drizzle/auth-schema.ts.
  • Writes lib/<name>-config.ts and lib/<name>-actions.ts.
  • Writes a form sheet and a table in features/<name>/.
  • Writes a list page and a [id] detail page under app/(app)/<path>/, plus a layout.tsx for user-scoped, non-admin resources.
  • Adds an entry to lib/resource-kit/manifest.json.
  • Adds a sidebar item in components/layouts/nav-configs/.

Generated files are formatted with Prettier when it is installed.

FlagDescription
--spec <path>Reads the resource from a JSON spec file instead of prompting. The file can hold one spec, or { "resources": [...] } for several.
--force, -fOverwrites files that already exist. Without it, existing files are skipped.

Without --spec, the script asks for the name, title, scope (user or organization), admin-only flag, path, Lucide icon and fields interactively.

pnpm resource:generate --spec drizzle/resources/org-projects.json
pnpm db:generate
pnpm db:migrate

Field types are text, textarea, number, boolean, date, json, email, url, select, password and relation. The names id, userId, organizationId, createdAt and updatedAt are reserved, and adminOnly cannot be combined with the organization scope. A relation field fails unless its target table already exists or is generated in the same run. See drizzle/resources/README.md for every spec option.

pnpm reset-project

Turns the starter into a clean slate. It removes the example CRUD resources, the demo pages and the shared demo account:

  • Moves these paths to examples/ (kept as reference, excluded from the build): app/(app)/projects, app/(app)/categories, features/projects, features/categories, lib/projects-actions.ts, lib/categories-actions.ts, app/(app)/orgs/[orgSlug]/org-projects, features/org-projects, lib/org-project-actions.ts, lib/org-project-config.ts, drizzle/resources/org-projects.json, app/(app)/(dash)/demo, lib/demo-actions.ts, features/auth/demo-signin-button.tsx and scripts/seed-demo.ts.
  • Strips every block between @reset-remove:start and @reset-remove:end comments in .ts and .tsx files under app, components, features, lib and drizzle.
  • Replaces files with the clean versions in scripts/reset/templates/ (the originals are copied to examples/ first).
  • Removes the db:seed:demo script from package.json and the orgProject entry from lib/resource-kit/manifest.json.
FlagDescription
--dry-runPrints the plan and changes nothing.
--yes, -ySkips the confirmation prompt (for CI).
--forceRuns even when the git working tree has uncommitted changes.
pnpm reset-project --dry-run
pnpm reset-project

The script plans everything before writing, and refuses to run twice: it writes examples/.reset.json and exits if that file already exists. After a reset, it prints the next steps:

pnpm typecheck
pnpm db:generate
pnpm db:migrate
pnpm resource:generate

The migration drops the example tables (categories, projects, org_projects). Skip both database steps on a brand-new database with no data. Then remove DEMO_EMAIL and DEMO_PASSWORD from your .env files and delete examples/ when you no longer need it.

Commit your work before running pnpm reset-project. The generated migration drops the example tables and their data.

pnpm legal:check

Loads your .env files the same way Next.js does, then lists every field in lib/config/legal.ts that still holds a TODO placeholder (using findLegalPlaceholders). It exits with code 1 when some remain, so you can use it to gate a release in CI.

pnpm legal:check

See Legal pages to fill the configuration.