1.1
absolute imports become mandatory, page-view metering ships turned on, and @alokai/cli 2.0.0 changes how stores are recognised
Showing every integration. Set your stack in Preferences and this page hides what isn't yours.
20.* || >=22.14.0Plan a real afternoon for this release, because every project has work to do. storefront-middleware becomes a composite TypeScript project, and all four apps switch from relative to absolute imports. That's an eleven-part migration you apply by hand, with no automatic path. @alokai/cli goes to 2.0.0 and treats a store as a template unless its alokai.config.json entry has a deployment field, so a project that changes nothing can find its stores silently reclassified as templates. Upgrading @alokai/connect, @vue-storefront/next, or @vue-storefront/nuxt turns on Alokai page-view metering in production: a script that sends a trace on every navigation, and two new middleware endpoints. You turn it off with an environment variable.
Highlights
Your apps must move to absolute imports, and storefront-middleware becomes a composite TypeScript project
@alokai/cli@vue-storefront/eslint-configAbsolute imports inside storefront-middleware don't resolve from the apps unless the apps reference the middleware as a TypeScript project. That's why the switch to absolute imports and the composite middleware are one change.
storefront-middleware declares compilerOptions.composite: true. storefront-unified-nextjs and storefront-unified-nuxt consume it as a TypeScript Project Reference, so absolute imports inside it resolve from both apps.
@vue-storefront/eslint-config 5.1.0 adds a multistore rule group that rewrites relative imports to aliased ones. @alokai/cli adds store prepare, which generates the paths and include arrays in per-store tsconfig.json files. Store tsconfig files inherit shared configuration from the root config instead of each store carrying a private copy.
The upgrade doesn't apply any of this for you. The tsconfigs, eslint configs, turbo.json, and app package.json files are yours, so you make every edit by hand, in order, and then run yarn lint:fix to rewrite the imports across every app and store. Skip it and tsc stops resolving imports inside storefront-middleware from the apps, and your Playwright integration tasks run before the middleware build they now depend on.
Don't stop halfway, or your build fails altogether. Making the middleware composite breaks the type check that next build runs, and the step's last part is what fixes it.
Page-view metering is now on by default in production
@alokai/connect@vue-storefront/next@vue-storefront/nuxt@alokai/instrumentation@alokai/instrumentation-next-component@alokai/instrumentation-nuxt2-module@alokai/instrumentation-nuxt3-moduleAlokai measures fair-use accounting in page views, so the core packages now count them without any configuration.
Four new packages measure page views for fair-use accounting, and the three core packages wire them in with no configuration. In the middleware, createServer in @alokai/connect registers POST /alokai-trace, a Prometheus page-view counter. It also registers GET /alokai-metrics, which serves that counter plus the prom-client default process metrics - heap, CPU, and event loop.
In Next.js, AlokaiProvider in @vue-storefront/next renders an inline beforeInteractive next/script that POSTs to <origin>/api/alokai-trace on every history navigation. In Nuxt, the @vue-storefront/nuxt module installs a plugin that does the same from router.beforeEach. Both scripts switch themselves off in development. The middleware endpoints don't - createServer registers them in every mode.
On Alokai Cloud, you've already agreed to page-view metering, and /alokai-metrics is blocked at the edge. If you host the middleware yourself, it exposes /alokai-metrics on whatever hostname your middleware answers, in development too. If you host a storefront yourself, a production build starts sending traces. To turn it off, set the opt-out variable to true for each app you host yourself: ALOKAI_IS_SELF_HOSTED for the middleware, NEXT_PUBLIC_ALOKAI_IS_SELF_HOSTED for Next.js, and NUXT_PUBLIC_ALOKAI_IS_SELF_HOSTED for Nuxt.
@alokai/cli 2.0.0 treats a store without a deployment field as a template
@alokai/cliYou couldn't parametrise a template store in alokai.config.json, because giving a store any config at all made it a deployable store.
A store is a template unless its alokai.config.json entry has a deployment field. Before, a store was a template only when its entry had no config at all. A template store can now be parametrised in alokai.config.json.
If a store you build, run, or deploy has no deployment field in its entry, the CLI now skips it as a template. Nothing errors - store build, store dev, and store deploy just stop composing it. Check every entry in alokai.config.json before you run anything, and add a deployment field to each store that isn't a template.
@vsf-enterprise/middleware-headers 3.0.0 changes your CDN cache key and stops ignoring per-method headers
@vsf-enterprise/middleware-headersUnder multistore and integration routing, the content the middleware returns depends on x-alokai-middleware-config-id and x-alokai-locale, but the Vary header didn't list them.
The extension appends x-alokai-middleware-config-id and x-alokai-locale to the Vary header of every response it touches, merged with any Vary you set yourself. The top-level cacheControl option no longer suppresses the per-method headers section. A Cache-Control you set for a specific method now wins over the general one instead of being a no-op.
Your CDN cache key widens, so expect a lower hit rate until the new key warms up. There's nothing to change in your config for this.
If you set a per-method Cache-Control alongside a top-level cacheControl, that header was silently doing nothing and now takes effect. That changes what your CDN caches, from a config you never touched. Drop the per-method header to keep what your CDN did before, or leave it to accept the new behavior.
All changes by area
Every change in 1.1 has one entry here, grouped by area. The highlights, from above and from the patch sections, are here too, marked with a star. Open an area to see its changes, and open a change to read why it changed and what changed. The upgrade guide from 1.0.2 to 1.1.0 collects the migration steps for the whole line.
Alokai ConnectAction needed4 changes
changed @vsf-enterprise/middleware-headers 3.0.0 changes your CDN cache key and stops ignoring per-method headers highlight Action needed
Your CDN cache key widens, so expect a lower hit rate until it warms up. A per-method Cache-Control you set alongside a top-level cacheControl was silently doing nothing and now takes effect - drop it to keep what your CDN did before, or leave it to accept the new behavior.
What changedWhy, and what changed ▸
Under multistore and integration routing, the content the middleware returns depends on x-alokai-middleware-config-id and x-alokai-locale, but the Vary header didn't list them.
The extension appends x-alokai-middleware-config-id and x-alokai-locale to Vary on every response it touches, merged with any Vary you set yourself. The top-level cacheControl option no longer suppresses the per-method headers section, so a Cache-Control set for a specific method now wins over the general one.
@vsf-enterprise/middleware-headerschanged context.getApiClient is typed as returning a promise Action needed
If you call context.getApiClient in a custom middleware method or extension, add await to every call. An unawaited call that used to typecheck now fails tsc.
What changedWhy, and what changed ▸
Federated code could call context.getApiClient without await and still typecheck. The call always returned a promise at runtime, so that code was already broken.
context.getApiClient in @alokai/connect's MiddlewareContext is typed as returning Promise<ApiClient>.
@alokai/connectchanged The config switcher falls back to the default config id
A request that used to be rejected for a missing header now resolves against the default config.
What changedWhy, and what changed ▸
@alokai/connect/config-switcher accepts a request with no config header at all and uses the default config id. Before, it required the header.
@alokai/connectremoved dotenv is gone from the Connect logger
You don't need to add it. Your root package.json has carried "dotenv": "16.4.7" in dependencies all along, so the import 'dotenv/config' in your middleware keeps resolving through the workspace root.
What changedWhy, and what changed ▸
@alokai/connect/logger no longer depends on dotenv, so you can use the logger in React Native projects. A project generated at 1.1.0 declares dotenv 16.4.7 directly in apps/storefront-middleware/package.json instead.
@alokai/connectStorefrontAction needed9 changes
changed Your apps must move to absolute imports, and storefront-middleware becomes a composite TypeScript project highlight Action needed
The upgrade doesn't apply any of this for you - you edit the tsconfigs, eslint configs, turbo.json, and app package.json files by hand, in order. Don't stop halfway, or your build fails: making the middleware composite breaks the type check that next build runs.
What changedWhy, and what changed ▸
Absolute imports inside storefront-middleware don't resolve from the apps unless the apps reference the middleware as a TypeScript project. That's why the switch to absolute imports and the composite middleware are one change.
storefront-middleware declares compilerOptions.composite: true, and both storefront apps consume it as a TypeScript Project Reference. @vue-storefront/eslint-config 5.1.0 adds a multistore rule group that rewrites relative imports to aliased ones. @alokai/cli adds store prepare to generate the paths and include arrays in per-store tsconfig.json files, and store tsconfig files inherit shared configuration from the root config.
@alokai/cli@vue-storefront/eslint-configadded Page-view metering is now on by default in production highlight Action needed
On Alokai Cloud, you've already agreed to page-view metering, and /alokai-metrics is blocked at the edge. A middleware you host yourself exposes /alokai-metrics on your own hostname, and a storefront you host yourself sends traces from a production build, until you set the opt-out variable to true for each app you host yourself: ALOKAI_IS_SELF_HOSTED for the middleware, NEXT_PUBLIC_ALOKAI_IS_SELF_HOSTED for Next.js, and NUXT_PUBLIC_ALOKAI_IS_SELF_HOSTED for Nuxt.
What changedWhy, and what changed ▸
Alokai measures fair-use accounting in page views, so the core packages now count them without any configuration.
createServer in @alokai/connect registers POST /alokai-trace and GET /alokai-metrics on your middleware. AlokaiProvider in @vue-storefront/next renders an inline beforeInteractive next/script that POSTs to <origin>/api/alokai-trace on every history navigation. The @vue-storefront/nuxt module installs a plugin that does the same from router.beforeEach. Both scripts switch themselves off in development, but the middleware endpoints don't.
@alokai/connect@vue-storefront/next@vue-storefront/nuxt@alokai/instrumentation@alokai/instrumentation-next-component@alokai/instrumentation-nuxt2-module@alokai/instrumentation-nuxt3-modulefixed Nuxt hydration warnings on the size and colour chips and the checkout layout are fixed
These files belong to your project, so your copies keep the old markup until you port the change.
What changedWhy, and what changed ▸
The size filter chips in components/CategoryFilters/FilterSize.vue and the product page's size and colour chips in components/ProductAttributes/ProductAttributes.vue get real id/for pairs. layouts/checkout.vue wraps the checkout layout's loader and slot in <ClientOnly>. Together, they stop the hydration warnings in storefront-unified-nuxt.
removed The no-JavaScript price fallback is dropped from the Nuxt product cards
Both files are yours, so your copies keep the <noscript> markup until you port the change.
What changedWhy, and what changed ▸
components/ui/ProductCard/ProductCard.vue and components/ui/PurchaseCard/PurchaseCard.vue no longer carry the <noscript> DecoratedPrice fallbacks. A client with JavaScript disabled no longer sees prices. SkeletonGeneric gains min-h-10 to hold the space instead.
changed The Nuxt lazy-load types are renamed per composable
The types live in your own project, so the old names keep working until you rename them yourself.
What changedWhy, and what changed ▸
LazyLoadFn and LazyLoadFnReturn in composables/useLazyProduct/types.ts become ProductLazyLoadFn and ProductLazyLoadFnReturn. The pair in composables/useLazySearchProducts/types.ts becomes SearchProductsLazyLoadFn and SearchProductsLazyLoadFnReturn.
added The Alokai version is readable from the Nuxt app config and the composed .env
If you upgraded rather than generated, the upgrade never touches that version field. The value in your composed .env stays at the version that generated your project - a project created at 1.0.0 and upgraded to 1.1.0 reports 1.0.0. Nothing in the storefront reads the variable, so there's nothing to repair. It's worth knowing because the value is public, and because later releases resolve other things from that same field.
What changedWhy, and what changed ▸
The @vue-storefront/nuxt module injects NUXT_PUBLIC_ALOKAI_VERSION into Nuxt's appConfig. @alokai/cli writes the variable into the composed .env, from the version field of .alokai/package.json or the root package.json. It's NEXT_PUBLIC_ALOKAI_VERSION for storefront-unified-nextjs and NUXT_PUBLIC_ALOKAI_VERSION for storefront-unified-nuxt.
@vue-storefront/nuxt@alokai/clichanged The generated app manifests gain a typecheck script and pin their tooling Action needed
Your own build still runs only next build until you change it, and you must change it - next build can't type-check a composite project. The shared eslint pin is also why the composite-project step offers a root resolutions entry as its fallback.
What changedWhy, and what changed ▸
next build can't type-check a composite project. The type check has to move to a compiler that honours project references, and the manifest has to declare it as a script.
apps/storefront-unified-nextjs/package.json gains a typecheck script, and build becomes yarn typecheck && next build. eslint is pinned from ^9.22.0 to 9.23.0, and prettier 3.3.2 is added as a devDependency. The same eslint pin lands in apps/storefront-middleware/package.json, apps/playwright/package.json, and apps/storefront-unified-nuxt/package.json.
Two other pins move with it, and they're yours to take or leave: express from 4.20.0 to 4.21.2 in the middleware, and happy-dom from 14.12.3 to 15.10.2 in the Nuxt app.
fixed The register-b2b module picks up a userAlreadyExists message and new test ids Action needed
If you installed the register-b2b module, port all of it to your copies. Until you do, they still carry the old test ids, and the module's Playwright suite keeps failing on locators that no longer match.
step →What changedWhy, and what changed ▸
The Nuxt register form had no message for an existing user. The module's files are copies in your project, so a fix to the module's source doesn't reach them.
The Nuxt register form in apps/storefront-unified-nuxt/components/RegisterForm/RegisterForm.vue gains a userAlreadyExists error message. data-testid="success-modal" moves onto the modal element itself. The message textarea's test id becomes message-input, and the module's Playwright suite is fixed to match.
fixed The re-order module binds its defineProps result Action needed
If you installed the re-order module, the file is a copy in your project, so the one-line fix is yours to apply.
step →What changedWhy, and what changed ▸
The component references props.product.id but never binds the defineProps result.
The re-order module's apps/storefront-unified-nuxt/components/CartPageProductCard/CartPageProductCard.vue assigns its defineProps result to props.
CLI & toolingAction needed13 changes
changed @alokai/cli 2.0.0 treats a store without a deployment field as a template highlight Action needed
If a store you build, run, or deploy has no deployment field in its entry, the CLI now skips it as a template. Nothing errors - store build, store dev, and store deploy just stop composing it.
What changedWhy, and what changed ▸
You couldn't parametrise a template store in alokai.config.json, because giving a store any config at all made it a deployable store.
A store is a template unless its alokai.config.json entry has a deployment field. Before, a store was a template only when its entry had no config at all.
@alokai/cliadded store lint is a new command, and the root lint scripts cover stores
You get the command with the CLI. The root scripts are yours, so they keep skipping stores until you extend them - the composite-project step does that as one of its parts.
What changedWhy, and what changed ▸
store lint is a new @alokai/cli command. A generated project's root lint and lint:fix scripts now lint the stores directory as well as the base apps.
@alokai/cliadded store rename changes a store id
You no longer edit alokai.config.json and the store directory by hand to rename a store.
What changedWhy, and what changed ▸
alokai-cli store rename --store-id sapcc-b2c --new-store-id sapcc-my-brand renames a store.
@alokai/cliadded build, dev, start and test take a --turbo-option passthrough flag
You can pass a Turbo option on the command line. Before, the only way to set it was to edit turbo.json.
What changedWhy, and what changed ▸
build, dev, start, and test in @alokai/cli accept a --turbo-option flag. The flag passes custom options through to the underlying Turbo task.
@alokai/cliadded alokai.config.json honours an ignorePaths field
You can declare the paths you want the CLI to leave out of a store in config, instead of working around them.
What changedWhy, and what changed ▸
alokai.config.json now honours an ignorePaths field.
@alokai/cliadded integration generate can use local boilerplate code and lints what it writes
A generated integration arrives formatted to your own lint rules. You can try boilerplate changes without publishing them first.
What changedWhy, and what changed ▸
integration generate in @alokai/cli takes a flag to use local boilerplate code instead of a published version. It lints the files it generates with the project's lint:fix script.
@alokai/clichanged store test runs Playwright store tests through Turbo
Store test runs use Turbo's task graph and caching instead of running outside it.
What changedWhy, and what changed ▸
store test now runs Playwright store tests through Turbo.
@alokai/clifixed store deploy retries its docker prerequisite check
A deploy no longer stops because docker was slow to answer for a moment.
What changedWhy, and what changed ▸
store deploy retries its docker prerequisite check instead of failing on the first attempt.
@alokai/clifixed Dev-mode URLs keep their suffixes, aliased imports resolve, and new stores get next-env.d.ts
You get all three fixes with the CLI version. A store you added before this release still lacks its next-env.d.ts.
What changedWhy, and what changed ▸
In dev mode, @alokai/cli keeps the suffixes of the middleware API and SSR URLs, so http://localhost:4000/api is no longer truncated. Aliased imports resolve in the IDE. A new store created with store add gets the next-env.d.ts file its Next.js app was missing.
@alokai/clichanged A generated project's root manifest gains an alokai script and a new postinstall
No package delivers any of this. yarn alokai <command> comes from that root script, so your project doesn't have it until you add the script yourself.
What changedWhy, and what changed ▸
A project generated at 1.1.0 has an alokai script in its root package.json, mapped to alokai-cli. Its postinstall runs a new scripts/init-script.mjs, which copies .env.example to .env.
The generated project no longer gets scripts/lint-stores.mjs at all. scripts/init-script.mjs and scripts/utils.mjs replace it.
changed A generated project's .gitignore covers the yarn install state and generated tsconfigs
Your own .gitignore doesn't change, so git tracks the files store prepare writes into your substores until you add the entries.
What changedWhy, and what changed ▸
A generated project's .gitignore now lists .yarn/install-state.gz, oclif.manifest.json, and the autogenerated tsconfig.json files that store prepare writes into substores.
changed A generated project's pre-commit hook runs prettier, and its test:integration takes Playwright options
Both changes are yours to port. cross-env is already in your root package.json, so you have nothing to install for it.
What changedWhy, and what changed ▸
Every packages/lint-staged-config/*.mjs now runs prettier --write before eslint --fix in the pre-commit hook, so a commit reformats as well as lints.
In apps/playwright/package.json, test:integration becomes cross-env playwright test ${PLAYWRIGHT_OPTIONS:-""}. That's what lets the new --turbo-option flag reach Playwright.
fixed Four tooling packages carry fixes of their own
All four reach you the next time you generate a project or install a module, not through a dependency you declare.
What changedWhy, and what changed ▸
@vsf-enterprise/file-modifier 3.1.0 creates a missing .env file before it modifies it, instead of failing. @vsf-enterprise/module-kit 3.1.1 fixes the CMS module installation schema and changes how the kit is bundled. @alokai/boilerplate-integration 1.1.0 fixes AI context file paths that pointed at directories that don't exist.
@vsf-enterprise/storefront-cli 3.0.2 no longer validates --version up front. It accepts any string, and an unknown one now errors with the list of available versions. It also installs the version package inside node_modules in its temp directory, and its manifest gains a dependency that was missing.
@vsf-enterprise/file-modifier@vsf-enterprise/module-kit@alokai/boilerplate-integration@vsf-enterprise/storefront-cliBigCommerce1 change
fixed The BigCommerce product API stops throwing on null product fields
A catalogue with incomplete product data no longer takes the request down.
What changedWhy, and what changed ▸
@vsf-enterprise/bigcommerce-api 8.0.1 no longer throws TypeError: Cannot read properties of null (reading 'toLowerCase') when a product's condition is null or undefined. It also tolerates a missing product availability status and a product option with no displayName.
@vsf-enterprise/bigcommerce-apiSmartEditAction needed2 changes
changed SmartEdit resolves component references before normalization Action needed
If you override a SmartEdit normalizer that resolves references itself, it now does that work twice, on data that's already resolved. Drop that logic and read the resolved components from the input.
step →What changedWhy, and what changed ▸
Every normalizer had to resolve component references itself, although the API can resolve them once before it hands the data over.
@vsf-enterprise/smartedit-api 4.0.0 resolves component references before normalization instead of during it. Your normalizers receive components whose references are already resolved.
getReferenceFieldsForComponent now accepts object-style reference definitions. { type: "string", path: "fieldName" } is now the recommended form, and plain strings still work. It also supports dot-notation nested paths such as slides.componentId or sections.rows.cells.componentId.
@vsf-enterprise/smartedit-apifixed SmartEdit normalizers fix nested resolution, slot placement and urlLink
Nested component resolution changes with the bump. The slot placement fix lives in the default normalizePage, so a page template that looked wrong under 3.0.0 renders as authored unless you override normalizePage.
What changedWhy, and what changed ▸
In 4.0.0, nested components resolve recursively. normalizePage places slots by their position rather than by their name, so they land in the right place in the page template. normalizeComponent returns urlLink.
@vsf-enterprise/smartedit-api