Bake the Playwright E2E setup + the devsite port-band convention into the template, so new projects inherit it with zero per-project design.
Port-band convention (from devsite)
30xx = dev servers — one per project via package.json#devSite.port (3000–3099).
31xx = e2e web server — derived, never stored: devSite.port + 100 (3100–3199).
Properties: dev + e2e coexist (different bands); no cross-project collision (uniqueness inherited from dev port); nothing beyond the dev port is ever tracked. Optional devSite.e2ePort override for a rare clash. 100 project slots.
E2E harness shape (proven in muxa-io)
- Convex preview deployment per run (
convex deploy --preview-create, seeded via reset) — no separate project, fresh DB per CI run.
- Public
_testing.reset mutation hard-guarded by E2E_TEST_MODE=true (a default preview env var) — fails closed on dev/prod.
- Real WorkOS sign-in in
globalSetup → saved storageState; authenticated + unauthenticated Playwright projects.
- Web server:
CLOUDFLARE_ENV=e2e loads .dev.vars.e2e (localhost redirect at dev+100), VITE_CONVEX_URL from the preview URL file.
- WorkOS requires the exact callback port allowlisted (no port wildcards), so the derived port is registered once per project:
http://localhost:<devPort+100>/api/auth/callback.
Reference implementation
Landing in the muxa-io repo — copy apps/web/e2e/, the _testing.ts mutation, the docs/e2e-testing.md convention doc, and the devsite README port-band section. (Once @dendotai/devsite is extracted, the +100 derivation belongs in it.)
Capture-only issue — do the actual template port in the template repo, not from muxa-io.
Bake the Playwright E2E setup + the devsite port-band convention into the template, so new projects inherit it with zero per-project design.
Port-band convention (from devsite)
30xx= dev servers — one per project viapackage.json#devSite.port(3000–3099).31xx= e2e web server — derived, never stored:devSite.port + 100(3100–3199).Properties: dev + e2e coexist (different bands); no cross-project collision (uniqueness inherited from dev port); nothing beyond the dev port is ever tracked. Optional
devSite.e2ePortoverride for a rare clash. 100 project slots.E2E harness shape (proven in muxa-io)
convex deploy --preview-create, seeded via reset) — no separate project, fresh DB per CI run._testing.resetmutation hard-guarded byE2E_TEST_MODE=true(a default preview env var) — fails closed on dev/prod.globalSetup→ savedstorageState;authenticated+unauthenticatedPlaywright projects.CLOUDFLARE_ENV=e2eloads.dev.vars.e2e(localhost redirect at dev+100),VITE_CONVEX_URLfrom the preview URL file.http://localhost:<devPort+100>/api/auth/callback.Reference implementation
Landing in the muxa-io repo — copy
apps/web/e2e/, the_testing.tsmutation, thedocs/e2e-testing.mdconvention doc, and the devsite README port-band section. (Once@dendotai/devsiteis extracted, the+100derivation belongs in it.)Capture-only issue — do the actual template port in the template repo, not from muxa-io.