Alokai

Getting Started

This guide covers how to set up and use the Alokai SDK in Next.js, Nuxt, and plain JavaScript applications. The SDK provides a type-safe interface to communicate with your Server Middleware.

The Alokai Storefront comes with the SDK already configured. The Installation and Initializing sections below are only relevant if you're setting up the SDK from scratch. If you just want to use the SDK, skip to Usage.

In the examples below, we assume that you have an Alokai app with the Unified Data Model. However, the approach for non-unified Alokai applications is similar.

Installation

To get started with the SDK within Next.js, first you have to install the @vue-storefront/next package. In the root of your Storefront project run:

Next.js
# Using yarn
yarn add @vue-storefront/next

# Using pnpm
pnpm add @vue-storefront/next

# Using npm
npm install @vue-storefront/next

To get started with the SDK within Nuxt, first you have to install and configure the @vue-storefront/nuxt module.

  1. In the root of your Storefront project run:
Nuxt
# Using yarn
yarn add @vue-storefront/nuxt

# Using pnpm
pnpm add @vue-storefront/nuxt

# Using npm
npm install @vue-storefront/nuxt
  1. Add @vue-storefront/nuxt to the modules section of nuxt.config.ts
nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@vue-storefront/nuxt"],
});
  1. Configure the module

To configure the module, use vsf key in the Nuxt configuration object and provide necessary information such as the Middleware instance address:

nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@vue-storefront/nuxt"],
  vsf: {
    middleware: {
      apiUrl: "http://localhost:4000",
    },
  },
});

The values set in the vsf key are stored as Nuxt runtime config under runtimeConfig.public.alokai. This means you can override them at runtime using environment variables — for example, NUXT_PUBLIC_ALOKAI_MIDDLEWARE_API_URL overrides apiUrl. This is useful for deploying the same build to different environments without rebuilding.

To install the SDK Core, run the following command:

npm
# Using npm
npm install @alokai/connect

# Using yarn
yarn add @alokai/connect

# Using pnpm
pnpm install @alokai/connect

Initializing the SDK

To use the SDK in your application, you need to initialize it first. Create an sdk directory in the root of your project and follow these steps:

Create SDK Options

Create sdk/options.ts to configure the middleware address for both client and SSR mode, cache busting, and multistore settings.

The env() helper from @vue-storefront/next reads environment variables at runtime instead of build time. It is a built-in replacement for the next-runtime-env package — no additional configuration or extra packages required. It works on both server and client, and NEXT_PUBLIC_* variables are automatically injected into the client-side by AlokaiProvider.

sdk/options.ts
import { env, resolveSdkOptions } from "@vue-storefront/next";

export function getSdkOptions() {
  const apiUrl = env("NEXT_PUBLIC_ALOKAI_MIDDLEWARE_API_URL");
  const ssrApiUrl = env("NEXT_PUBLIC_ALOKAI_MIDDLEWARE_SSR_API_URL");
  const cdnCacheBustingId =
    env("NEXT_PUBLIC_ALOKAI_MIDDLEWARE_CDN_CACHE_BUSTING_ID") ??
    env("GIT_SHA") ??
    "no-cache-busting-id-set";
  const isMultiStoreEnabled =
    env("NEXT_PUBLIC_ALOKAI_MULTISTORE_ENABLED") === "true";

  if (!apiUrl) {
    throw new Error(
      "NEXT_PUBLIC_ALOKAI_MIDDLEWARE_API_URL is required to run the app"
    );
  }

  if (!ssrApiUrl) {
    throw new Error(
      "NEXT_PUBLIC_ALOKAI_MIDDLEWARE_SSR_API_URL is required to run the app"
    );
  }

  return resolveSdkOptions({
    middleware: {
      apiUrl,
      cdnCacheBustingId,
      ssrApiUrl,
    },
    multistore: {
      enabled: isMultiStoreEnabled,
    },
  });
}

Create SDK Config

Create sdk/config.ts to define which modules the SDK uses. This is a separate file so it can be imported on both the server and the client.

sdk/config.ts
import { defineSdkConfig } from "@vue-storefront/next";

import * as modules from "@/sdk/modules";

export function getSdkConfig() {
  return defineSdkConfig(modules);
}

Define SDK Modules

Create your SDK modules under sdk/modules/. Each module is a separate file that uses defineSdkModule to configure how it communicates with the middleware.

sdk/modules/unified.ts
import { defineSdkModule } from "@vue-storefront/next";
import type { UnifiedEndpoints } from "storefront-middleware/types";

export const unified = defineSdkModule(
  ({ buildModule, config, getRequestHeaders, middlewareModule }) =>
    buildModule(middlewareModule<UnifiedEndpoints>, {
      apiUrl: `${config.apiUrl}/commerce/unified`,
      cdnCacheBustingId: config.cdnCacheBustingId,
      defaultRequestConfig: {
        headers: async () => getRequestHeaders(),
      },
      ssrApiUrl: `${config.ssrApiUrl}/commerce/unified`,
    }),
);
sdk/modules/commerce.ts
import { defineSdkModule } from "@vue-storefront/next";
import type { CommerceEndpoints } from "storefront-middleware/types";

export const commerce = defineSdkModule(
  ({ buildModule, config, getRequestHeaders, middlewareModule }) =>
    buildModule(middlewareModule<CommerceEndpoints>, {
      apiUrl: `${config.apiUrl}/commerce`,
      cdnCacheBustingId: config.cdnCacheBustingId,
      defaultRequestConfig: {
        headers: async () => getRequestHeaders(),
      },
      ssrApiUrl: `${config.ssrApiUrl}/commerce`,
    }),
);
sdk/modules/index.ts
export * from "./unified";
export * from "./commerce";

The factory function receives a context object with these key properties:

  • buildModule — builds the module from a module definition and its configuration.
  • middlewareModule — the default SDK module for communicating with your Server Middleware. Pass your endpoint types as a generic parameter (e.g. middlewareModule<CommerceEndpoints>).
  • config — contains apiUrl, ssrApiUrl, and cdnCacheBustingId resolved from your SDK options.
  • getRequestHeaders — proxies incoming request headers (cookies, etc.) to SDK requests during SSR. Returns an empty object in the browser.

Create the Universal SDK Instance

Create sdk/sdk.server.ts. The createSdk function takes your options and config, and returns a getSdk function for creating SDK instances.

sdk/sdk.server.ts
import { createSdk } from "@vue-storefront/next";

import { getSdkConfig } from "@/sdk/config";
import { getSdkOptions } from "@/sdk/options";

export const { getSdk } = createSdk(getSdkOptions(), getSdkConfig());

export type Sdk = ReturnType<typeof getSdk>;

Create the Server-Side Wrapper

Create sdk/index.ts — the entry point that your server components import from. It wraps getSdk with locale resolution and request headers (cookies, headers) from the incoming request.

sdk/index.ts
import { cookies, headers } from "next/headers";
import { getLocale } from "next-intl/server";

import { getSdk as getUniversalSdk } from "@/sdk/sdk.server";

export const getSdk = async () => {
  const locale = await getLocale();
  return getUniversalSdk({
    getLocale: () => locale,
    getRequestHeaders: async () => ({
      cookies: await cookies(),
      headers: await headers(),
    }),
  });
};

Create the Client-Side Context

Create sdk/alokai-context.tsx. The createAlokaiContext function provides the AlokaiProvider, the useSdk hook, and state management hooks for your application.

sdk/alokai-context.tsx
"use client";

import { createAlokaiContext } from "@vue-storefront/next/client";
import type { SfContract } from "storefront-middleware/types";

import type { Sdk } from "@/sdk/sdk.server";

export const {
  AlokaiProvider,
  useSdk,
  useSfCartState,
  useSfCurrenciesState,
  useSfCurrencyState,
  useSfCustomerState,
  useSfLocaleState,
  useSfLocalesState,
} = createAlokaiContext<Sdk, SfContract>();

The SfContract generic tells the state management hooks which types your middleware uses for cart (SfCart), customer (SfCustomer), currency (SfCurrency), and locale (SfLocale). You can read more in the State Management page.

Wire Up the AlokaiProvider

Fetch initial data (like currencies) on the server in your layout and pass both the SDK options and initial data to a client Providers component.

app/[locale]/layout.tsx
import type { ReactNode } from "react";
import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";

import Providers from "@/components/providers";
import { getSdk } from "@/sdk";
import { getSdkOptions } from "@/sdk/options";

export default async function RootLayout({
  children,
}: {
  children: ReactNode;
}) {
  const sdk = await getSdk();
  const currencies = await sdk.unified.getCurrencies();
  const sdkOptions = getSdkOptions();
  const messages = await getMessages();

  return (
    <html lang="en">
      <body>
        <NextIntlClientProvider messages={messages}>
          <Providers initialCurrency={currencies} sdkOptions={sdkOptions}>
            {children}
          </Providers>
        </NextIntlClientProvider>
      </body>
    </html>
  );
}
components/providers.tsx
"use client";

import type { CreateSdkOptions } from "@vue-storefront/next";
import { createSdk } from "@vue-storefront/next";
import { useLocale } from "next-intl";
import type { ReactNode } from "react";

import { AlokaiProvider } from "@/sdk/alokai-context";
import { getSdkConfig } from "@/sdk/config";

export default function Providers({
  children,
  initialCurrency,
  sdkOptions,
}: {
  children: ReactNode;
  initialCurrency: { currencies: string[]; currentCurrency: string };
  sdkOptions: CreateSdkOptions;
}) {
  const { getSdk } = createSdk(sdkOptions, getSdkConfig());
  const locale = useLocale();

  return (
    <AlokaiProvider
      initialData={{
        currencies: initialCurrency.currencies,
        currency: initialCurrency.currentCurrency,
        locale,
      }}
      sdk={getSdk({ getLocale: () => locale })}
    >
      {children}
    </AlokaiProvider>
  );
}

Don't be alarmed by the "use client" directive in providers.tsx. It doesn't turn your application into a client-side rendered app — all children inside the provider are still rendered on the server by default. Read more about "use client" in the React Documentation.

To use SDK in our application, we need to initialize it first. To do so, follow these steps:

Create SDK Config file - sdk.config.ts in root directory of your project.

For Nuxt framework it's necessary to name the file sdk.config.ts and keep it in the root of your project.

You should import all SDK modules from a dedicated modules directory. Here's how to structure your Nuxt SDK configuration:

sdk.config.ts
import * as modules from './sdk-modules';

export default defineSdkConfig(modules);

Each module should be defined in a separate file under the sdk-modules directory:

sdk-modules/unified.ts
import type { UnifiedEndpoints } from 'storefront-middleware/types';

export const unified = defineSdkModule(({ buildModule, config, getRequestHeaders, middlewareModule }) =>
  buildModule(middlewareModule<UnifiedEndpoints>, {
    apiUrl: `${config.apiUrl}/commerce/unified`,
    cdnCacheBustingId: config.cdnCacheBustingId,
    defaultRequestConfig: {
      headers: getRequestHeaders(),
    },
    ssrApiUrl: `${config.ssrApiUrl}/commerce/unified`,
  }),
);
sdk-modules/commerce.ts
import type { CommerceEndpoints } from 'storefront-middleware/types';

export const commerce = defineSdkModule(({ buildModule, config, getRequestHeaders, middlewareModule }) =>
  buildModule(middlewareModule<CommerceEndpoints>, {
    apiUrl: `${config.apiUrl}/commerce`,
    cdnCacheBustingId: config.cdnCacheBustingId,
    defaultRequestConfig: {
      headers: getRequestHeaders(),
    },
    ssrApiUrl: `${config.ssrApiUrl}/commerce`,
  }),
);
sdk-modules/cms.ts
import { contentfulModule } from "@vsf-enterprise/contentful-sdk";

export const cms = defineSdkModule(({ buildModule, config, getRequestHeaders }) =>
  buildModule(contentfulModule, {
    apiUrl: `${config.apiUrl}/cms`,
    cdnCacheBustingId: config.cdnCacheBustingId,
    defaultRequestConfig: {
      headers: getRequestHeaders(),
    },
    ssrApiUrl: `${config.ssrApiUrl}/cms`,
  }),
);
sdk-modules/index.ts
export * from './unified';
export * from './commerce';
export * from './cms';

The defineSdkModule factory function receives a context object with these key properties:

  • buildModule — builds the module from a module definition and its configuration.
  • middlewareModule — the default SDK module for communicating with your Server Middleware. Pass your endpoint types as a generic parameter (e.g. middlewareModule<UnifiedEndpoints>).
  • config — contains apiUrl, ssrApiUrl, and cdnCacheBustingId resolved from your SDK options.
  • getRequestHeaders — proxies incoming request headers (cookies, etc.) to SDK requests during SSR. Returns an empty object in the browser.

Next, you have to initialize the SDK, along with any integrations' SDK modules in your frontend project. To do so, follow these steps:

  1. Create SDK Config file - sdk.config.ts in root directory of your project.

It is not necessary to name the file sdk.config.ts specifically or to keep it in the root of your project, but it is recommended to keep it consistent with the rest of the Alokai project.

  1. Create the SDK configuration by importing the initSDK function from the SDK Core and the modules you want to use.

The examples below use the SAP Commerce Cloud and Contentful SDK modules. However, the same principles apply to all modules.

When it comes to managing multiple SDK modules, there are two options for this:

  1. Individual exports (recommended) - initialize each integration as a separate SDK instance, allowing for better code-splitting
  2. Single Instance - combine multiple modules in one SDK instance

Individual Exports

sdk.config.ts
import { initSDK, buildModule, middlewareModule } from "@alokai/connect/sdk";
import { contentfulModule } from "@vsf-enterprise/contentful-sdk";
import { UnifiedEndpoints } from "storefront-middleware/types";

const { unified } = initSDK({
  unified: buildModule(middlewareModule<UnifiedEndpoints>, {
    apiUrl: "http://localhost:4000/commerce",
  }),
});

const { cms } = initSDK({
  cms: buildModule(contentfulModule, {
    apiUrl: "http://localhost:4000/cms",
  }),
});

export { unified, cms };

Single Instance

sdk.config.ts
import { initSDK, buildModule, middlewareModule } from "@alokai/connect/sdk";
import { contentfulModule } from "@vsf-enterprise/contentful-sdk";
import { UnifiedEndpoints } from "storefront-middleware/types";

const sdkConfig = {
  unified: buildModule(middlewareModule<UnifiedEndpoints>, {
    apiUrl: "http://localhost:4000/commerce/unified",
  }),
  cms: buildModule(contentfulModule, {
    apiUrl: "http://localhost:4000/cms",
  }),
};

export const sdk = initSDK(sdkConfig);

The SDK Core exposes two methods to help with this, buildModules, which takes in SDK modules and uses them to extend the SDK Core, and initSDK, which takes multiple modules and converts them into a type-safe interface.

You can name the modules anything you want.

For example, you can rename unified to sapcc and cms to contentful. initSDK will return an object with the same keys as the one passed to it.

Usage

Once you've registered the SDK in your application, you can start using it. For more information about available methods, refer to the respective Integration's documentation.

Server Components — use getSdk to create a new SDK instance. It has access to request headers and cookies, making it ideal for SSR data fetching.

import { getSdk } from "@/sdk";

export default async function SearchPage() {
  const sdk = await getSdk();
  const productCatalog = await sdk.unified.searchProducts({});

  return (
    <ul>
      {productCatalog.products.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

Client Components — use the useSdk hook to access the shared SDK instance provided by AlokaiProvider. Pair it with TanStack Query for caching and state management.

"use client";

import { useSdk } from "@/sdk/alokai-context";
import { useQuery } from "@tanstack/react-query";

export function Products() {
  const sdk = useSdk();
  const { data } = useQuery({
    queryFn: () => sdk.unified.searchProducts({}),
    queryKey: ["products"],
  });

  return (
    <ul>
      {data?.products?.map((product) => (
        <li key={product.id}>{product.name}</li>
      ))}
    </ul>
  );
}

That's it! You can now use Alokai SDK Module in your NextJS app ✨

<template>/* ... */</template>

<script setup>
const sdk = useSdk();

const { data: productCatalog } = await useAsyncData("products", () =>
  sdk.unified.searchProducts({})
);
</script>

That's it! You can now use Alokai SDK Module in your Nuxt app ✨

import { unified } from "../sdk.config";

const productCatalog = await unified.searchProducts({});
import { sdk } from "../sdk.config";

const productCatalog = await sdk.unified.searchProducts({});

That's it! You can now use Alokai SDK in your JavaScript app ✨

Next Steps

On this page