# Local Development Guide Use this guide after the first quickstart bootstrap when you are working in the repository day to day. It keeps local setup explicit, avoids production secrets, and keeps browser, Playwright, Cypress, and other E2E checks as manual review unless a focused run is explicitly approved. ## Local service prerequisites Install and run these local services before starting the application: - Node.js compatible with the repository runtime expectation. - Corepack with the pinned package manager, `pnpm@10.33.0`. - PostgreSQL for the Prisma-backed application database. - Optional Redis only when queue or worker behavior is in scope. Activate the pinned package manager from the repository root: ```sh corepack enable corepack prepare pnpm@10.33.0 --activate pnpm install ``` ## Local environment placeholders Create a local environment file from the example: ```sh cp .env.example .env ``` Use placeholder-only values in `.env`. Do not copy production secrets, real deployment credentials, live API keys, OAuth secrets, Mailjet credentials, Stripe secrets, database passwords, or webhook signing secrets into local docs or examples. Review these local values before running commands: - `APP_NAME`: local display name. - `SESSION_SECRET`: local placeholder session secret. - `CRYPTO_SECRET`: local placeholder encryption secret. - `DATABASE_URL`: local PostgreSQL connection string consumed by Prisma. - `DIRECT_URL`: optional direct Prisma connection placeholder for maintenance commands. - `APP_BASE_DOMAIN`, `WEB_APP_HOST`, `ADMIN_APP_HOST`, `API_HOST`, and `APP_PROTOCOL`: split-host local routing settings from `.env.example`. - `PORT`: web listener bind port only; keep the default unless you need a different local port. - `WORKER_ENABLED`: set to `true` only when intentionally running worker behavior. - `BULLMQ_REDIS_URL`: local Redis placeholder for BullMQ when the worker is enabled. ## PostgreSQL and Prisma workflow Start PostgreSQL locally and confirm `DATABASE_URL` points to that database. Apply migrations during normal schema work: ```sh pnpm exec prisma migrate dev ``` Check migration status when local schema or generated client state feels stale: ```sh pnpm exec prisma migrate status ``` For disposable bootstrap databases where migrations are not enough, a local schema push may be used deliberately: ```sh pnpm exec prisma db push ``` After schema changes or dependency updates, refresh generated Prisma client artifacts when needed: ```sh pnpm exec prisma generate ``` ## Seed and run the web runtime Seed local development data after the schema is ready: ```sh pnpm seed pnpm run permissions:sync ``` Start the `@toolctrl/web` React Router runtime from the root script; source lives in `apps/web/app`: ```sh pnpm dev ``` Open `http://app.localhost:3000` for the tenant app and `http://admin.localhost:3000` for admin. The root `pnpm dev` command starts only the `@toolctrl/web` runtime; when API work is in scope, run `pnpm --filter @toolctrl/api dev` separately and open `http://api.localhost:3001`. Seeded accounts and placeholder credentials are development conveniences only and must not be reused in production. ## Optional API and worker notes The root script starts the `@toolctrl/web` React Router runtime. `apps/api` contains the runtime-wired Hono `/v1` API app, but it is not required for the default local web loop unless the task explicitly targets API behavior. The worker foundation is opt-in. Redis is not required for ordinary web development. To run worker-related behavior, start Redis locally, set `WORKER_ENABLED=true`, and set `BULLMQ_REDIS_URL` to a local placeholder such as `redis://localhost:6379/0`. Leave `REDIS_URL` as a platform-binding fallback unless that specific environment contract is under test. ## Focused non-E2E verification Use scoped checks that match the files or behavior you changed. Examples: ```sh pnpm exec eslint docs/local-dev.md --max-warnings=0 node scripts/verify-production-docs.mjs node -e "const fs=require('fs');const s=fs.readFileSync('docs/local-dev.md','utf8');for(const r of [/pnpm dev/,/DATABASE_URL/,/PostgreSQL/,/Prisma/,/WORKER_ENABLED/,/BULLMQ_REDIS_URL/,/manual/]) if(!r.test(s)) process.exit(1);" ``` Do not add browser, Playwright, Cypress, or `test:e2e` commands as automatic local development verification. Keep those flows manual unless a specific run is explicitly approved, and record the manual scenario and result in handoff notes. ## Troubleshooting ### PostgreSQL connection failures Confirm PostgreSQL is running, the database exists, and `DATABASE_URL` uses local placeholder credentials. Re-run `pnpm exec prisma migrate status` to distinguish connectivity failures from migration drift. ### Prisma schema or client drift If generated types or local queries disagree with the schema, run `pnpm exec prisma migrate status`, apply the missing migration with `pnpm exec prisma migrate dev`, and regenerate the client with `pnpm exec prisma generate` when needed. For throwaway local databases, recreate the database and run the seed again instead of editing migrations manually. ### Seed problems Confirm migrations or `pnpm exec prisma db push` completed successfully before `pnpm seed`. Run `pnpm run permissions:sync` after role or permission changes. If seed data partially exists, reset only your disposable local database and keep production databases out of the workflow. ### Redis or worker startup problems If worker logs mention Redis or BullMQ, verify Redis is running locally and `BULLMQ_REDIS_URL` is set. If you are not working on queue behavior, unset `WORKER_ENABLED` or keep it false so the worker path remains opt-in. ### Configuration drift Compare `.env` with `.env.example` after pulling changes. Add missing local placeholders, remove accidental real secrets, and keep documentation examples generic.