feat: release @decocms/tanstack and @decocms/nextjs in lockstep with blocks at 8.3.0
Stacked on #697 (P5). Part 6 of the v8 framework packages stack: #693 → #694 → #695 → #696 → #697 → this.
What changes
- Lockstep publish.
.releaserc.json's publish allowlist isblocks tanstack nextjsplus the sevenapps-*. Every release publishes all ten at one version, even a package with no change.@decocms/tanstackand@decocms/nextjspublish frommainonlatest. - Peer ranges. The
apps-*took@decocms/blocksasworkspace:*independencies, which publishes as an exact pin, so a blocks patch release put a second blocks next to an app. They now take it as a peer,^8.3.0, withworkspace:*indevDependencies, as the bindings already do. scripts/sync-versions.mjswrites the release version, rewritesworkspace:ranges only indevDependencies, and refuses to release when an in-repo package is a plain dependency or a peer floor is above the release version.tests/release.test.ts(38 tests): allowlist =packages/, blocks then the bindings first; every dependent takes blocks as^8.3.0peer; the sync on a copy of the manifests (8.3.0, a later 8.4.1, refusing 8.2.4 and a plain dependency). New since the PO review: for each of the ten packages, every export target (through conditional branches) has thetypes+source+defaultshape (or is plain JS shipped fromsrc, as@decocms/nextjs/config), andnpm packwould ship each of those files and no test or fixture. That covers the clients' new helper subpaths,@decocms/apps-vtex/imageand@decocms/apps-shopify/image(#694); a mutation that dropssrc/image.tsfromapps-vtex'sfilesfails it.- CI. The build job's plain-Node import of every built export already walks every subpath, so it imports the new
/imagesubpaths; the job now also runstests/release.test.tsagainst the dist it built. - Docs. CLAUDE.md (allowlist, peer-range rule), README (the packages publish
tscoutput indist/plus asourcecondition, not plain.ts), release workflow comment (ten packages).
Dry run (repeated after the PO review)
In a throwaway clone (deleted afterwards), origin/main plus this stack squashed into one feat: commit, with the real config (GitHub plugin included; dry run only):
semantic-release --dry-run --no-ci: "The next release version is 8.3.0" (last tagblocks-v8.2.3).- The prepare step (
VERSION=8.3.0 node scripts/sync-versions.mjs && bun run build): all ten manifests at 8.3.0, noworkspace:left; tanstack, nextjs and everyapps-*havepeerDependencies["@decocms/blocks"] = "^8.3.0". - The publish step rendered from the config, with
npm publish --dry-run:+ @decocms/blocks@8.3.0,+ @decocms/tanstack@8.3.0,+ @decocms/nextjs@8.3.0and the seven apps, all "with tag latest". No test files in the binding tarballs. - The
apps-vtexandapps-shopifytarballs holddist/image.{js,d.ts}(+ maps) andsrc/image.ts; the blocks tarball has nostudiomodule; the nextjs tarball has its owndraft,studioandStudioBridgemodules. - The ten tarballs installed together with npm:
npm ls @decocms/blocksshows one copy, every other packagededuped(one@decocms/blocks/package.jsonon disk). Plain Node imported all 38 exports of the installed packages,/imagesubpaths included, with no failure;@decocms/blocksexports neitherSTUDIO_ORIGINSnorDRAFT_PARAM, and@decocms/nextjs' and@decocms/tanstack's copies are equal. No package was published.
Dry run after the PO decisions of 2026-10-15
Re-run after merging #697 (with #693–#696's decisions: NODE_ENV dev mode, isNextDev removed, first-match multivariate, deco schema --check, leading asset-host strip, edit shortcut on by default). Throwaway local repos, deleted afterwards; nothing was pushed or published:
semantic-release --dry-run --no-ci(commit analyzer and release notes, against a local bare mirror of the repo with its tags): last tagblocks-v8.2.3, "The next release version is 8.3.0".- Prepare step: all ten manifests at 8.3.0, no
workspace:left; build passes. npm publish --dry-run --tag latestfor all ten: each exits 0. The nextjs tarball (54 files) has nodevmodule.- blocks, tanstack, nextjs, apps-vtex and apps-shopify installed together: one
@decocms/blocks(the othersdeduped); plain Node imported all 31 of their exports, and@decocms/nextjsexports noisNextDev. tests/release.test.ts: 38/38.
Tests
bun run check,bun run build,skills:check,skills:readme:check: pass.bun run test: 2,396 passed, 5 failed, all known or load timeouts: DS-2 indelivery.cli.test.ts, and timeouts under full-suite load indelivery.cli.test.tsDS-5,guides.cli.test.tstr-13,protocol/storage/fs/git.test.tsandschema.test.ts. Rerun on their own: the first three files pass apart from DS-2, andschema.test.tspasses 58/58 alone.
For the PO: landing and npm commands (not run)
Landing as 8.3.0. semantic-release releases on every push to main. To ship all three at 8.3.0 together, land the stack as one commit on main: merge this PR into #697, #697 into #696, and so on down to #693, then squash #693 into main with a feat: title. If the PRs land on main one by one, P1 alone becomes 8.3.0 and the bindings first publish at a later minor (their ^8.3.0 peer would then also need raising to that version). If another feat: reaches main first, the release is 8.4.0: raise the peer floors in this PR to ^8.4.0 before landing.
Before landing (7.x). Merge #698 first (7.x branch). Today 7.x publishes both bindings with --tag latest, so the next 7.x release would take latest back from 8.3.0. #698 moves them to latest-7.
npm commands, run by the PO with an npm owner login, before the stack lands:
# 1. Keep v7 installable by tag. Use 7.79.6, or the newest 7.x if a 7.x release has run since
# (merging #698 releases 7.79.7 and sets latest-7 itself; then skip this step).
npm dist-tag add @decocms/tanstack@7.79.6 latest-7
npm dist-tag add @decocms/nextjs@7.79.6 latest-7
# 2. Rewrite the 8.0.0 deprecation (it says "use @latest (7.x)", which is wrong once latest is 8.3.0).
npm deprecate @decocms/tanstack@8.0.0 "Published by mistake. Use ^8.3.0 for v8, or 7.x for v7."
npm deprecate @decocms/nextjs@8.0.0 "Published by mistake. Use ^8.3.0 for v8, or 7.x for v7."
# 3. Deprecate the two prereleases (not deprecated today).
npm deprecate @decocms/tanstack@"8.0.0-next.0 || 8.1.0-next.0" "Prerelease. Use ^8.3.0 for v8, or 7.x for v7."
npm deprecate @decocms/nextjs@"8.0.0-next.0 || 8.1.0-next.0" "Prerelease. Use ^8.3.0 for v8, or 7.x for v7."
latest moves to 8.3.0 by itself when the release publishes; no command is needed for it. Check afterwards:
npm view @decocms/tanstack dist-tags # { latest: '8.3.0', 'latest-7': '7.79.x' }
npm view @decocms/nextjs dist-tags
Other things to know:
- Trusted Publishing. The bindings were last published from the 7.x branch. npm's trusted publisher names the repo and the workflow file (
release.yml), not a branch, somainshould be accepted. If either package's trusted publisher is tied to a GitHub environment, add it formainbefore landing, or its publish fails while the other nine succeed. - No CI check against the oldest blocks in range yet. The plan lists one. It needs blocks 8.3.0 on npm first, so it's a follow-up. Until then, the rule (CLAUDE.md) is to raise every peer floor together when a package starts using a newer blocks API, and
sync-versions.mjsrefuses a floor above the release. npm publishprints "repository.url was normalized" for every package, as it already does today. It's harmless.
https://claude.ai/code/session_01WNwbSEePYNcY5YCgqZURig
Main refresh (2026-10-17, 6ce49dcf)
- Merged P5
73b9b98dinto this branch (normal merge, no conflicts), then merged up the stack to M2 #707. - Gates at the top of the stack (M2
5131a3c1):bun run check,bun run build,skills:check,skills:readme:checkpass.bun run test(2 GB memory cap): 122 files pass, 1 skipped; 2,745 tests pass, 95 skipped, 0 fail. DS-2 now passes (fixed on main by #709); no timeouts this run. - CI on this PR's new head: all checks pass.
🤖 Generated with Claude Code