Workflows
End-to-end flows driven by the CLI. Workflows coordinate workers, pipelines, and services to deliver a complete task (init → build → watch/test → publish). They are orchestration only; low-level logic lives in engine components.
What They Are
- Thin coordinators that call workers and services in a defined order.
- Source of truth for user-visible behavior, exit codes, and logs.
- Deterministic: same inputs produce the same outputs.
- Composable: some workflows run others (e.g.,
watchrunsbuildthentest).
See also: Engine internals — engine
Workflow Docs
- Init — init
- Build — build
- Watch — watch
- Test — test
- Publish — publish
- Generators — add-page, add-route, add-job, add-test
How They Fit In
- CLI selects a workflow (
webstir <command>), builds anAppWorkspace, then invokes the engine. - Workflows call workers (frontend/backend/shared) and pipelines (HTML/CSS/TS) to do the actual work.
- Long-running behavior (serving, watching, proxying, reload) is handled by services. See services and servers.
- All paths and file names come from the workspace and constants. See workspace.
Workers & DI
- Contracts:
IWorkflowWorker: common worker contract (BuildOrder, InitAsync, BuildAsync, PublishAsync).IFrontendWorker: extendsIWorkflowWorkerwithAddPageAsyncfor page scaffolding.
- DI pattern: all workers are registered as
IWorkflowWorkerand workflows injectIEnumerable<IWorkflowWorker>. - Filtering: workflows choose which workers to run based on project mode (client-only, server-only, fullstack). The
add-pageworkflow resolves the singleIFrontendWorker, which now shells out towebstir-frontend add-pagefor scaffolding.
Initiation
- CLI commands (primary):
webstir init [options] [directory]webstir build [--clean]webstir watch(default when no command is provided)webstir testwebstir publish- Generators:
webstir add-page <name>,webstir add-route <name> [--method <METHOD>] [--path <path>] [--fastify],webstir add-job <name> [--schedule <expression>],webstir add-test <name-or-path>
- Programmatic chaining: workflows may invoke others as steps (e.g.,
watch→build→test→ start services). - CI usage: run discrete workflows with standard exit codes to gate builds.
Responsibilities
- Validate inputs and workspace invariants; fail fast with clear errors.
- Decide order of operations and which workers/services to involve.
- Surface concise, actionable logs and return appropriate exit codes.
- Never hand-roll path strings; use workspace helpers and constants.
Lifecycle (By Workflow)
init
- Create a project from embedded templates (frontend, backend, shared, types).
- Normalize names/paths; write a ready-to-run structure.
- Output: scaffolded source tree under
src/**plustypes/.
build
- Compile TypeScript with
tsc --build, then bundle JavaScript with esbuild for fast development builds. - Process CSS imports and merge page HTML into
build/. - Copy Images, Fonts, and Media to
build/frontend/{images|fonts|media}/**. - Perform incremental work when possible; keep output readable with source maps in dev.
- Output:
build/frontend/**,build/backend/**.
watch
- Run an initial
buildandtest. - Start the dev web server and Node API server; begin watching
src/**. - On frontend change: rebuild affected assets and notify browsers via SSE reload.
- On backend change: rebuild backend code and restart the Node process.
test
- Build (if needed) and execute compiled tests in Node.
- Resolve the testing provider from
webstir.providers.jsonorWEBSTIR_TESTING_PROVIDER, installing overrides when required. - Produce a pass/fail summary with CI-friendly exit codes.
publish
- Produce optimized, fingerprinted assets in
dist/per page. - Use esbuild to bundle, tree-shake, minify JavaScript, and perform automatic code-splitting with production optimizations.
- esbuild extracts shared dependencies into
chunks/folder; manages content hashing for entries (index-<hash>.js) and chunks (chunks/*-<hash>.js). - Minify HTML/CSS, remove comments and source maps, and rewrite HTML links using per-page manifests.
- Optimize Images and Fonts when tools available, then copy to
dist/frontend/{images|fonts|media}/**. - Output:
dist/frontend/pages/<page>/index.html,index-<hash>.js,index.<hash>.css,manifest.json, plusdist/frontend/chunks/*-<hash>.js.
generators
add-page <name>: scaffoldindex.html|css|tsundersrc/frontend/pages/<name>/.add-route <name> [--method <METHOD>] [--path <path>] [--fastify]: add a route towebstir.module.routesand optionally scaffold/register a Fastify handler.add-job <name> [--schedule <expression>]: createsrc/backend/jobs/<name>/index.tsand add a jobs manifest entry.add-test <name-or-path>: scaffold a.test.tsin the nearesttests/.
Contracts & Guarantees
- Source roots:
src/frontend/**,src/backend/**,src/shared/**,types/**. - Dev outputs:
build/frontend/**,build/backend/**(includingbuild/frontend/{images|fonts|media}/**). - Prod outputs:
dist/frontend/pages/<page>/**with per-page manifests,dist/frontend/chunks/**for shared code, plus static assets underdist/frontend/{images|fonts|media}/**. - Dev server proxies
/api/*to the Node process duringwatch. - Base HTML requires
<main>insrc/frontend/app/app.html.
Errors & Exit Codes
- Validation failures (missing base HTML, bad flags, TS errors, failing tests) return non-zero exit codes.
- Logs name the failing stage and file when possible.
Adding a New Workflow
- Keep it thin: coordinate, don’t implement pipelines in the workflow.
- Use
AppWorkspaceand constants; avoid manual path strings. - Compose existing workers/services; prefer small, testable steps.
- Define clear inputs, outputs, and exit behavior; add E2E tests that lock down the contract.