Alokai versions
Showing every integration. Set your stack in Preferences and this page hides what isn't yours.
The legacy version refers to all releases prior to the introduction of the new versioning model (before version v0).
You can upgrade your Alokai project to the next compatible version by running yarn alokai version upgrade.
Looking for what changed in a package before Alokai ecosystem 1.0.0? The per-package history is archived in the legacy package changelogs.
Pick where the project is and where it is going. The table shows every package version in between for your stack, and the upgrade guide beneath it lists every step in that range.
Upgrade guide
2.4.2 → 2.5.0· covers2.5.0·15 steps
1Apply the versions from the tableAll projects
Applies to: All projects · Only if: always
Run the upgrade command first; it moves the core packages to the target column. Then set every remaining highlighted row to its target version in `package.json` and reinstall. The table above is already filtered to your stack, so every row in it is yours to move; nothing else in the release asks for a version change.
yarn alokai version upgrade
# then bump the remaining rows in package.json and run yarn install2Annotate the return type of createRequestFunction in your axios OpenAPI client2.5.0CLI & tooling
Applies to: All projects · Only if: your middleware has an integration generated with integration generate --template openapi --http-client axios, whose common.ts defines createRequestFunction
Find the generated clients. The generator writes them under apps/storefront-middleware/integrations/<name>/src/middleware/generated/, and this also finds clients you placed elsewhere under integrations/:
find apps -type f -name common.ts -path '*/integrations/*' -not -path '*/node_modules/*' -exec grep -lF 'createRequestFunction' {} +In each file, give the inner function an explicit return type and cast the request result:
export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) {
- return <T = unknown, R = AxiosResponse<T>>(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+ return <T = unknown, R = AxiosResponse<T>>(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH): Promise<R> => {
const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || axios.defaults.baseURL || basePath) + axiosArgs.url};
- return axios.request<T, R>(axiosRequestArgs);
+ return axios.request<T, R>(axiosRequestArgs) as Promise<R>;
};
}This release's packages require axios 1.20.0 or newer, so after the upgrade yarn install resolves a version whose types fail the unannotated file with TS2527: The inferred type of 'createRequestFunction' references an inaccessible 'unique symbol' type. Pinning axios back below 1.19 would make the file compile but keeps the HTTP/2 unhandled-error advisory GHSA-542g-h47m-68v8 open; remove such a pin from resolutions if you added one.
Redo this edit after every integration generate, because the generator still emits the file without it.
3Pass a normalized class to SfScrollable in ProductSlider and the CMS Scrollable2.5.0Nuxt
Applies to: Nuxt · Only if: the lockfile resolves vue at 3.5.30 or newer
Check which Vue your lockfile resolves. The line after the entry prints it:
grep -A1 '^"\?vue@' yarn.lockBelow 3.5.30 the build is unaffected, and the edit below is still correct to make now. At 3.5.30 or newer nuxt build fails with TS2322: Type 'ClassValue' is not assignable to type 'string | Record<string, any> | unknown[] | undefined' until it is made.
Find every copy of the two components still forwarding the raw class, per-store overrides included:
find apps -type f -name Scrollable.vue -not -path '*/node_modules/*' -exec grep -lF '$attrs.class ??' {} + ; find apps -type f -name ProductSlider.vue -not -path '*/node_modules/*' -exec grep -lF ':wrapper-class="wrapperClass"' {} +In components/cms/page/Scrollable.vue:
+import { normalizeClass } from 'vue';- :wrapper-class="$attrs.class ?? ''"
+ :wrapper-class="normalizeClass($attrs.class)"In components/ProductSlider/ProductSlider.vue:
+import { normalizeClass } from 'vue';- :wrapper-class="wrapperClass"
+ :wrapper-class="normalizeClass(wrapperClass)"In components/ProductSlider/types.ts, type the prop with Vue's own ClassValue, so it accepts conditional values and object syntax:
-import type { HTMLAttributes } from 'vue';
+import type { ClassValue } from 'vue';
- wrapperClass?: HTMLAttributes['class'];
+ wrapperClass?: ClassValue;4Configure a FusionAuth application for Connect Admin before you deploy2.5.0Connect Admin
Applies to: Connect Admin · Only if: the Connect Admin editor is enabled on a production deployment, through CONNECT_ADMIN_FEATURE_EDITOR=true or CONNECT_ADMIN_ROLE=admin
Ask Alokai for a FusionAuth application for your deployment, then set its id and secret in the environment of every middleware that serves the editor:
CONNECT_ADMIN_FUSIONAUTH_APPLICATION_ID=<your application id>
CONNECT_ADMIN_FUSIONAUTH_CLIENT_SECRET=<its client secret, if it needs one>Do this before the deployment that moves @alokai/connect-admin to 1.1.0. From that version a production editor with no application id answers every authoring call with 404 and {"error":"Not found"}, and the UI shows "Sign-in isn't set up". getFormValues keeps serving the storefront either way. If you adopted the module at an earlier release, none of your .env files carry these variables, because only a fresh module install writes them.
Set CONNECT_ADMIN_FUSIONAUTH_URL only when your SSO host isn't https://sso.vuestorefront.cloud.
Don't use Alokai's shared demo application in production. The module installer writes its id into the middleware .env.example so a fresh install works at once, and a production process still using it logs [connect-admin] CONNECT_ADMIN_FUSIONAUTH_APPLICATION_ID is still Alokai's shared DEMO application. Anyone registered for it can sign in to this deployment and change its configuration. Replace it with your own FusionAuth application. once at start. Nothing is blocked while it's there.
Keep CONNECT_ADMIN_FEATURE_EDITOR=true if that's how your deployment enables the editor; it still works and means the deployment serves both the editor and getFormValues. Set CONNECT_ADMIN_ROLE=admin instead on a dedicated admin deployment that should serve the editor and no runtime reads. store deploy sets that role itself on the Connect Admin app it creates.
Once an application id is set, sign-in is required on your own machine too. Leave the variable unset locally to keep developing without it.
5Move the AI review plugin to 0.3.12.5.0CLI & tooling
Applies to: All projects · Only if: you want AI code review running on your pull requests or merge requests
Check which version of @alokai/cli-plugin-review you have. The upgrade doesn't move it, and it lives in the CLI's own plugin store, so package.json, node_modules and the lockfile don't show it:
./node_modules/.bin/alokai-cli pluginsIf it isn't listed and you don't want AI review, there's nothing to do. Above 0.3.1, leave it - the install below would downgrade it. Otherwise, install 0.3.1:
./node_modules/.bin/alokai-cli plugins install @alokai/cli-plugin-review@0.3.10.3.1 behaves exactly like 0.3.0; it is rebuilt against this release's dependencies. The plugin registers the ai review and ai fix commands for pull requests on GitHub and merge requests on GitLab.
6Move Storefront UI to a version with the spin-slow keyframes2.5.0Storefront
Applies to: Storefront · Only if: packages/tailwind-config/package.json pins @storefront-ui/react below 4.0.2 or @storefront-ui/vue below 3.1.3
List every Storefront UI pin your project declares. The Tailwind theme that was missing the keyframes is the one packages/tailwind-config imports, and the apps pin the same packages:
find packages apps -maxdepth 4 -type f -name package.json -not -path '*/node_modules/*' -exec grep -Hn '@storefront-ui/' {} +In packages/tailwind-config/package.json, move both theme packages to the versions this release pins. 4.0.2 and 3.1.3 are the first with the fix:
- "@storefront-ui/react": "4.0.1",
+ "@storefront-ui/react": "4.0.3",
"@storefront-ui/typography": "3.1.0",
- "@storefront-ui/vue": "3.1.2",
+ "@storefront-ui/vue": "3.1.4",Move the app pins to match, so one copy of each package is installed: @storefront-ui/react to 4.0.3 in apps/storefront-unified-nextjs/package.json, and @storefront-ui/nuxt to 3.3.3 in apps/storefront-unified-nuxt/package.json. Then run yarn install. The next store build or store dev recomposes the stores.
7Remove the out-of-root Tailwind @source path2.5.0Next.js
Applies to: Next.js · Only if: a tailwind.scss in your project declares the @source path with six .. segments to @storefront-ui/react
Find every copy of the file carrying the longer path. Multistore projects keep per-store overrides, so this searches them too:
find apps -type f -name tailwind.scss -not -path '*/node_modules/*' -exec grep -lF '../../../../../../node_modules/@storefront-ui/react' {} + || trueNothing printed means your files are already right. In each file printed, delete the longer path and keep the one above it:
@source '../**/*.ts';
@source '../**/*.tsx';
@source '../../../../../node_modules/@storefront-ui/react';
-@source '../../../../../../node_modules/@storefront-ui/react';The remaining path reaches the project root's node_modules from every store built into .out/<store-id>/storefront-unified-nextjs, so no utility classes are lost. On Next.js 16.2 the longer path is ignored and nothing fails; on 16.3 next build aborts with TurbopackInternalError: ... leaves the filesystem root when the project sits inside another repository, so make the edit now rather than when you move next.
8Re-export the onRequestError instrumentation hook2.5.0Next.js
Applies to: Next.js · Only if: you are adopting this release's onRequestError hook from @vue-storefront/next/instrumentation
Add the hook to the re-export in apps/storefront-unified-nextjs/instrumentation.ts, once @vue-storefront/next is at 10.1.0:
-export { register } from '@vue-storefront/next/instrumentation';
+export { onRequestError, register } from '@vue-storefront/next/instrumentation';Next.js then calls the hook the moment the server captures a render, route-handler, server-action or proxy error, and every such error is logged with its route in every environment, next dev and preview deployments included. In production the console bridge skips what the hook already reported, so each error still produces one log entry.
9Provision Firestore for Connect Admin2.5.0Connect Admin
Applies to: Connect Admin · Only if: you run Connect Admin on a production deployment
Enable Firestore in the customer project on Google Cloud and grant the service account the Cloud Datastore User role. No composite index is needed.
Add a TTL policy to each of these collections, so finished runs, archived outputs, logs, the key-value store and expired locks are removed by Firestore itself:
workflowRunsonexpiresAtworkflowRunOutputsonexpiresAtworkflowRunLogsonexpiresAtfeatureEditorKvonexpiresAtfeatureEditorLocksonuntil
Set the three required variables in the deployment's environment:
CONNECT_ADMIN_FIRESTORE_PROJECT_ID=<gcp project id>
CONNECT_ADMIN_FIRESTORE_CLIENT_EMAIL=<service account email>
CONNECT_ADMIN_FIRESTORE_PRIVATE_KEY=<service account private key>Set CONNECT_ADMIN_FIRESTORE_DATABASE_ID only when the database isn't (default). On a shared dev or test project, set CONNECT_ADMIN_FIRESTORE_COLLECTION_PREFIX per person so each one's data lives in its own namespace; the TTL policies then go on the prefixed collection names.
Nothing migrates by hand. The versions already in Redis are carried over on the first read after the variables are set. Until they're set, the editor runs on Redis, logs a warning the first time someone opens it, and shows a banner that can't be dismissed, and a cache flush still loses the authored configuration.
10Pass a view reference to getFeatureVersions and drop the shared cursor2.5.0Connect Admin
Applies to: Connect Admin · Only if: your middleware code calls getFeatureVersions or reads currentId from the versions it returns
Find the call sites in your middleware code. The module's own files don't call it:
find apps -type f \( -name '*.ts' -o -name '*.tsx' \) -path '*/storefront-middleware/*' -not -path '*/node_modules/*' -exec grep -lE 'getFeatureVersions\(|\.currentId' {} + || trueNothing printed means there's nothing to do. Otherwise, pass the feature and the view instead of the feature id, because each form view now has its own history:
-const versions = await getFeatureVersions(context, "merchandising");
+const versions = await getFeatureVersions(context, { featureId: "merchandising", viewId: "rules" });Remove reads of currentId. Which version is open belongs to each operator's browser now, and the server record no longer carries a cursor. VersionStatus is "live" | "saved"; a version stored earlier with the retired draft status comes back as saved.
11Move the root zod resolution to 4.2.12.5.0Compass
Applies to: Compass · Only if: the root package.json has resolutions.zod below 4.2.1
Check the pin the module installer wrote into your root package.json:
grep -n '"zod"' package.json || trueNothing printed means no resolution is set and @alokai/compass installs its own zod. Otherwise move it to 4.2.1. The value you see depends on the release you adopted the module at; a 2.4.2 install wrote 4.1.12:
"resolutions": {
- "zod": "4.1.12"
+ "zod": "4.2.1"
}Then run yarn install. The resolution is root-only, so one install is enough.
With an older resolution in place, every cache hit on a tool with a cache.key logs Failed to read/write dynamic schema from cache and falls back to the schema function. Calls validate correctly, but the schema cache does nothing until the pin moves.
12Register the config switcher on the Compass integration2.5.0Compass
Applies to: Compass · Only if: you are adopting this release's configId eval variants or config switcher profiles
Take this release's extensions/configSwitcher/index.ts into apps/storefront-middleware/sf-modules/compass/. Re-running npx @vsf-enterprise/storefront-cli add-module compass writes this release's module files, but it overwrites every edit you made under sf-modules/compass, so where you have edits, copy the file from a project where the module was installed at this release instead. The file reads ALOKAI_COMPASS_CONFIG_SWITCHER_PROFILES as a JSON map of config id to a partial middleware configuration, holds code-declared entries beside it, and fails the start when ALOKAI_COMPASS_CONFIG_ID names no entry.
Register the extension in sf-modules/compass/config.ts:
+import type { ApiClientExtension } from '@alokai/connect/middleware';
+
+import { configSwitcherExtension } from '@/sf-modules/compass/extensions'; export const config = defineConfig({
// ...
+ extensions: (extensions: ApiClientExtension[]) => [...extensions, configSwitcherExtension],
location: '@alokai/compass/server',Let the two variables through turbo in the root turbo.json. store dev runs through turbo, whose strict env mode drops them otherwise:
"globalPassThroughEnv": [
+ "ALOKAI_COMPASS_CONFIG_ID",
+ "ALOKAI_COMPASS_CONFIG_SWITCHER_PROFILES",
// ...
]Then name an entry from a variant in eval-config.json:
{
"variants": [
{ "name": "baseline" },
{ "name": "concise", "configId": "concise-prompt" }
]
}With no entries declared, the switcher does nothing and every request gets the base configuration.
13Move @alokai/cli-plugin-compass to 1.2.02.5.0Compass
Applies to: Compass · Only if: the CLI reports @alokai/cli-plugin-compass at a version below 1.2.0
Check which version of @alokai/cli-plugin-compass you have. The upgrade command doesn't move it, and it lives in the CLI's own plugin store, so grepping node_modules or yarn.lock shows nothing:
./node_modules/.bin/alokai-cli pluginsIf it isn't listed, you have nothing to do. Above 1.2.0, leave it - the install below would downgrade it. Otherwise, install 1.2.0:
./node_modules/.bin/alokai-cli plugins install @alokai/cli-plugin-compass@1.2.01.2.0 is the first version that reads configId, storeId and the judge block from eval-config.json.
If you adopted the Compass module, check the postinstall script in your root package.json too. The installer appends an unpinned plugins install @alokai/cli-plugin-compass to it, which reinstalls the newest published plugin on every yarn install and undoes any pin you write.
14Keep SmartEdit slot wrappers layout-transparent2.5.0SmartEdit
Applies to: SmartEdit · Only if: sf-modules/cms-smartedit is in your project
Find the copies still carrying the old wrappers. grep -L prints the files that don't yet have the fix:
find apps -type f -name render-cms-content.tsx -path '*/cms-smartedit/*' -not -path '*/node_modules/*' -exec grep -LF "classNames('contents', classes)" {} + ; find apps -type f -name RenderSlot.vue -path '*/cms-smartedit/*' -not -path '*/node_modules/*' -exec grep -LF 'class="contents"' {} + || trueIn Next.js, in sf-modules/cms-smartedit/components/render-cms-content.tsx, merge contents with the SmartEdit classes in getSmartEditProps and drop the hard-coded class from the two wrappers in RenderSlot:
function getSmartEditProps(item: AgnosticCmsComponent | Slot) {
const { properties = {} } = item;
const { smartedit } = properties;
if (!smartedit) {
- return {};
+ return { className: 'contents' };
}
const { catalogVersionUuid, classes, componentId, componentType, componentUuid } = smartedit;
return {
- className: classes,
+ className: classNames('contents', classes),
'data-smartedit-catalog-version-uuid': catalogVersionUuid,
'data-smartedit-component-id': componentId,
'data-smartedit-component-type': componentType,
'data-smartedit-component-uuid': componentUuid,
};
}
function RenderSlot({ aboveFold, item }: { aboveFold?: boolean; item: Slot }) {
const { components: slotComponents } = item;
return (
<>
- <div className="contents" {...getSmartEditProps(item)}>
+ <div {...getSmartEditProps(item)}>
{slotComponents.map((component: AgnosticCmsComponent) => (
- <div className="contents" {...getSmartEditProps(component)} key={component.id}>
+ <div {...getSmartEditProps(component)} key={component.id}>
<RenderComponent aboveFold={aboveFold} item={component} />
</div>
))}
</div>
</>
);
}In Nuxt, in sf-modules/cms-smartedit/components/RenderCmsContent/RenderSlot.vue, add a static class to both wrappers; Vue merges it with the classes bound through v-bind:
<template>
- <div v-bind="getSmartEditProps(item)">
- <div v-for="component in item.components" :key="component.id" v-bind="getSmartEditProps(component)">
+ <div class="contents" v-bind="getSmartEditProps(item)">
+ <div
+ v-for="component in item.components"
+ :key="component.id"
+ class="contents"
+ v-bind="getSmartEditProps(component)"
+ >
<RenderCmsContent :item="component" />
</div>
</div>
</template>In Nuxt this also restores the multi-column template layout on regular pages, not only in preview.
Steps carry the release that introduced them. When a later release supersedes an earlier step, the guide shows only the final state. Each step's release note is one click away: Alokai 2.5.