Development
Day-to-day commands, the demo store, and the live API check.
Commands
| Command | Does |
|---|---|
pnpm run dev | All apps via Turbo |
pnpm run dev:web · dev:admin · dev:api | One app on its own port |
pnpm run type-check | tsc --noEmit in every app — or type-check:<app> for one |
pnpm run lint | ESLint in every app (no-explicit-any is an error) — or lint:<app> |
pnpm run build | Production builds for every app — or build:<app> (Turbo builds its dependencies first) |
pnpm run dev:worker · start:worker | The background worker — email and Stripe webhook queues on Redis. Needs REDIS_URL; without it the API runs those jobs inline and the worker is not needed |
pnpm run seed | Load the demo store — images to your CDN, data to MongoDB (-- --fresh, -- --dry-run, -- --keep-settings) |
pnpm run test | Unit and component tests — Jest in the API, Vitest with jsdom and Testing Library in the storefront and the dashboard |
pnpm run test:e2e | Playwright smoke test: its own API, storefront and dashboard against the grovia_e2e database, one cash order through every job (test:e2e:ui for the UI, test:e2e:report for the last report) |
pnpm run check:api | Live check suite against a running API — creates and removes its own records |
pnpm --filter api run create:admin <email> <password> [name] | Headless administrator |
The demo store
apps/api/data/demo/ holds the demo store as data: one JSON file per collection plus every image it uses. pnpm run seed uploads the images to your ImageKit or Cloudinary account, writes the documents with the URLs of your copies, and moves sale campaigns and coupons forward so they are live today. It is idempotent — documents are upserted by id and finished uploads are remembered, so a second run uploads nothing.
pnpm run seed # load or refresh the demo store
pnpm run seed -- --dry-run # check the pack, your image keys and the database
pnpm run seed -- --fresh # empty the demo collections first
pnpm run seed -- --keep-settings # keep your own ConfigurationIt never creates customers or orders and never touches existing accounts — the only accounts it adds are the anonymised reviewers the demo reviews belong to.
The live API check
check:api exercises a *running* server end to end — middleware order, auth chains, response envelopes, role rules — which unit tests against controllers cannot. It creates its own admin and customer, and its teardown removes every record it made, including leftovers from a crashed run.
pnpm run check:api # against http://localhost:8000
API_URL=https://api-staging.example.com pnpm run check:apiNext.js gotchas already handled
<html>carriesdata-scroll-behavior="smooth"— Next 16 no longer overrides smooth scrolling during navigation without it, and you land mid-page.- Never call
setStateinside an effect to react to a route change; adjust during render with a previous-value guard. ESLint enforces it. - Per-user reads use
cache: "no-store"— Next's Data Cache keys on the URL, not the session. - A client component must not import a *value* from a module that reaches
next/headers;tscwill not catch it, onlypnpm run builddoes. - A page reads what it shows, once. Shared storefront readers are wrapped in React
cache()and take alimit; the dashboard counts with count queries (/api/contacts/count,/api/stats) and reads grids throughview=table— never fetch a list to measure it or sort 500 rows in JS.