v0.6.0

Released: July 26, 2026


This release brings the framework's dependencies up to date: the CLI, @tsdevstack/nest-common, and all templates move to current package versions across the board. A few changes need action on your side; those come first.

Before anything else: patch two frontend files

This one applies to every existing project, even if you never update the framework.

The Radix UI team published @radix-ui/react-slot 1.3.1, a minor release inside the version range every scaffolded frontend already has. That release made Slot a client-only module: it now creates a React context the moment the file loads, and server components run on a React build that cannot do that. The result is that any fresh dependency resolution, a new clone without a lockfile, a CI install, an npm update, picks up 1.3.1 and next build fails with:

TypeError: e.createContext is not a function

on every page that renders a Button or Badge.

The fix is two lines. Add "use client" to the top of both files that import Slot:

// components/ui/button.tsx and components/ui/badge.tsx
"use client"

import * as React from "react"
import { Slot } from "@radix-ui/react-slot"

That is the whole fix. Projects scaffolded after this release already include it. If your build currently works, you have a lockfile pinning the older Slot; patch the two files anyway so the next lockfile refresh cannot break you.

Node 22.12 or newer

The CLI now requires Node.js 22.12.0 or newer. Its command-line parser moved to a major version that runs as native ES modules and needs require(esm) support. If you are on an older 22.x, npm will print an engines warning when you update the CLI; move to a current Node 22 LTS or Node 24 and it goes away.

New monorepos also ship lint-staged 17, which wants a recent Node 22 as well. One Node upgrade covers both.

The CLI is stricter about arguments

Extra arguments to CLI commands now produce an error instead of being silently ignored:

npx tsdevstack sync extra-word
# before: ran sync, ignored "extra-word"
# now: error: too many arguments

If a script in your CI has been passing a stray argument all along, it will start failing loudly. That is the parser doing its job now; fix the invocation and you are done.

Dependency refresh across the stack

What moved, grouped by where it matters:

Backend services. NestJS 11.1.28, Prisma 7.9, class-validator 0.15, and current helmet, ioredis, pg, and bullmq. @tsdevstack/nest-common updated its internals (OpenTelemetry, dotenv) with no API change; it arrives through your existing version range and nothing in your services needs to change. Generated clients now accept class-validator 0.14 or 0.15, so services on either version work with them.

Frontend template. Next.js 16.2.11, React 19.2.8, Tailwind 4.3, lucide-react 1.x, and zod 4. These land in newly scaffolded frontends. Existing frontends keep their own ranges; zod 3 stays fully supported, and moving to zod 4 is a small opt-in migration (steps below).

Cloud SDKs inside the CLI. Updated AWS SDK clients, googleapis 173, Cloud Scheduler 5 and Resource Manager 6 on GCP, and the Azure management SDKs (App Service 19, Resources 8, Storage 20, Key Vault 5). No behavior change in any CLI command.

Lint and test tooling. Service templates move to ESLint 10 with typescript-eslint 8.65. ESLint 10 adds two useful rules you may see fire on your own code: one flags initial values that every branch overwrites, the other asks re-thrown errors to carry the original error as cause. Both catch real issues; the fixes are small and worth taking. The frontend template stays on ESLint 9 for now because the React plugin ecosystem does not support ESLint 10 yet; it will move when upstream does.

Existing monorepos. Nothing is forced. Your services keep their pinned ranges and keep building. When you add a new service, add-service still aligns its dependency versions to what your project already uses, so your monorepo stays on one set of versions and the new packages arrive only when you migrate.

Migrating an existing service (optional)

Each step is independent and per service; take them at your own pace.

class-validator 0.15. Change the dependency to "class-validator": "^0.15.1" and run npm install. The only breaking change upstream is the IsIBAN decorator signature; if you do not use IsIBAN, nothing else changes. Validation behavior for the standard decorators is unchanged.

ESLint 10. Change two devDependencies: "eslint": "^10.7.0" and "@eslint/js": "^10.0.1". Your flat config keeps working. Expect two new rules to flag real code on first run: one reports initial values that every branch overwrites (delete the initializer and keep the explicit type), the other asks re-thrown errors to carry the original as cause (add { cause: error } as the second Error argument). Both are worth taking. Keep the Next.js frontend on ESLint 9 for now; the React plugin ecosystem does not support ESLint 10 yet.

zod 4 (frontend). Change the dependency to "zod": "^4.4.3". The two changes you are most likely to need: error.errors becomes error.issues, and the errorMap option on schema builders becomes error, which accepts a plain string.

A cleaner npm audit

Several widely used packages pin transitive dependencies that currently carry published advisories, including one rated critical in the tar library that lerna pins. Their parents have not re-pinned yet, so the framework now resolves them with scoped overrides, pinning only the affected dependency of the affected parent and nothing else.

New projects get this automatically. For an existing project, add this to the overrides section of your root package.json (replacing the old tar entry if you have one):

"overrides": {
  "lerna": { "tar": "^7.5.19", "js-yaml": "^4.3.0" },
  "nx": { "axios": "^1.18.1", "brace-expansion": "^5.0.8" },
  "prisma": { "@prisma/dev": "^0.24.16" },
  "@nestjs/swagger": { "js-yaml": "^5.2.2" },
  "next": { "postcss": "^8.5.18" }
}

Then delete node_modules and package-lock.json and run npm install. The clean install matters: npm does not re-apply changed overrides to an existing tree, so an in-place install can silently keep the old resolutions, and regenerating only the lockfile is not enough either.

Two things to know before you do it. Regenerating the lockfile refreshes every dependency to the latest version your ranges allow, not just the overridden ones, so apply the button and badge patch from the top of this page first. And commit your current lockfile beforehand, so the regeneration is one reviewable diff you can roll back.

Each entry is temporary by design. When a parent ships a release with a fixed pin, delete its line.

Some advisories will remain visible in npm audit after this and cannot be fixed from your side. Next.js optionally pulls a sharp version that is flagged; the fix arrives with a Next.js release, and it only concerns the image optimizer, not request handling.

One more deserves a heads up because it looks alarming: a brace-expansion advisory currently flags every version below 5.0.8, and since nearly every dev tool depends on it through minimatch, npm audit may show dozens of high findings from this single advisory. There is nothing to fix yet: no patched releases exist for the older lines that tools like eslint, jest, and lerna use, and the patched 5.0.8 is not a drop-in replacement for them. The practical risk is negligible, because these libraries expand glob patterns you wrote yourself, never untrusted input. The noise clears as the ecosystem re-releases; resist the urge to run npm audit fix --force.

More reliable generated client types

Client DTO classes now spell out their types explicitly in their decorators, enum values included, instead of leaning on TypeScript runtime reflection, which cannot tell a nullable number from a plain object. Anything that consumes the generated classes now sees exactly the types the source service declared. Regenerate your clients after updating the CLI to pick this up.

Action

  1. Add "use client" to components/ui/button.tsx and components/ui/badge.tsx in every existing frontend. Do this one regardless of anything else.
  2. Be on Node 22.12 or newer before updating the CLI.
  3. Check CI scripts for stray CLI arguments; they now error.
  4. Optionally add the overrides block above and enjoy a quiet npm audit.