- name
- ce-setup
- description
- Set up the Commerce Engine TypeScript SDK in any project. Framework detection, public vs session client selection, token storage choices, environment variables, and migration guidance.
- license
- MIT
- allowed-tools
- Bash
- metadata
- {"author":"commercengine","version":"1.1.0"}
> **LLM Docs Header**: All requests to `https://llm-docs.commercengine.io` **must** include the `Accept: text/markdown` header (or append `.md` to the URL path). Without it, responses return HTML instead of parseable markdown.
# Setting Up Commerce Engine
This skill sets up the latest Commerce Engine SDK surface.
## Current Mental Model
All frameworks install `@commercengine/storefront` — a unified package with subpath exports:
- **SPA**: `import { createStorefront } from "@commercengine/storefront"` → `storefront.public()` / `storefront.session()`
- **Next.js**: `import { createNextjsStorefront } from "@commercengine/storefront/nextjs"` → `storefront.publicStorefront()` / `storefront.clientStorefront()` / `await storefront.serverStorefront()`
- **TanStack Start**: `import { createTanStackStartStorefront } from "@commercengine/storefront/tanstack-start"` → `storefront.publicStorefront()` / `storefront.clientStorefront()` + separate server entry for `serverStorefront()`
- **Astro**: `import { createAstroStorefront } from "@commercengine/storefront/astro"` → `storefront.publicStorefront()` / `storefront.clientStorefront()` + separate server entry for `serverStorefront(cookies)`
- **SvelteKit**: `import { createSvelteKitStorefront } from "@commercengine/storefront/sveltekit"` → `storefront.publicStorefront()` / `storefront.clientStorefront()` + separate server entry for `serverStorefront(cookies)`
## Quick Reference
| Step | Action |
|------|--------|
| 1. Detect framework | Check `package.json` and config files |
| 2. Install SDK | `@commercengine/storefront` (all frameworks) |
| 3. Initialize storefront | SPA: `createStorefront(...)`, Next.js: `createNextjsStorefront(...)`, TanStack Start: `createTanStackStartStorefront(...)`, Astro: `createAstroStorefront(...)`, SvelteKit: `createSvelteKitStorefront(...)` |
| 4. Set env vars | Next.js: `NEXT_PUBLIC_*`, TanStack Start / SPA: `VITE_*`, Astro / SvelteKit: `PUBLIC_*` |
| 5. Bootstrap session | SPA: call `sdk.ensureAccessToken()` once during startup if you want eager session setup, SSR frameworks: `storefront.bootstrap()` in a client component |
| 6. Use the right accessor | Public reads: `publicStorefront()` / `public()`, Session flows: `clientStorefront()` / `serverStorefront()` / `session()` |
| 7. Hosted Checkout (if used) | **Required**: `authMode: "provided"` with two-way token sync (any app using the Storefront SDK) |
## Canonical Setup (Storefront + Hosted Checkout)
If the app uses Hosted Checkout alongside the Storefront SDK, `authMode: "provided"` with two-way token sync is **required** — not optional. The SDK manages its own session for API calls; without `provided` mode, checkout creates a second independent session. This is the canonical setup:
- The Storefront SDK owns session state.
- Hosted Checkout runs in `authMode: "provided"`.
- Initialize checkout once at app startup, not per route or component render.
- Token sync is mandatory in both directions:
- SDK -> checkout via `updateTokens(...)`
- checkout -> SDK via `onTokensUpdated`
```typescript
import {
BrowserTokenStorage,
createStorefront,
} from "@commercengine/storefront";
import { getCheckout, initCheckout } from "@commercengine/checkout";
const tokenStorage = new BrowserTokenStorage("myapp_");
export const storefront = createStorefront({
storeId: import.meta.env.VITE_STORE_ID,
apiKey: import.meta.env.VITE_API_KEY,
session: {
tokenStorage,
// Note: in SPA (createStorefront), onTokensUpdated is nested inside `session`.
// In SSR wrappers (createNextjsStorefront / createTanStackStartStorefront),
// it is a top-level config property — do not nest it under `session` there.
onTokensUpdated: (accessToken, refreshToken) => {
getCheckout().updateTokens(accessToken, refreshToken);
},
},
});
const sessionSdk = storefront.session();
const accessToken = await sessionSdk.ensureAccessToken();
const refreshToken = await tokenStorage.getRefreshToken();
initCheckout({
storeId: import.meta.env.VITE_STORE_ID,
apiKey: import.meta.env.VITE_API_KEY,
authMode: "provided",
accessToken: accessToken ?? undefined,
refreshToken: refreshToken ?? undefined,
onTokensUpdated: ({ accessToken, refreshToken }) => {
void sessionSdk.setTokens(accessToken, refreshToken);
},
});
```
## Framework Detection
Check `package.json` and config files to identify the framework:
| Indicator | Framework | Import Path | Session Storage |
|-----------|-----------|-------------|-----------------|
| `next` in deps + `next.config.*` | Next.js | `@commercengine/storefront/nextjs` | Built-in (cookie-backed) |
| `@tanstack/react-start` in deps | TanStack Start | `@commercengine/storefront/tanstack-start` | Built-in (cookie-backed) |
| `astro` in deps | Astro | `@commercengine/storefront/astro` | Built-in (cookie-backed) |
| `@sveltejs/kit` in deps | SvelteKit | `@commercengine/storefront/sveltekit` | Built-in (cookie-backed) |
| `nuxt` in deps | Nuxt | `@commercengine/storefront` + `@commercengine/ssr-utils` | `ServerTokenStorage` |
| `vite.config.*` + browser app | React / Vue / Svelte / Solid SPA | `@commercengine/storefront` | `BrowserTokenStorage` |
| `express` in deps | Express / Node.js | `@commercengine/storefront` | `MemoryTokenStorage` or custom `TokenStorage` |
| None of above | Vanilla JS | `@commercengine/storefront` | `BrowserTokenStorage` |
## Decision Tree
```
User Request: "Set up Commerce Engine" / "Add e-commerce"
│
├─ Read package.json + config files
│
├─ Next.js detected?
│ ├─ YES → Install @commercengine/storefront
│ │ → Use createNextjsStorefront() from @commercengine/storefront/nextjs
│ │ → Root layout uses storefront.publicStorefront() + StorefrontBootstrap
│ │ → See ce-ssr-patterns for request-bound usage
│ └─ NO ↓
│
├─ TanStack Start detected?
│ ├─ YES → Install @commercengine/storefront
│ │ → Use createTanStackStartStorefront() from @commercengine/storefront/tanstack-start
│ │ → Server-only: createTanStackStartServerStorefront() from .../tanstack-start/server
│ └─ NO ↓
│
├─ Astro detected?
│ ├─ YES → Install @commercengine/storefront
│ │ → Use createAstroStorefront() from @commercengine/storefront/astro
│ │ → Server-only: createAstroServerStorefront() from .../astro/server
│ └─ NO ↓
│
├─ SvelteKit detected?
│ ├─ YES → Install @commercengine/storefront
│ │ → Use createSvelteKitStorefront() from @commercengine/storefront/sveltekit
│ │ → Server-only: createSvelteKitServerStorefront() from .../sveltekit/server
│ └─ NO ↓
│
├─ Other SSR framework (Nuxt)?
│ ├─ YES → Install @commercengine/storefront + @commercengine/ssr-utils
│ │ → Use ServerTokenStorage with CookieAdapter
│ └─ NO → Install @commercengine/storefront
│ → Use BrowserTokenStorage (SPA) or MemoryTokenStorage (Node)
│
├─ Using Hosted Checkout?
│ ├─ YES → Install @commercengine/checkout
│ │ → authMode: "provided"
│ │ → Two-way token sync (SDK ↔ checkout)
│ └─ NO → SDK-only setup
│
└─ Create one storefront factory and use the framework-appropriate accessors
```
## Setup by Framework
### Next.js (App Router)
```bash
npm install @commercengine/storefront
```
```typescript
// lib/storefront.ts
import { Environment } from "@commercengine/storefront";
import { createNextjsStorefront } from "@commercengine/storefront/nextjs";
export const storefront = createNextjsStorefront({
storeId: process.env.NEXT_PUBLIC_STORE_ID!,
apiKey: process.env.NEXT_PUBLIC_API_KEY!,
environment: Environment.Staging,
tokenStorageOptions: { prefix: "myapp_" },
});
```
```tsx
// components/storefront-bootstrap.tsx
"use client";
import { useEffect } from "react";
import { storefront } from "@/lib/storefront";
export function StorefrontBootstrap() {
useEffect(() => {
storefront.bootstrap().catch(console.error);
}, []);
return null;
}
```
The root layout is a Server Component, but it can render `StorefrontBootstrap` (a Client Component) as a child — this is standard Next.js composition. Place the bootstrap component as high in the tree as possible.
```tsx
// app/layout.tsx (Server Component — this is fine)
import { storefront } from "@/lib/storefront";
import { StorefrontBootstrap } from "@/components/storefront-bootstrap";
const { data: storeConfig } = await storefront.publicStorefront().store.getStoreConfig();
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<StorefrontBootstrap />
<header>{storeConfig?.store_config?.brand.name}</header>
{children}
</body>
</html>
);
}
```
> For the full Next.js request model, see `ce-ssr-patterns`.
>
> **Using Hosted Checkout?** See `ce-cart-checkout` and `references/hosted-checkout.md` for the token sync pattern.
```env
# .env.local
NEXT_PUBLIC_STORE_ID=your-store-id
NEXT_PUBLIC_API_KEY=your-api-key
```
### TanStack Start
```bash
npm install @commercengine/storefront
```
```typescript
// lib/storefront.ts
import { Environment } from "@commercengine/storefront";
import { createTanStackStartStorefront } from "@commercengine/storefront/tanstack-start";
export const storefrontConfig = {
storeId: import.meta.env.VITE_STORE_ID,
apiKey: import.meta.env.VITE_API_KEY,
environment: Environment.Staging,
tokenStorageOptions: { prefix: "myapp_" },
};
export const storefront = createTanStackStartStorefront(storefrontConfig);
```
```typescript
// lib/storefront.server.ts (server-only module)
import { createTanStackStartServerStorefront } from "@commercengine/storefront/tanstack-start/server";
import { storefrontConfig } from "./storefront";
const serverStorefrontFactory = createTanStackStartServerStorefront(storefrontConfig);
export function serverStorefront() {
return serverStorefrontFactory.serverStorefront();
}
```
```tsx
// components/storefront-bootstrap.tsx
import { useEffect } from "react";
import { storefront } from "@/lib/storefront";
export function StorefrontBootstrap() {
useEffect(() => {
storefront.bootstrap().catch(console.error);
}, []);
return null;
}
```
Mount `StorefrontBootstrap` in the root layout (`__root.tsx`).
```env
# .env
VITE_STORE_ID=your-store-id
VITE_API_KEY=your-api-key
```
### Astro
```bash
npm install @commercengine/storefront
```
```typescript
// src/lib/storefront-config.ts
import { Environment } from "@commercengine/storefront";
import type { AstroStorefrontConfig } from "@commercengine/storefront/astro";
export const storefrontConfig: AstroStorefrontConfig = {
storeId: import.meta.env.PUBLIC_STORE_ID,
apiKey: import.meta.env.PUBLIC_API_KEY,
environment: Environment.Staging,
tokenStorageOptions: { prefix: "myapp_" },
};
```
```typescript
// src/lib/storefront.ts
import { createAstroStorefront } from "@commercengine/storefront/astro";
import { storefrontConfig } from "./storefront-config";
export const storefront = createAstroStorefront(storefrontConfig);
```
```typescript
// src/lib/server-storefront.ts (server-only)
import { createAstroServerStorefront } from "@commercengine/storefront/astro/server";
import { storefrontConfig } from "./storefront-config";
export const serverStorefront = createAstroServerStorefront(storefrontConfig);
```
Bootstrap in a root layout script, then use `serverStorefront.serverStorefront(Astro.cookies)` in SSR pages/API routes.
> For the full Astro request model, see `ce-ssr-patterns`.
```env
# .env
PUBLIC_STORE_ID=your-store-id
PUBLIC_API_KEY=your-api-key
```
### SvelteKit
```bash
npm install @commercengine/storefront
```
```typescript
// src/lib/storefront-config.ts
import { Environment } from "@commercengine/storefront";
import type { SvelteKitStorefrontConfig } from "@commercengine/storefront/sveltekit";
import { env } from "$env/static/public";
export const storefrontConfig: SvelteKitStorefrontConfig = {
storeId: env.PUBLIC_STORE_ID,
apiKey: env.PUBLIC_API_KEY,
environment: Environment.Staging,
tokenStorageOptions: { prefix: "myapp_" },
};
```
```typescript
// src/lib/storefront.ts
import { createSvelteKitStorefront } from "@commercengine/storefront/sveltekit";
import { storefrontConfig } from "./storefront-config";
export const storefront = createSvelteKitStorefront(storefrontConfig);
```
```typescript
// src/lib/server/storefront.ts (server-only — $lib/server/ is enforced by SvelteKit)
import { createSvelteKitServerStorefront } from "@commercengine/storefront/sveltekit/server";
import { storefrontConfig } from "$lib/storefront-config";
View on GitHub