ShipVeryFastShipVeryFast
Documentation

Dev tooling & scripts

ShipVeryFast ships an interactive scaffolding CLI, two layers of linting, a Husky pre-commit hook, and a complete catalogue of npmscripts. This page is the reference for every command you'll run day to day, plus the marketing-screenshot helper and one build pitfall that bites people.

The interactive devtool

npm run devtool runs node scripts/devtool.js, an Inquirer-driven CLI that scaffolds the boilerplate's common file types so you don't hand-write the same imports every time. It prompts you for what to generate and writes the file relative to the project root.

npm run devtool

# 🛠️  Developer Tool CLI
# ? What would you like to generate? (Use arrow keys)
# ❯ UI Component
#   Page (Next.js)
#   API Endpoint
#   Debug Utility
#   Run Development Tools

Each generator asks a few follow-up questions and drops a ready-to-edit file:

GeneratorTemplatesWrites to
UI ComponentBasic, With Styles, ShadCN Stylecomponents/ui (default dir, overridable) as <Name>.tsx
Page (Next.js)Basic, With Layout, Dashboardapp/<route>/page.tsx
API EndpointBasic, With Validation, With Authapp/api/<route>/route.ts
Debug UtilityBasic, Advancedutils/<name>.ts
Run Development ToolsBundle size, dependency analysis, Lighthouse, unused filesRuns in place (no file written)

The templates aren't generic, they match this codebase. The With Validation API template wires in zod and a requestSchema; the With Auth template imports getServerSession from next-auth/next and authOptions from @/app/api/auth/[...nextauth]/route; the With Styles component pulls in cn from @/libs/utils. The Run Development Tools submenu shells out to npx next build --analyze, npx depcheck, and npx lighthouse http://localhost:3000, installing the tool on the fly if it's missing.

Linting

There are two linting layers. The lintpair runs through Next.js's built-in ESLint integration; the lint:strict pair calls eslint directly over every JS/TS file in the repo, which is useful in CI or when you want to lint files Next.js would skip.

ScriptRunsUse it for
npm run lintnext lintEveryday check (this is what the pre-commit hook runs)
npm run lint:fixnext lint --fixAuto-fix what Next.js's linter can fix
npm run lint:stricteslint . --ext .js,.jsx,.ts,.tsxFull-repo lint, every file, no Next.js filtering
npm run lint:strict:fixeslint . --ext .js,.jsx,.ts,.tsx --fixFull-repo lint with auto-fix

The flat config lives in eslint.config.mjs. It extends next/core-web-vitals and next/typescript, then layers on eslint-plugin-react, eslint-plugin-react-hooks, eslint-plugin-jsx-a11y, eslint-plugin-import, eslint-plugin-security, and the Testing Library / jest-dom plugins. That's why both linters share the same rules.

The Husky pre-commit hook

Git hooks are managed with Husky and live in .husky/. The single active hook is .husky/pre-commit, which runs three checks before a commit is allowed through:

#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

# Run linting
npm run lint

# Run unit tests (quick feedback)
npm run test:unit

# Check if coverage meets minimum threshold
echo "Checking test coverage..."
npm run test:coverage:unit -- --passWithNoTests

echo "✅ Pre-commit checks passed!"

The hook is installed by the prepare script (husky install), which npm runs automatically after every npm install, so a fresh clone gets the hook wired up with no extra step. If a lint error or failing unit test sneaks in, the commit is blocked until you fix it.

Need to land a work-in-progress commit past a failing test? Use git commit --no-verify to skip the hook for that one commit. Reach for it sparingly, the hook exists to keep main green.

Full npm script reference

Every script defined in package.json, grouped by purpose. See the dedicated testing pages for the Jest and Playwright details.

# Dev & build
npm run dev      # next dev --turbopack  (http://localhost:3000)
npm run build    # next build            (production build)
npm run start    # next start            (serve the production build)
npm run devtool  # node scripts/devtool.js

# Lint
npm run lint              # next lint
npm run lint:fix          # next lint --fix
npm run lint:strict       # eslint . --ext .js,.jsx,.ts,.tsx
npm run lint:strict:fix   # eslint . --ext .js,.jsx,.ts,.tsx --fix

# Unit & integration tests (Jest)
npm run test                       # jest
npm run test:unit                  # jest, excludes e2e + integration
npm run test:integration           # jest tests/integration
npm run test:watch                 # jest --watch
npm run test:ci                    # jest --coverage --watchAll=false --passWithNoTests
npm run test:coverage              # jest --coverage
npm run test:coverage:unit         # coverage, unit only
npm run test:coverage:integration  # coverage, integration only
npm run coverage:open              # open coverage/lcov-report/index.html

# E2E tests (Playwright)
npm run test:e2e                # npx playwright test
npm run test:e2e:auth           # auth-flow.e2e.spec.ts
npm run test:e2e:navigation     # navigation.e2e.spec.ts
npm run test:e2e:forms          # forms.e2e.spec.ts
npm run test:e2e:accessibility  # accessibility.e2e.spec.ts (@axe-core)
npm run test:e2e:flows          # flows.spec.ts
npm run test:e2e:headed         # --headed
npm run test:e2e:debug          # --debug

# Test database (Docker)
npm run db:test:up    # docker-compose up -d db-test
npm run db:test:down  # docker-compose down

# Git hooks
npm run prepare  # husky install (runs automatically after npm install)

Marketing & preview scripts

scripts/capture-marketing-shots.mjsis a build-tool (not product code) that drives the running boilerplate with Playwright and saves crisp, deterministic PNGs of the dashboard and landing template in light and dark themes. It's run directly with Node, there's no npm alias for it:

node scripts/capture-marketing-shots.mjs

It has two prerequisites baked into the script's header:

  1. The boilerplate dev server must be running on http://localhost:3000.
  2. The /dashboard (and /admin) auth guard must be bypassed locally in middleware.ts (the LOCAL-PREVIEW lines) so the pages render without logging in.

It captures /dashboard, /dashboard/analytics, /dashboard/billing, and the landing template /, writing <name>-<theme>.png files at a 1440×900 viewport with a 2× device scale. The output directory and base URL are overridable via the OUT_DIR and BASE_URL environment variables.

Separately, scripts/performance/ holds standalone analysis tools, lighthouse-audit.js, analyze-bundle.js, analyze-api-performance.js, analyze-renders.js, and performance-monitor.js, each documented in scripts/performance/README.md and run directly with node.

Pitfalls

Never run npm run build with the dev server running.

npm run dev and npm run build both write into the same .next directory. Running a production build while the Turbopack dev server is live can corrupt that cache and produce confusing errors. Stop the dev server first, and if things get weird, delete .next and rebuild.

A couple of smaller ones worth knowing:

  • The pre-commit hook runs npm run lint and npm run test:unit on every commit, so keep them green, a broken test anywhere blocks every commit, not just the file you touched.
  • The marketing-shot script writes outside the boilerplate repo by default (into the landing-page project's public/), so set OUT_DIR if you want the PNGs somewhere else.

Next steps