You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
webjs dev / webjs start and npm run dev / npm run start behave differently today, and only the npm-script forms work as expected. The orchestration (Tailwind's css:watch, predev: prisma generate, prestart: prisma migrate deploy) lives in package.json via concurrently + lifecycle hooks, so bare webjs dev/start (the framework primitives) skip all of it. An agent (or human) who runs the bare CLI gets an app with no compiled CSS and stale/absent generated code. This is the #452 gap, and it also blocks offering both webjs db and npm run db:* as equivalent.
Design / approach
Move the orchestration INTO webjs dev/start via a small declarative tasks config in the package.json"webjs" block, and make the npm scripts thin aliases so the two are identical by construction.
webjs dev reads the config, runs the parallel watchers alongside the server (absorbing the concurrently role), and webjs start runs the before steps then the server. npm run dev becomes literally webjs dev, so both forms behave identically. The same applies to webjs db vs npm run db:*: behavior lives in webjs, so both work.
Scope guard: webjs takes on a small, bounded orchestrator role (running the configured commands), declarative and capped, NOT a bundler, so it does not cross the no-build line any more than today's Tailwind watch already does. The dev/prod split still holds: dev runs parallel watchers; prod (start) runs before steps (e.g. migrate) then serves, and must NOT run codegen in a read-only container.
Note: the Drizzle ORM default (separate issue) removes the prisma generate codegen footgun, so once that lands the only orchestration to absorb is Tailwind (dev) and migrate-apply (start), which is a small, well-defined set.
Implementation notes (for the implementing agent)
CLI entry: packages/cli/bin/webjs.js (the dev/start/db command handlers; today the dev preflight hint is ~L101-108 and case 'db' ~L147). The tasks-config reading + orchestration hooks in here.
Server boot: startServer in @webjsdev/server (runtime-neutral listener seam). The parallel watchers run as child processes alongside the listener; ensure clean teardown on SIGINT/SIGTERM (kill children, like concurrently --kill-others-on-fail).
Config surface: the package.json"webjs" block (already used for headers/CSP/redirects/trailing-slash/basePath, typed by WebjsConfig). Add dev/start task fields + JSON Schema + the WebjsConfig type.
Scaffold: packages/cli/lib/create.js generates the scripts + "webjs" block; update so generated scripts.dev/start are thin aliases and the tasks config carries Tailwind/migrate.
Landmines: dogfood: DX papercuts — redirect() defaults to 307; bare webjs dev skips predev #452 (the root cause); running configured shell commands is a capability to keep bounded/declarative (do not turn it into an arbitrary task runner); ensure child-process teardown so webjs dev does not leak a Tailwind watcher; on Bun the listener shell differs (Bun.serve), so verify orchestration + teardown on BOTH runtimes.
Invariants: stays buildless (no bundler); the webjs dev/start primitives must remain runnable with an empty/absent tasks config (a plain app with no Tailwind/DB still works).
Tests + docs: CLI tests that bare webjs dev runs the configured parallel tasks and tears them down; scaffold-integration assertion; a Bun cross-runtime check; docs agent-docs/configuration.md (the "webjs" block) + agent-docs/deployment.md (start before steps) + root AGENTS.md CLI section.
Acceptance criteria
webjs dev and npm run dev produce identical behavior (CSS compiled, watchers running); same for webjs start / npm run start.
Bare webjs dev run on a fresh scaffold serves a fully-working, styled app with no manual pre-steps.
webjs db <sub> and npm run db:* are equivalent.
Configured parallel watchers are torn down cleanly on exit (no leaked processes), verified on Node AND Bun.
A counterfactual proves the orchestration test fails when the tasks config is ignored.
Problem
webjs dev/webjs startandnpm run dev/npm run startbehave differently today, and only the npm-script forms work as expected. The orchestration (Tailwind'scss:watch,predev: prisma generate,prestart: prisma migrate deploy) lives in package.json viaconcurrently+ lifecycle hooks, so barewebjs dev/start(the framework primitives) skip all of it. An agent (or human) who runs the bare CLI gets an app with no compiled CSS and stale/absent generated code. This is the #452 gap, and it also blocks offering bothwebjs dbandnpm run db:*as equivalent.Design / approach
Move the orchestration INTO
webjs dev/startvia a small declarative tasks config in thepackage.json"webjs"block, and make the npm scripts thin aliases so the two are identical by construction.webjs devreads the config, runs theparallelwatchers alongside the server (absorbing theconcurrentlyrole), andwebjs startruns thebeforesteps then the server.npm run devbecomes literallywebjs dev, so both forms behave identically. The same applies towebjs dbvsnpm run db:*: behavior lives in webjs, so both work.Scope guard: webjs takes on a small, bounded orchestrator role (running the configured commands), declarative and capped, NOT a bundler, so it does not cross the no-build line any more than today's Tailwind watch already does. The dev/prod split still holds: dev runs
parallelwatchers; prod (start) runsbeforesteps (e.g. migrate) then serves, and must NOT run codegen in a read-only container.Note: the Drizzle ORM default (separate issue) removes the
prisma generatecodegen footgun, so once that lands the only orchestration to absorb is Tailwind (dev) and migrate-apply (start), which is a small, well-defined set.Implementation notes (for the implementing agent)
packages/cli/bin/webjs.js(thedev/start/dbcommand handlers; today the dev preflight hint is ~L101-108 andcase 'db'~L147). The tasks-config reading + orchestration hooks in here.startServerin@webjsdev/server(runtime-neutral listener seam). Theparallelwatchers run as child processes alongside the listener; ensure clean teardown on SIGINT/SIGTERM (kill children, likeconcurrently --kill-others-on-fail).package.json"webjs"block (already used for headers/CSP/redirects/trailing-slash/basePath, typed byWebjsConfig). Adddev/starttask fields + JSON Schema + theWebjsConfigtype.packages/cli/lib/create.jsgenerates the scripts +"webjs"block; update so generatedscripts.dev/startare thin aliases and the tasks config carries Tailwind/migrate.webjs devdoes not leak a Tailwind watcher; on Bun the listener shell differs (Bun.serve), so verify orchestration + teardown on BOTH runtimes.webjs dev/startprimitives must remain runnable with an empty/absent tasks config (a plain app with no Tailwind/DB still works).webjs devruns the configured parallel tasks and tears them down; scaffold-integration assertion; a Bun cross-runtime check; docsagent-docs/configuration.md(the"webjs"block) +agent-docs/deployment.md(startbeforesteps) + rootAGENTS.mdCLI section.Acceptance criteria
webjs devandnpm run devproduce identical behavior (CSS compiled, watchers running); same forwebjs start/npm run start.webjs devrun on a fresh scaffold serves a fully-working, styled app with no manual pre-steps.webjs db <sub>andnpm run db:*are equivalent.parallelwatchers are torn down cleanly on exit (no leaked processes), verified on Node AND Bun."webjs"block, deployment) + AGENTS.md CLI section updated.