Engineering — Product

What's New in 2026

Every stable Alokai ecosystem release of 2026, with dates and full notes — shipped continuously, adopted on your schedule.

How releases & upgrades work

We operate on a continuous release schedule, so you always have access to our latest features and improvements. But we know your workflow matters — so you have complete control over when to apply updates. Pin the version that suits you and upgrade at your own pace, whenever it best fits your roadmap.

Continuous releasesFeatures and fixes ship regularly across the ecosystem, versioned with semantic versioning so impact is predictable.
Upgrade on your scheduleYou're pinned to a known-good version. Step forward with the Alokai CLI (alokai version upgrade) when you're ready — never forced mid-sprint.
We reach outWe proactively flag security updates and releases of special interest to your project, so nothing important slips past you.

This page mirrors our private GitHub release registry for the @alokai/ecosystem package — the same source our team watches on your behalf.

Major Feature (minor) Patch & maintenance

Release timeline

2.2.4June 16, 2026Patch

Patch Changes

  • FIXED Contentstack Live Preview now stays in sync with the latest draft on every edit. The onLiveEdit callback receives a ready-to-use livePreviewUrl with the live preview query encoded, and the Next.js integration navigates to it with router.replace instead of router.refresh() so the previewed content is re-fetched correctly.
2.2.3May 20, 2026Patch

Patch Changes

  • FIXED env('NEXT_PUBLIC_*') now returns the correct value on the client during the first render and inside initial useEffect calls. Previously, runtime env vars were undefined until shortly after hydration, which could break integrations that read them eagerly — for example, the SAP CDC module's getCdcConfig() returned no API key on first render and failed to load the Gigya SDK.
  • FIXED AlokaiInstrumentation now reliably captures the initial page view and any navigation that happens during page load. Previously, the history-trace script started running after hydration, so the very first page view and any router navigation triggered before that point were not reported.
2.2.2May 20, 2026Patch

Patch Changes

FIXED getProductReferences now normalizes each reference's target via normalizeProductCatalogItem instead of normalizeProduct. The SeProductReferences component renders catalog cards (via ProductCardVertical, which is typed SfProductCatalogItem) — so the data must flow through the catalog-item normalizer chain. With the previous normalizeProduct choice, customer-side addCustomFields.normalizeProductCatalogItem augmentations (e.g. @vsf-modules/compass's required description: string) caused a structural $custom mismatch and failed typecheck in customer projects (ES-2626).

  • CHANGED Improve application performance
2.2.1April 17, 2026Patch

Patch Changes

  • FIXED Normalizer validation errors now include the input object, normalizer name, Zod validation issues, and a link to documentation. Previously, these details were stripped during error serialization, making it difficult to diagnose schema mismatches between e-commerce platforms and the Unified Data Layer.

Patch Changes

  • FIXED Improve facet value matching to handle prefixed values (e.g. color-black, size-10) and prefer superZoom image format for gallery and primary images.

  • Facet normalizer now correctly resolves prefixed facet values by trying exact match first, then suffix match

  • Product images normalizer prefers superZoom format over zoom for highest quality
  • getOptions helper falls back to variantOptions when baseOptions is empty
2.2.0April 1, 2026Feature

Minor Changes

  • ADDED --docker-image-tag flag for store deploy command to allow specifying a custom Docker image tag instead of the auto-generated git commit SHA. Can also be set via the CLI_DOCKER_IMAGE_TAG environment variable.

  • ADDED defineMocker for recording and replaying outgoing HTTP requests in middleware.

```typescript import { defineMocker } from "@alokai/connect/integration-kit";

const { extension, mocker } = defineMocker({ // Enable or disable the extension entirely (default: true) enabled: process.env.MOCKER_ENABLED === "true", // Initial mode: "idle" | "recording" | "replaying" mode: () => "recording", // Allow real network requests for unmatched hosts during replay allowUnmocked: (host) => host.includes("my-trusted-api.com"), // Control which recorded requests are saved and replayed shouldMock: (call) => !call.scope?.includes("internal-service"), // Preload previously saved recordings (required when mode is "replaying") recordings: () => savedRecordings, // Specify custom call duration delayResponse: (call) => call.duration, // Do something with request paths before matching (e.g. strip dynamic segments) filteringPath: (_call, path) => path.replace(/\/api\/v[0-9]+\//, "/api/"), // Do something with the body before matching filteringRequestBody: (_call, body) => body, // Do something with the recordings (e.g. save them to a file) onRecordingStopped: (recordings, allRecordings) => { console.log({ recordings }); }, });

// Programmatic control (no HTTP requests needed): mocker.record(); // Start recording mocker.replay(); // Start replaying mocker.stop(); // Stop recording or replaying mocker.reset(); // Stop and clear all state mocker.getState(); // Get current state ```

Once registered, the mocker also exposes HTTP endpoints on your middleware server:

Endpoint Method Description
/mocker GET View current state and available handlers
/mocker/record GET Start recording outgoing HTTP requests
/mocker/replay GET Start replaying previously recorded requests
/mocker/stop GET Stop recording or replaying
/mocker/reset GET Stop and clear all recordings and state
  • ADDED Payload size limits for Compass workflows. Text and image content is measured after transforms and trimming, right before the LLM call. Default limits: 200KB text, 1MB images. Configurable per workflow via limits in workflow config.

  • ADDED Periodic chat history compaction — older messages are summarized while preserving recent context. Opt in via useCompactHistory in the assistant hook or as an SDK parameter.

  • ADDED Image analysis action and context message rendering — describes images for both chat history and compact chat history.

  • ADDED Compass batch cart removal and clear cart tools for the chatbot workflow.

  • ADDED Handle Set-Cookie headers from commerce API responses by intercepting, streaming, and applying them on the client. Compactor tool-call summaries improved to prevent LLM hallucination of IDs and SKUs.

  • CHANGED Consolidated product search into the main assistant action, removing the separate search-products router step. Category enum strategy for searchProducts tool schema updated accordingly.

  • CHANGED Compass module: replaced defineDynamicTool with unified defineTool in tool definitions.

  • CHANGED Compass analytics action no longer accepts the model option.

Minor Changes — SAPCC only

  • ADDED SAPCC and SAPCC-B2B storefronts now use native URL routing with PLP pages under /c/... and PDP pages under /p/....

Minor Changes — Bloomreach only

  • CHANGED Updated @vsf-modules/search-bloomreach module and @vsf-enterprise/bloomreach-discovery-api. See package changelogs and docs for details.

Minor Changes — SmartEdit only

  • ADDED cms-smartedit now maps the root path / to pageLabelOrId: 'homepage' by default in resolvePages. SmartEdit's default "homepage" label works out of the box on the root route without manual configuration. See migration guide below.

Patch Changes

  • FIXED Deploying a new storefront to CI/CD no longer fails due to missing private package access. Switching from the CMS mock to a real CMS provider no longer leaves behind stale mock references in the codebase.

  • FIXED Updated install.js to target correct file paths after sf-modules refactor (category and product pages). Added replaceAllOrThrow safety guard so install-time regressions throw immediately instead of silently producing broken storefronts.

  • FIXED Resolved tinyexec version conflict causing MODULE_NOT_FOUND error on global CLI install.

  • FIXED Deploying a store with --framework nextjs no longer triggers unnecessary nuxt prepare during composition, preventing CI failures caused by unbuilt workspace packages.

Patch Changes — Compass only

  • CHANGED Upgraded OpenAI models: GPT-4.1 to GPT-5-chat (heavy) and GPT-4.1-mini to GPT-5-mini (medium). Compactor-aware tool-calling instructions are now injected automatically when a workflow has a compactor enabled. Cart data is now returned from the getCart tool so the LLM can resolve line item IDs for remove/update operations. Guided selling prompts updated for GPT-5-chat compatibility.

Migration guide

SmartEdit: configure root path mapping

cms-smartedit now maps / to pageLabelOrId: 'homepage' by default in resolvePages.

  1. Ensure your page label or ID in SmartEdit is set to homepage for your storefront's root page (rename it from / if needed).
  2. Apply the following update in storefront-middleware/sf-modules/cms-smartedit/config.ts:
/* ... */
resolvePages: () => ({
+  '/': {
+    pageLabelOrId: 'homepage',
+  },
  /* ... */
})
2.1.3March 23, 2026Patch

Patch Changes

Added @antfu/ni to the generated project's devDependencies. This dependency is required by alokai-cli integration generate and other CLI commands.

For existing projects: Add @antfu/ni manually by running:

yarn add -W -D @antfu/ni
2.1.2March 19, 2026Patch

Patch Changes

  • FIXED getTypedApiClient now accepts any integration context, not just the primary commerce one. Previously, the function typed its context parameter using the project-specific IntegrationContext from @/types (which resolved to the commerce integration's context type), causing TypeScript errors when calling the helper from within a second integration's methods (e.g. SmartEdit). The parameter is now typed using the base IntegrationContext from @alokai/connect/middleware, which all integration contexts extend.
2.1.1March 11, 2026Patch

Patch Changes

  • FIXED Polyfill Node.js util module in the Nuxt storefront browser build.

Migration guide

Add the following to your nuxt.config.ts under the vite key:

vite: {
  resolve: {
    alias: {
      util: 'unenv/node/util',
    },
  },
},
2.1.0March 9, 2026Feature

Minor Changes

  • ADDED Opt-in method-level circuit breaker granularity. Set granularity: "method" in the circuitBreaker config to isolate breakers per API method — a failing endpoint no longer trips the breaker for the entire integration.
2.0.3March 4, 2026Patch

Patch Changes

  • FIXED Unified 404 error handling in connectCmsPage across all CMS modules. When the API returns 404, null is passed as page to the consumer instead of silently catching all errors or calling notFound() directly. Non-404 errors now propagate correctly.
2.0.2March 2, 2026Patch

Patch Changes

  • FIXED Updated @storefront-ui/nuxt to 3.2.0, ensuring compatibility with Nuxt 4.
  • FIXED extendApiMethods is now optional in defineIntegrationExtension, allowing extensions with only hooks or extendApp.
2.0.1February 23, 2026Patch

Patch Changes

  • FIXED Generate store-specific typecheck turbo tasks for frontend apps so yarn typecheck works in generated and multistore projects.
2.0.0February 23, 2026Major

Major Changes

  • CHANGED Update to Tailwind 4 requires some manual changes in the storefronts code. See the migration guide below for more details.

  • ADDED Circuit Breaker automatically protects your application from cascading failures when backend services become unavailable. When errors exceed a threshold, the circuit breaker blocks requests immediately instead of waiting for timeouts, giving failing services time to recover. Works out of the box with sensible defaults — no code changes required. All circuit breaker events logged with structured metadata. Prometheus metrics for monitoring state transitions and request outcomes. Configurable presets (PRODUCTION, DEVELOPMENT, AGGRESSIVE, TOLERANT, FAST_FAILURE, HARD_FAIL, RELAXED_DEBUG, EXTREME_DEBUG). Please, check Circuit Breaker for more details.

  • FIXED Default error handler now returns JSON for 5xx server errors (consistent with 4xx responses) instead of a plain text message.

  const response = await fetch(url);
  if (response.status >= 500) {
-   const text = await response.text();
-   console.error(text);
+   const body = await response.json();
+   console.error(body.message);
  }
  • CHANGED (Next.js only) Next@16 support

  • CHANGED Upgraded to Nuxt 4. All Nuxt-related packages now require Nuxt ^4.0.0.

  • CHANGED Improved error handling in middleware with better type safety and more reliable error responses. Error responses are now more consistent and predictable — if you're catching and handling errors from API calls, you may notice more detailed error information in 4xx responses (validation errors, not found errors, etc.), better structured error objects with proper error types, and improved error messages for authentication and token-related issues.

  • CHANGED The storefront-middleware app now uses ESM (ECMAScript Modules) instead of CommonJS.

Minor Changes

  • ADDED (@alokai/connect) normalizeGraphQLError helper for normalizing GraphQL errors from any client (Apollo Client, urql, graphql-request) to HttpError. Maps GraphQL error codes to appropriate HTTP status codes and preserves error metadata. The normalizer is client-agnostic and works without requiring the graphql package as a dependency.
  • ADDED (@alokai/connect) withData method on HttpError class, useful for adding context to errors without reconstructing the entire error.
  • ADDED (@alokai/connect) New HTTP Client adapter types for error handling on the middleware layer.
  • ADDED (@alokai/cli) The alokai-cli store build command now accepts the --skip-compose flag.
  • ADDED (@vsf-enterprise/sapcc-types) ASM typings are now available in the sapcc-types package.
  • CHANGED (@alokai/connect) Allow headers to accept async functions and promised header objects.
  • CHANGED (@alokai/connect) The InferCustom type alias now falls back to Record<string, unknown> instead of object.
  • CHANGED (@vsf-enterprise/sapcc-api) Migrate to use axiosErrorAdapter from @alokai/middleware-axios-error-adapter.
  • CHANGED (@vsf-enterprise/magento-api) Migrate to use apolloErrorAdapter from @alokai/middleware-apollo-error-adapter.
  • CHANGED (@vsf-enterprise/contentstack-api) Contentstack normalizers now preserve original snake_case field names from the CMS instead of converting them to camelCase. This allows field names in the storefront to match your Contentstack schema, enabling use of auto-generated TypeScript types.
  • ADDED (@alokai/connect/integration-kit) defineIntegrationExtension factory for creating typed custom extensions with full type inference for API methods, hooks configuration, and extendApp.
  • ADDED (@vue-storefront/next) Runtime environment variable support via env() function. This replaces the next-runtime-env package with a built-in solution that automatically injects NEXT_PUBLIC_* environment variables into the client-side for runtime access. The new solution provides a unified env() function that works on both server and client, automatic injection of NEXT_PUBLIC_* variables via AlokaiProvider, no additional configuration or props needed, and supports runtime environment changes (e.g., in Alokai Console).
  • ADDED (@alokai/cli) Support for ni (package manager agnostic tool), enabling automatic detection and usage of the package manager configured in your project (npm, yarn, pnpm, or bun). This allows developers to use their preferred package manager while the CLI automatically adapts to the project's configuration.
  • CHANGED Refactored the ProductCardVertical component to accept the product prop directly, eliminating the need for prop drilling from ancestor components.

Patch Changes

  • CHANGED (@alokai/connect) Changed lodash to lodash-es for better ESM compatibility.
  • ADDED Missing typescript devDependency in playwright app.
  • CHANGED (@alokai/connect/sdk) When using the middlewareModule, it no longer throws when trying to access a method by a non-string property name and returns undefined instead. This avoids errors in edge cases where React's built-in development hooks inspect SDK modules by accessing Symbol properties.
  • CHANGED Replaced .cursorrules and .windsurfrules with AGENTS.md in generated projects.
  • FIXED (@alokai/cli) CLI now detects the package manager binary path more reliably under Yarn Berry (Yarn 3/4).
  • CHANGED commitlint has been removed from generated projects.
  • FIXED Add typecheck step to generated project CI workflow.
  • FIXED (@alokai/connect) Fixed CONFIG type inference when providing extensions property in identify functions using the Integration interface. Previously, keyof typeof config.configuration.workflows resolved to string | number | symbol; now it correctly resolves to the literal union (e.g., "a" | "b" | "c").
  • CHANGED Replaced Rollup with tsdown for @vsf-enterprise and @alokai package builds.
  • FIXED (@vue-storefront/next) Security vulnerability fix for Next.js (CVE-2025-66478).
  • CHANGED (@vsf-enterprise/storefront-cli) Add --cwd flag to add-module command.
  • FIXED (@alokai/cli) Improved store composition performance by skipping excluded directories and parallelizing file copy operations.
  • FIXED (@alokai/cli) Improved error handling for missing ni commands. The CLI would throw a generic spawn nr ENOENT error when @antfu/ni was not found. It now provides a clear error message with instructions to install @antfu/ni as a dev dependency.
  • FIXED (@vsf-enterprise/module-kit) Fixed improper package.json path resolution when running the add-module command from @vsf-enterprise/storefront-cli.
  • CHANGED (@alokai/connect) Updated logger printer behaviour in dev mode. Logs are now printed in a single line as a formatted message instead of JSON.
  • FIXED (@alokai/connect) Fixed ESM module loading for integrations. The middleware now prefers ESM modules and falls back to CommonJS when ESM fails, with a warning log for debugging.
  • FIXED (@alokai/connect/sdk) SDK no longer crashes with "process is not defined" error when used with browser-first bundlers like Vite.
  • CHANGED Docker containers now use Node.js 22 instead of Node.js 18.

Migration Guide

1. Tailwind 4

  1. Update packages/tailwind-config/package.json: diff{}[packages/tailwind-config/package.json] "exports": { + "./*": "./*.css" - ".": { - "import": { - "default": "./dist/index.mjs", - "types": "./dist/index.d.mts" - }, - "require": { - "default": "./dist/index.cjs", - "types": "./dist/index.d.cts" - }, - "types": "./dist/index.d.ts" - }, - "./nextjs": { - "import": { - "default": "./dist/nextjs.mjs", - "types": "./dist/nextjs.d.mts" - }, - "require": { - "default": "./dist/nextjs.cjs", - "types": "./dist/nextjs.d.cts" - }, - "types": "./dist/nextjs.d.ts" - }, - "./nuxt": { - "import": { - "default": "./dist/nuxt.mjs", - "types": "./dist/nuxt.d.mts" - }, - "require": { - "default": "./dist/nuxt.cjs", - "types": "./dist/nuxt.d.cts" - }, - "types": "./dist/nuxt.d.ts" - } }, "scripts": { "build": "unbuild" }, "dependencies": { - "@storefront-ui/react": "3.0.0-8cb4b8e477376e2cfbbcec1491037c76bbeba33b", + "@storefront-ui/react": "4.0.0", + "@storefront-ui/vue": "3.1.1", - "@storefront-ui/typography": "2.6.1", + "@storefront-ui/typography": "3.1.0", + "@tailwindcss/typography": "^0.5.19", - "tailwindcss": "3.4.4" + "tailwindcss": "4.1.14" },
  2. Remove whole packages/tailwind-config/src directory.
  3. Create packages/tailwind-config/nextjs.css and packages/tailwind-config/nuxt.css files with content: css @import "tailwindcss"; @import "@storefront-ui/react/tailwind-config"; @plugin "@storefront-ui/typography";
  4. Next.js only:

  5. Create apps/storefront-unified-nextjs/app/tailwind.scss:

```diff{}[apps/storefront-unified-nextjs/app/tailwind.scss] +@import 'tailwind-config/nextjs';

+@source '..//*.ts'; +@source '..//*.tsx'; +@source '../../../../../node_modules/@storefront-ui/react'; +@source '../../../../../../node_modules/@storefront-ui/react'; ```

  1. Update apps/storefront-unified-nextjs/app/[locale]/globals.scss:

diff{}[apps/storefront-unified-nextjs/app/[locale]/globals.scss] @use '@/components/cms/page'; - @tailwind base; - @tailwind components; - @tailwind utilities; + @use '../tailwind.scss';

  1. Migrate any customizations from your tailwind.config.ts and your components using Tailwind upgrade guide.
  2. Remove file tailwind.config.ts.
  3. Update `apps/storefront-unified-nextjs/package.json:

diff{}[apps/storefront-unified-nextjs/package.json] (...) -"@storefront-ui/react": "3.0.0-8cb4b8e477376e2cfbbcec1491037c76bbeba33b", -"@storefront-ui/shared": "2.5.1", +"@storefront-ui/react": "4.0.0", +"@storefront-ui/shared": "3.1.0", (...) -"@storefront-ui/typography": "2.6.1", +"@storefront-ui/typography": "3.1.0", +"@tailwindcss/postcss": "^4.1.14", (...) -"tailwindcss": "3.4.4", +"tailwindcss": "4.1.14",

  1. Update the file apps/storefront-unified-nextjs/postcss.config.mjs

diff{}[apps/storefront-unified-nextjs/postcss.config.mjs] (...) plugins: { - tailwindcss: {}, + '@tailwindcss/postcss': {}, }

  1. The SfCheckbox component is now wrapped in a label element by default. To comply with WCAG ARIA requirements, a label must not appear inside another label. Please update all instances where SfCheckbox is used within another label, for example:

diff (...) <label> <SfCheckbox (...) + wrapperAs="span" /> </label>

  1. Nuxt only:
  2. Rename file apps/storefront-unified-nuxt/assets/style.scss to apps/storefront-unified-nuxt/assets/css/tailwind.css and apply changes: diff{}[apps/storefront-unified-nuxt/assets/css/tailwind.css] - @tailwind base; - @tailwind components; - @tailwind utilities; + @import 'tailwind-config/nuxt'; + + @source '../**/*.vue'; + @source '../../../../node_modules/@storefront-ui/vue'; + @source '../../../../../node_modules/@storefront-ui/vue';
  3. Migrate any customizations from your tailwind.config.ts and your components using Tailwind upgrade guide.
  4. Remove file tailwind.config.ts.
  5. In every .vue component that uses Tailwind @apply directive add a line at the top of <style> block: @reference '@/assets/css/tailwind.css';
  6. The SfCheckbox component is now wrapped in a label element by default. To comply with WCAG ARIA requirements, a label must not appear inside another label. Please update all instances where SfCheckbox is used within another label, for example: diff (...) <label> <SfCheckbox (...) + wrapper-tag="span" /> </label>

2. Next@16

  1. Update dependencies:

diff{}[apps/storefront-unified-nextjs/package.json] -"@vue-storefront/next": "6.1.0", +"@vue-storefront/next": "7.0.0", -"next": "14.2.25", +"next": "16.1.1", -"next-intl": "3.26.3", +"next-intl": "4.6.0", -"next-runtime-env": "3.3.0", -"react": "18.3.1", -"react-dom": "18.3.1", +"react": "19.2.3", +"react-dom": "19.2.3", -"@types/react": "18.3.2", +"@types/react": "19.2.7", -"@types/react-dom": "18.3.0", +"@types/react-dom": "19.2.3"

  1. Update apps/storefront-unified-nextjs/next.config.mjs. Move outputFileTracingRoot and typedRoutes from experimental to top-level config:

diff{}[apps/storefront-unified-nextjs/next.config.mjs] output: 'standalone', + outputFileTracingRoot: join(fileURLToPath(import.meta.url), '..', '..', '..', '..'), sassOptions: { + typedRoutes: true, typescript: { - experimental: { - outputFileTracingRoot: join(fileURLToPath(import.meta.url), '..', '..', '..', '..'), - typedRoutes: true, - },

  1. The params and searchParams APIs are now asynchronous. Update all usages accordingly, as shown below:

diff - const { params, searchParams } = props; + const { locale: appLocale } = await props.params; - const { locale: appLocale } = params; + const searchParams = await props.searchParams;

Make sure to update the typings for page props, as shown in the example:

diff interface CategoryPageProps extends PropsWithCmsPage<CategoryPage> { - params: { + params: Promise<{ locale: string; slugs?: string[]; - }; + }>; - searchParams: SearchParams; + searchParams: Promise<SearchParams>; }

  1. next-intl config migration. Routing should be specified according to the new way:

```ts{}[apps/storefront-unified-nextjs/i18n.ts] import { notFound } from 'next/navigation'; import type { LocalePrefix, LocalePrefixMode } from 'next-intl/routing'; // [!code ++] import { getRequestConfig } from 'next-intl/server'; // ... export const locales = ['en', 'de']; // [!code --] export const locales = ['en', 'de'] as const; // [!code ++] export const defaultLocale = 'en'; export const localePrefix: 'always' | 'as-needed' | 'never' = 'as-needed'; // [!code --] export const localePrefix: LocalePrefix = 'as-needed'; // [!code ++] export const timeZone = 'Europe/Berlin';

export default getRequestConfig(async ({ locale }) => { // [!code --] export default getRequestConfig(async ({ requestLocale }) => { // [!code ++] let locale = await requestLocale; // [!code ++] if (!locale) locale = defaultLocale; // [!code ++] // Validate that the incoming locale parameter is valid if (!locales.includes(locale)) notFound(); // [!code --] if (!locales.includes(locale as (typeof locales)[number])) notFound(); // [!code ++]

 return {
   locale, // [!code ++]
   messages: (await import(`./lang/${locale}`)).default(),
   timeZone,
 };

```

```ts{}[apps/storefront-unified-nextjs/config/navigation.ts] import { createLocalizedPathnamesNavigation } from 'next-intl/navigation'; // [!code --] import { createNavigation } from 'next-intl/navigation'; // [!code ++] import type { Pathnames } from 'next-intl/routing'; // [!code --] import { defineRouting, type LocalePrefixMode, type Pathnames } from 'next-intl/routing'; // [!code ++] import type { ComponentProps } from 'react';

import { localePrefix, locales } from '@/i18n'; // [!code --] import { defaultLocale, localePrefix, locales } from '@/i18n'; // [!code ++]

export const pathnames = { // ... } satisfies Pathnames;

export const { Link, redirect, usePathname, useRouter } = createLocalizedPathnamesNavigation({ // [!code --] const routing = defineRouting<typeof locales, LocalePrefixMode, Record<{} & string, string> & typeof pathnames>({ // [!code ++] defaultLocale, // [!code ++] localePrefix, locales, pathnames: pathnames as Record<{} & string, string> & typeof pathnames, // [!code --] pathnames, // [!code ++] }); ```

  1. next-intl now requires you to specify the locale when performing a redirect. Update your code as shown below:
+  const locale = await getLocale();
  redirect({
-    pathname: `/${redirectPath}`,
-    query: { cmsTicketId },
+    href: { pathname: `/${redirectPath}`, query: { cmsTicketId } },
+    locale,
  });
  1. Update all places where you pass headers into middlewareModule — they must now return a Promise:
defineSdkModule(({ buildModule, middlewareModule }) =>
  buildModule(middlewareModule<Endpoints>, {
    /* ... */
    defaultRequestConfig: {
      getConfigSwitcherHeader,
-      headers: () => ({ 'my-header': 'value' }),
+      headers: () => Promise.resolve({ 'my-header': 'value' }),
    },
  }),
);

Note: If you use getRequestHeaders method coming from buildModule you do not have to do anything.

For further information on upgrading React and Next.js, follow the official upgrade guides:

3. Nuxt 4

  1. Update Nuxt and related dependencies

Update your package.json:

```diff{}[package.json] -"nuxt": "^3.13.2", +"nuxt": "^4.0.0", -"nuxt-jsonld": "^2.0.8", -"@nuxtjs/i18n": "^8.5.6", +"@nuxtjs/i18n": "^10.2.3", -"@pinia/nuxt": "^0.5.5", +"@pinia/nuxt": "^0.11.0", -"pinia": "^2.2.6", +"pinia": "^3.0.4",


2. Remove `nuxt-jsonld` module

`nuxt-jsonld` is not compatible with Nuxt 4. Replace `useJsonld` with native `useHead`:

```diff{}[nuxt.config.ts]
 modules: [
-  'nuxt-jsonld',...
 ]

```diff{}[composables/seo/useSeoProduct.ts] -import { useJsonld } from '#jsonld'; -useJsonld({ ... }); +useHead({ + script: [ + { + type: 'application/ld+json', + innerHTML: JSON.stringify({ ... }), + }, + ], +});


3. Migrate i18n to v10 directory structure

i18n v10 enforces a new [directory structure](https://i18n.nuxtjs.org/docs/guide/migrating) where all i18n files must be placed under a root-level `i18n/` directory. Move locale files accordingly:

```bash
mkdir -p i18n
mv lang i18n/lang
mv i18n.config.ts i18n/i18n.config.ts

Update imports in locale index files:

```diff{}[i18n/lang/en/index.ts] -import base from '@/lang/en/base.json'; +import base from '@/i18n/lang/en/base.json';


4. Rename `@alokai/instrumentation-nuxt3-module` to `@alokai/instrumentation-nuxt-module`

```diff{}[package.json]
-"@alokai/instrumentation-nuxt3-module": "...",
+"@alokai/instrumentation-nuxt-module": "...",

```diff{}[nuxt.config.ts] modules: [ - '@alokai/instrumentation-nuxt3-module',... + '@alokai/instrumentation-nuxt-module',... ]


5. Update `@nuxt/image` custom providers to v2 API

Custom image providers must use `defineProvider` from `@nuxt/image/runtime`:

```diff{}[modules/alokai-cloudinary/provider.ts]
-import { getImage as cloudinaryGetImage } from '#image/providers/cloudinary';
-import type { ProviderGetImage } from '@nuxt/image';
+import { defineProvider } from '@nuxt/image/runtime';
+import cloudinaryFactory from '@nuxt/image/runtime/providers/cloudinary';

-export const getImage: ProviderGetImage = (src, options, ctx) => {
+export default defineProvider({
+  getImage: (src, options, ctx) => {
   // ...
-  return cloudinaryGetImage(src, { ...options, baseURL }, ctx);
-};
+    const cloudinary = cloudinaryFactory();
+    return cloudinary.getImage(src, { ...options, baseURL }, ctx);
+  },
+});
  1. Replace useVModel with native computed

VueUse's useVModel returns a Ref type incompatible with Vue 3.5's v-model:

-import { useVModel } from '@vueuse/core';
-const internalModelValue = useVModel(props, 'modelValue', emit);
+const internalModelValue = computed({
+  get: () => props.modelValue,
+  set: (value) => emit('update:modelValue', value),
+});

4. ESM migration for storefront-middleware

To migrate your storefront-middleware app to ESM, follow these steps:

  1. Update apps/storefront-middleware/package.json:

diff{}[apps/storefront-middleware/package.json] { "name": "storefront-middleware", "private": true, "version": "x.x.x", + "type": "module", "main": "./src/index.ts", "license": "MIT", "scripts": { - "build": "NODE_OPTIONS=\"--max-old-space-size=8192\" tspc", + "build": "NODE_OPTIONS=\"--max-old-space-size=8192\" tspc && tsc-alias --resolve-full-paths", "start": "node lib/src/index.js", - "dev": "tspc && concurrently --raw \"tspc --preserveWatchOutput --watch\" \"tsx watch --clear-screen=false src/index.ts\"", + "dev": "tsx watch --clear-screen=false src/index.ts", ... }, "devDependencies": { ... + "tsc-alias": "^1.8.16", ... } }

  1. Update apps/storefront-middleware/tsconfig.json:

diff{}[apps/storefront-middleware/tsconfig.json] { "compilerOptions": { ... - "module": "Node16", - "moduleResolution": "Node16", + "module": "ESNext", + "moduleResolution": "Bundler", + "baseUrl": ".", "rootDir": ".", "outDir": "lib", ... } }

  1. Install the new dependencies:

bash yarn install

  1. If you have any CommonJS-style imports or exports in your middleware code, convert them to ESM syntax:

```diff - const { something } = require('./module'); + import { something } from './module';

  • module.exports = { something };
  • export { something }; ```
  1. Update any dynamic imports to use ESM syntax if needed.

  2. For Nuxt storefronts, ensure typescript.typeCheck: 'build' is set in nuxt.config.ts: ts{}[nuxt.config.ts] export default defineNuxtConfig({ typescript: { typeCheck: 'build', }, });

6. SAP-ASM typings

Migration of SAP-ASM module (follow only if you're using it)

Update typing in apps/storefront-middleware/sf-modules/sap-asm/middleware/api/searchCustomer360.ts:

-import type { Customer360List } from '@vsf-enterprise/sap-commerce-assisted-service-module-webservices-sdk';
import type { SapccIntegrationContext } from '@vsf-enterprise/sapcc-api';
-import type { SearchCustomer360Props } from '@vsf-enterprise/sapcc-types';
+import type { Asm, SearchCustomer360Props } from '@vsf-enterprise/sapcc-types';

import { getTypedApiClient } from '@/integrations/typedApiClient';

export const searchCustomer360 = async (
  context: SapccIntegrationContext,
  args: SearchCustomer360Props,
-): Promise<Customer360List> => {
+): Promise<Asm.Customer360List> => {
/* ... */

7. Contentstack snake_case field names

If you are using Contentstack CMS, update your code to use snake_case field names:

// Dynamic pages
- page.componentsAboveFold
+ page.components_above_fold

- page.componentsBelowFold
+ page.components_below_fold

// Category pages
- page.componentsTop
+ page.components_top

- page.componentsBottom
+ page.components_bottom

// Product pages
- page.componentsBottom
+ page.components_bottom

Component props from CMS content now use snake_case:

// Hero component
- backgroundImage={data.backgroundImage}
+ backgroundImage={data.background_image}

- buttonA={data.buttonA}
+ buttonA={data.button_a}

The module's wrapper components handle this mapping automatically, so if you're using the standard RenderCmsContent component, no changes are needed for component rendering.

8. Runtime environment variables (env())

If you're currently using next-runtime-env, follow these steps:

  1. Update imports

Replace next-runtime-env imports with @vue-storefront/next:

- import { env } from "next-runtime-env";
+ import { env } from "@vue-storefront/next";

Files to update:

  • sdk/options.ts
  • config/image-loaders/cloudinary/cloudinary.ts
  • Any other files using next-runtime-env
  1. Add missing imports in next.config.mjs

If you're using env() in your next.config.mjs, add the import:

+ import { env } from "@vue-storefront/next";
  import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from 'next/constants.js';

  const nextConfig = {
    images: env('NEXT_PUBLIC_IMAGE_LOADER_FETCH_URL') ? cloudinaryConfig : defaultImageConfig,
  };
  1. Remove useEnvContext and PublicEnvScript

Remove any usage of useEnvContext() hook:

- import { useEnvContext } from "next-runtime-env";
+ import { env } from "@vue-storefront/next";

  export function MyComponent() {
-   const env = useEnvContext();
-   const apiUrl = env.NEXT_PUBLIC_API_URL;
+   const apiUrl = env("NEXT_PUBLIC_API_URL");
  }

Remove <PublicEnvScript /> from your layout:

- import { PublicEnvScript } from "next-runtime-env";

  export default function RootLayout({ children }) {
    return (
      <html>
        <head>
-         <PublicEnvScript />
        </head>
      </html>
    );
  }
  1. Remove next-runtime-env package from apps/storefront-unified-nextjs/package.json
1.4.6January 26, 2026Patch

Patch Changes

  • FIXED SAPCC B2B with Smartedit CMS combination was not working. It's working now as expected.

Mirrored from our private GitHub release registry (@alokai/ecosystem); release dates are the corresponding tag dates. We proactively surface security updates and releases of special interest to you — individual package changelogs carry per-package detail.