managing-dev-servers
Rules for starting, monitoring, and stopping local development servers (nuxt dev, nest start, npm/pnpm run dev, pnpm build --watch, Playwright, etc.) across all lt-dev workflows. Prefers `lt dev up/down/status/tunnel` for projects registered with the lt CLI — these serve every project under stable HTTPS URLs (`<slug>.localhost`, `api.<slug>.localhost`) via Caddy (via a dedicated LaunchAgent/systemd-user unit, NOT `brew services caddy`) and inject project-specific env vars (BASE_URL, APP_URL, NUXT_PUBLIC_*, NSC__MONGOOSE__URI, NUXT_PUBLIC_STORAGE_PREFIX, HOST=127.0.0.1, NODE_EXTRA_CA_CERTS, API_URL/SITE_URL legacy aliases) so multiple lt projects can run in parallel without port collisions or auth cross-wiring. `lt dev tunnel` exposes a running project externally via a Cloudflare Quick Tunnel. Falls back to the run_in_background / pkill contract for non-lt projects to prevent orphaned processes blocking the Claude Code session ("Unfurling..."). Activates whenever a long-running process must be started for manual validation, Chrome DevTools MCP debugging, TDD iterations, framework linking, or any E2E test run. Referenced by building-stories-with-tdd, developing-lt-frontend, generating-nest-servers, and contributing-to-lt-framework.
What this skill does
# Managing Dev Servers Local development servers (`npm run dev`, `nuxt dev`, `nest start`, `pnpm build --watch`, `pnpm test:watch`, etc.) are long-running processes. If they are started uncontrolled in the background, Claude Code cannot reliably reclaim them, the session blocks on "Unfurling..." without consuming tokens, and the user must press ESC to continue. Apply these rules whenever you start any such process — regardless of whether you are inside a TDD cycle, a framework-linking session, a manual validation run, or an MCP-driven debugging flow. ## Decision tree — what to run before any dev server The plugin's `detect-lt-dev` hook injects one of three context blocks at the top of every prompt. Use that block as your switch: 1. **"Active lt-dev project" with `session: yes`** — Project registered AND running. Use the URLs from the block. Do nothing extra; for browser tests / API calls use the URLs as-is. 2. **"Active lt-dev project" with `session: no`** — Project registered, **not** running. For the **Playwright/E2E suite** run `lt dev test` (isolated parallel stack on a dedicated `<slug>-test` DB — never touches dev data, auto-teardown). For **manual browser tests, Chrome DevTools MCP, or API probes**, run `lt dev up` first. 3. **"lt-Stack project detected — not yet migrated"** — Project IS an lt project but the registry entry is missing. **Proactively run `lt dev init` first** (idempotent, safe — patches legacy ports, registers, updates CLAUDE.md). Then `lt dev up`. **Do NOT start `pnpm dev` / `pnpm start` as a workaround.** 4. **No block injected** — Not an lt project. Use the classic `run_in_background: true` + `pkill` pattern documented below. If `lt dev up` later complains that Caddy is missing or the daemon is not running, run `lt dev install` first. One-time per machine: ```bash brew install caddy # macOS (Linux: https://caddyserver.com/docs/install) lt dev install # writes + bootstraps the dedicated LaunchAgent / systemd-user unit sudo -E HOME="$HOME" caddy trust # trust the local Caddy root CA system-wide ``` **Do NOT use `brew services start caddy`** — its plist hardcodes `--config /opt/homebrew/etc/Caddyfile` and crash-loops against the lt-dev Caddyfile at `~/.lenneTech/Caddyfile`. `lt dev install` owns its own dedicated service (`tech.lenne.lt-dev-caddy`) to sidestep that entirely. **The `-E HOME="$HOME"` on `caddy trust` is also mandatory** — without it sudo switches HOME to `/var/root`, caddy fails to find its user-scoped CA, and the trust install silently does nothing. ## Preferred for lt-Projects: `lt dev up` ```bash lt dev install # One-time per machine (dedicated LaunchAgent/systemd unit + Caddyfile stub + CA reminder) lt dev uninstall # Remove the lt-dev service (symmetric counterpart; `--purge` also drops Caddyfile + logs) lt dev init # Once per project (idempotent — patches + register + CLAUDE.md) lt dev up # Start API + App behind Caddy with stable HTTPS URLs lt dev status # Show what is running for THIS project lt dev status --all # List every registered project + running state lt dev down # Stop processes + remove Caddy block + clear ENV bridge lt dev doctor # Diagnose Caddy / CA / DNS / port issues lt dev test # ISOLATED Playwright E2E: parallel stack + dedicated DB, auto-teardown lt dev test down # Tear the isolated test stack down (residue-free) lt dev tunnel # Foreground Cloudflare Quick Tunnel — expose the App publicly (--api for the API) ``` **`init` and `install` auto-chain (idempotent, one hop, no recursion):** running `lt dev init` on a machine that isn't set up runs `lt dev install` first; running `lt dev install` inside an un-initialized project runs `lt dev init` afterwards. So the minimal first run in a fresh project is just **`lt dev init`** then **`lt dev up`** — no need to remember the install step. Opt out with `--skip-install` (init) / `--skip-init` (install). The former name `lt dev migrate` still works as an alias for `lt dev init`. ## E2E tests (Playwright + API) **API E2E tests (TestHelper, in-process)** — run unchanged. They start a NestJS test module in-process on a dynamic port and never touch Caddy. Use `pnpm run test:e2e` in `projects/api` as before. **App E2E tests (Playwright) — preferred: the isolated `lt dev test` (below).** For ad-hoc runs against the dev session, the `lt dev up` bridge still applies: - `lt dev up` writes a `<root>/.lt-dev/.env` bridge file containing `NUXT_PUBLIC_SITE_URL`, `NUXT_PUBLIC_API_URL`, storage prefix, DB URI, and `NODE_EXTRA_CA_CERTS` (Caddy root CA path). - `lt dev init` injects a tiny `// >>> lt-dev:bridge >>>` block at the top of `playwright.config.ts` that auto-loads this file. Result: any Playwright invocation (`pnpm test:e2e`, `npx playwright test`, VS Code Playwright Extension, JetBrains test runner) automatically picks up the active URLs and trusts the local CA — no parent-shell env required. - Existing env-aware patterns (`process.env.NUXT_PUBLIC_SITE_URL || 'http://localhost:3001'`) keep working as fallback when `lt dev` is not active (CI, classic local dev). **`lt dev test` — ISOLATED parallel E2E stack (preferred for the suite):** spins up a SECOND, fully separate stack that runs PARALLEL to — and never touches — your `lt dev up` dev session: - Own URLs (`<slug>-test.localhost` / `api.<slug>-test.localhost`), own internal ports + Caddy block, and a **dedicated DB `<slug>-test`** — separate from both the dev DB (`<slug>-local`) and the API-test DB (`<slug>-e2e`). - Playwright's `global-setup` resets that dedicated DB **once, before the first test** — so a developer keeps working in their own environment while E2E runs, a run never pollutes dev data, and tests may build on each other within the run. - The test API runs COMPILED (`node dist`) for stable long suites; the App is a Nuxt dev server. A separate `.lt-dev/.env.test` bridge carries the test URLs + DB. - **Auto-teardown** at the end — processes, Caddy block, env bridge, session file, registry entry all removed (residue-free) — with a Ctrl-C signal trap and a stale-session reclaim on the next run. ```bash lt dev test # isolated Playwright E2E in projects/app (auto-teardown) lt dev test --keep # leave the test stack up afterwards (debug) lt dev test down # tear the isolated test stack down (residue-free) lt dev test --api # API tests in projects/api (already isolated on `<slug>-e2e` — no stack) lt dev test --debug # PWDEBUG=1 + headed lt dev test -- --ui login.spec.ts # forward args to Playwright ``` **Do NOT run the Playwright suite against the `lt dev up` dev session** — that pollutes (and `global-setup` would reset) your dev DB. Use `lt dev test`. **Limit local Playwright runs to new + affected specs to keep TDD loops fast.** The full Playwright suite is slow and runs in **CI**. During local development / TDD, default to `lt dev test -- <spec>` (or `lt dev test -- tests/e2e/<file>.spec.ts`); the equivalent for non-lt-projects is `scripts/e2e-fast.sh -- <spec>` / `pnpm dlx playwright test <spec>`. Backend Unit + API stay unrestricted — they're fast. Only run the **full** local Playwright suite when the user explicitly asks (or when an orchestrator like `production-ready` calls for it). > **Requires** the lt CLI version that ships the isolated test session. Older lt CLIs run `lt dev test` against the dev session (legacy behavior). The project's `playwright.config.ts` global-setup must reset only the active `MONGO_URI` DB and allow-list `<slug>-test`. **Why `lt dev` is the preferred path:** - Stable URLs per project (`https://crm.localhost`, `https://api.crm.localhost`) — bookmarks, IDE-run-configs, and Chrome DevTools MCP commands stay valid across restarts. - Cross-wiring impossible: API only trusts its own App origin (Better Auth `trustedOrigins` derived from `APP_URL`), A
Related in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.