Releasing CraftTS
August 26, 2026 · View on GitHub
Fifteen packages share one version and one Git tag. releasePackages in
tools/release.mjs is the source of truth for that list —
nx.json (release.projects) is aligned on it, and every step below is derived
from it rather than from a hand-kept enumeration.
| npm package | nx project | built from |
|---|---|---|
@craft-ts/core | craft-ts-core | libs/core |
@craft-ts/component | craft-ts-component | libs/component |
@craft-ts/effect | craft-ts-effect | libs/effect |
@craft-ts/dev-tools | dev-tools | libs/dev-tools |
@craft-ts/deploy | craft-ts-deploy | libs/deploy |
@craft-ts/cli | craft-ts-cli | libs/cli |
@craft-ts/deploy-alchemy | craft-ts-deploy-alchemy | libs/deploy-alchemy |
@craft-ts/style | craft-ts-style | libs/style |
@craft-ts/style-testing | craft-ts-style-testing | libs/style-testing |
@craft-ts/i18n | craft-ts-i18n | libs/i18n |
@craft-ts/i18n-effect | craft-ts-i18n-effect | libs/i18n-effect |
@craft-ts/mcp | mcp | packages/mcp |
@craft-ts/log-server | log-server | apps/log-server |
@craft-ts/log-mcp | log-mcp | packages/log-mcp |
@craft-ts/function-registry-mcp | function-registry-mcp | packages/function-registry-mcp |
For now, releases are run locally from the four Git workspaces: this repository, the documentation repository, the main demo repository, and the frontend Effect demo repository.
One local command
Use an automatic stable bump:
npm run release:local -- patch
npm run release:local -- minor
npm run release:local -- major
Or choose an exact version, including a prerelease:
npm run release:local -- 0.6.0-beta.3
Beta releases
Beta versions must currently be specified explicitly. Start a new minor beta series with:
npm run release:local -- 0.6.0-beta.0
Then increment the beta number for each subsequent release:
npm run release:local -- 0.6.0-beta.1
npm run release:local -- 0.6.0-beta.2
The -beta.N suffix automatically selects the npm beta dist-tag, creates the
Git tag v0.6.0-beta.N, and marks the GitHub Release as a prerelease. The
automatic patch, minor, and major arguments produce stable versions; they
do not start or increment a beta series.
Automatic bumps use the highest supported version published across the existing npm packages as their baseline. A newly added package does not need a previous version; it is published as part of the release group:
| Highest npm version | Bump | Resolved version |
|---|---|---|
0.5.8 | patch | 0.5.9 |
0.5.8 | minor | 0.6.0 |
0.5.8 | major | 1.0.0 |
0.5.8-beta.1 | patch | 0.5.8 |
0.5.8-beta.1 | minor | 0.6.0 |
Exact versions accept x.y.z, x.y.z-beta.N, and x.y.z-rc.N. Their npm
dist-tags are respectively latest, beta, and next.
What the command does
Before changing files, the command checks that all four workspaces are clean,
on main, and synchronized with origin/main. It then runs npm ci, validates
the release tooling, runs the unit tests for projects affected since the latest
release tag, and completes the other release gates. E2E tests are temporarily
disabled in local releases. The release
package and documentation artifacts are built once, after confirmation, so the
preview does not build the same artifacts twice. The production preflight keeps
the application build, including demo-effect, as its validation build.
The affected comparison base is the latest reachable v* Git tag. To override
it deliberately, set CRAFT_RELEASE_AFFECTED_BASE to another commit or tag.
The generated-starter gate keeps all 48 runtime/template combinations in its
matrix. It remains available as npm run generated-starters:release, but is
currently skipped automatically by release:local to keep local releases
shorter. The full gate runs the install/typecheck/test/build/E2E suite for 13
representative cells: the six frontend/backend runtime pairs with the complete
feature profile, plus the remaining seven feature combinations on the minimal
plain starter. The full 48-cell executable matrix runs in parallel in
.github/workflows/generated-starters.yml.
Use npm run generated-starters:check for the 13-cell executable smoke,
npm run generated-starters:static for template-surface validation only, and
npm run generated-starters:full for all 48 cells. Set
CRAFT_GENERATED_STARTER_CELL to a one-based cell number to isolate one cell.
Successful Nx test tasks are cached. If a later test fails and the code is
corrected, rerunning the release reuses cached tasks whose inputs did not
change; only affected projects and invalidated tasks run again. Do not use
--skip-nx-cache or npx nx reset when you want this behavior.
After showing the resolved version, it asks for confirmation and:
- updates the fifteen package manifests and
CHANGELOG.md; - rebuilds the fifteen npm packages and VitePress documentation;
- mirrors
apps/demo/srcandapps/demo/publicintocraft-ts-demo; - pins the three CraftTS packages used by the demo (
core,component, anddev-tools) to the exact release version; - mirrors
apps/demo-effect/srcintocraft-ts-demo-effect; - pins
@craft-ts/core,@craft-ts/component, and@craft-ts/effectto the release version, moves@craft-ts/dev-toolstodevDependencies, and setseffectto the workspace-compatible version range in the frontend Effect demo; - removes and ignores the
package-lock.jsonfiles in both demos; - replaces the published documentation with the VitePress build;
- commits the four workspaces;
- publishes all fifteen packages to npm;
- pushes
main, creates and pushesv<version>, and creates the GitHub Release; - pushes the documentation and both StackBlitz demo repositories.
The demos do not run npm install or npm run build; StackBlitz performs those
steps when each project opens.
Required local setup
By default, the workspaces must be siblings:
craft-ts/
craft/
craft-ts-demo/
craft-ts-demo-effect/
Custom paths can be supplied with CRAFT_DOCS_REPO, CRAFT_DEMO_REPO, and
CRAFT_EFFECT_DEMO_REPO.
Before the first release, authenticate once:
npm login
gh auth login
The npm account must be allowed to publish every package in the table above —
in practice, the whole @craft-ts scope. The GitHub account must be allowed to
push all four repositories and create releases.
Safe preview
Run all preflight checks without modifying, publishing, committing, or pushing
anything. Artifact builds happen only after confirmation, so --dry-run does
not build packages or documentation. For the first @craft-ts/* publication, use the exact
version because the new packages do not have npm history yet:
npm run release:local -- 0.7.0-beta.11 --dry-run
For a non-interactive real release, add --yes to skip the confirmation prompt.
Verification
node -e "import('./tools/release.mjs').then(({releasePackages})=>{for(const{name}of releasePackages)console.log(name)})" \
| xargs -n1 -I{} npm view {} dist-tags --json
gh release view v0.6.0 --repo craft-ts/craft-ts
Reading the names from releasePackages keeps this check correct when a package
is added; a hand-written list is how the previous five-package version of this
file went stale.
Then open the published documentation and both StackBlitz examples. If a failure happens after local commits were created, inspect the four workspaces before retrying; do not calculate another bump until every push and npm publication for the resolved version has completed.