@commercengine/storefront-sdk-nextjs 0.2.9 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,19 @@
1
1
  # CommerceEngine Next.js SDK
2
2
 
3
- **Production-ready Next.js wrapper** for the CommerceEngine Storefront SDK. Provides the perfect developer experience with automatic context detection, universal API, and zero configuration complexity.
3
+ Production-ready Next.js wrapper for the CommerceEngine Storefront SDK.
4
4
 
5
- Built on [`@commercengine/ssr-utils`](../ssr-utils) for robust server-side token management.
5
+ Breaking changes from the previous wrapper API are documented in
6
+ [MIGRATION.md](./MIGRATION.md).
6
7
 
7
- **✨ Perfect DX Pattern:**
8
- - **🎯 One Config File** - Single `lib/storefront.ts` using `createStorefront()`
9
- - **🌍 Universal API** - Same `storefront()` import works everywhere
10
- - **🔥 Automatic Tokens** - Creates and manages tokens automatically
11
- - **🧠 Smart Context Detection** - Detects Server vs Client vs Build contexts
12
- - **🍪 Cookie-based State** - Shared authentication via Next.js cookies
13
- - **⚡ Request Isolation** - Proper per-request SDK instances on server
14
- - **🛠 Zero Complexity** - Environment variables + one lib file = done
8
+ This package gives Next.js apps one configured storefront factory with two
9
+ explicit access patterns:
10
+
11
+ - `storefront.public()` for build-safe and public server reads
12
+ - `storefront.session()` / `storefront.session(await cookies())` for live user
13
+ session flows
14
+
15
+ It builds on [`@commercengine/ssr-utils`](../ssr-utils) for cookie-backed server
16
+ storage, but the primary DX is the Next.js-specific `createStorefront()` API.
15
17
 
16
18
  ## Installation
17
19
 
@@ -23,82 +25,51 @@ pnpm add @commercengine/storefront-sdk-nextjs
23
25
 
24
26
  ## Quick Start
25
27
 
26
- ### 1. Environment Variables (Required)
27
-
28
- Add your store configuration to `.env.local`:
28
+ ### 1. Add environment variables
29
29
 
30
30
  ```bash
31
31
  NEXT_PUBLIC_STORE_ID=your-store-id
32
32
  NEXT_PUBLIC_API_KEY=your-api-key
33
- # Environment (defaults to "staging")
34
- NEXT_PUBLIC_ENVIRONMENT=staging # or "production"
33
+ NEXT_PUBLIC_ENVIRONMENT=staging
35
34
  ```
36
35
 
37
- ### 2. Create Your Storefront Configuration
38
-
39
- Create `lib/storefront.ts` in your project:
36
+ ### 2. Create `lib/storefront.ts`
40
37
 
41
38
  ```typescript
42
- // lib/storefront.ts
43
39
  import {
44
40
  createStorefront,
45
41
  type StorefrontRuntimeConfig,
46
42
  } from "@commercengine/storefront-sdk-nextjs";
47
43
 
48
- // Optional advanced configuration (everything not in environment variables)
49
44
  const storefrontConfig: StorefrontRuntimeConfig = {
50
45
  debug: true,
51
46
  timeout: 15000,
52
- logger: (msg: string, ...args: any[]) =>
53
- console.log("[STOREFRONT]", msg, ...args),
54
- onTokensUpdated: (access: string, refresh: string) => {
55
- console.log("🔥 TOKENS UPDATED:", {
56
- access: access.slice(0, 20) + "...",
57
- refresh: refresh.slice(0, 20) + "...",
58
- });
59
- },
60
- onTokensCleared: () => {
61
- console.log("🔄 TOKENS CLEARED");
62
- },
47
+ logger: (msg, ...args) => console.log("[STOREFRONT]", msg, ...args),
63
48
  };
64
49
 
65
- // Create the configured storefront function (storefrontConfig is OPTIONAL)
66
50
  export const storefront = createStorefront(storefrontConfig);
67
51
 
68
- // Re-export types for convenience
69
52
  export type { StorefrontRuntimeConfig };
70
53
  ```
71
54
 
72
- **All Core SDK Types Available:**
73
- The Next.js SDK re-exports all types from the core SDK, so you can import them directly:
74
-
75
- ```typescript
76
- // Import any core SDK types you need
77
- import type {
78
- UserInfo,
79
- SupportedDefaultHeaders,
80
- StorefrontSDKOptions,
81
- components,
82
- operations
83
- } from "@commercengine/storefront-sdk-nextjs";
84
-
85
- // Use imported types
86
- const headers: SupportedDefaultHeaders = {
87
- customer_group_id: "01ABC123..."
88
- };
89
- ```
90
-
91
- ### 3. Initialize in Root Layout
55
+ ### 3. Initialize once in the root layout
92
56
 
93
57
  ```typescript
94
- // app/layout.tsx
95
58
  import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
59
+ import { storefront } from "@/lib/storefront";
60
+
61
+ const { data: storeConfig } = await storefront.public().store.getStoreConfig();
96
62
 
97
- export default function RootLayout({ children }: { children: React.ReactNode }) {
63
+ export default function RootLayout({
64
+ children,
65
+ }: {
66
+ children: React.ReactNode;
67
+ }) {
98
68
  return (
99
69
  <html lang="en">
100
70
  <body>
101
71
  <StorefrontSDKInitializer />
72
+ <h1>{storeConfig?.store_config?.brand.name}</h1>
102
73
  {children}
103
74
  </body>
104
75
  </html>
@@ -106,349 +77,202 @@ export default function RootLayout({ children }: { children: React.ReactNode })
106
77
  }
107
78
  ```
108
79
 
109
- ### 4. Use Anywhere with Universal Import
80
+ ### 4. Use the correct accessor
110
81
 
111
82
  ```typescript
112
- // Import your configured storefront everywhere
113
83
  import { storefront } from "@/lib/storefront";
114
- import { cookies } from "next/headers"; // Only for server contexts
115
-
116
- // ✅ Client Component - No cookies needed
117
- const products = await storefront().catalog.listProducts();
84
+ import { cookies } from "next/headers";
118
85
 
119
- // ✅ Server Component, Server Action, or API Route - MUST pass cookies
120
- const products = await storefront(cookies()).catalog.listProducts();
86
+ // Build/prerender-safe reads
87
+ const publicSdk = storefront.public();
121
88
 
122
- // Root Layout - Special exception with explicit flag
123
- const products = await storefront({ isRootLayout: true }).catalog.listProducts();
89
+ // Client Components
90
+ const clientSessionSdk = storefront.session();
124
91
 
125
- // SSG/ISR (build contexts) - Automatic fallback to memory storage
126
- // (NEXT_BUILD_CACHE_TOKENS=true enables this)
127
- const products = await storefront().catalog.listProducts();
92
+ // Server Components, Server Actions, Route Handlers
93
+ const serverSessionSdk = storefront.session(await cookies());
128
94
  ```
129
95
 
130
- ## Usage in Different Next.js Contexts
96
+ ## Mental Model
131
97
 
132
- ### Client Components
98
+ - `public()` is for public reads that should stay API-key-backed and never touch
99
+ session bootstrap, refresh, or token persistence.
100
+ - `session()` is for live requests that operate on behalf of an anonymous or
101
+ authenticated user.
102
+ - The server version of `session()` requires `cookies()` so request continuity
103
+ is explicit and session state can flow across server/client boundaries.
104
+
105
+ That means:
133
106
 
134
- Client Components run in the browser and can persist tokens via cookies:
107
+ - Root layouts use `storefront.public()`
108
+ - SSG/ISR pages use `storefront.public()`
109
+ - Client Components use `storefront.session()`
110
+ - Server Components, Server Actions, and Route Handlers use
111
+ `storefront.session(await cookies())`
112
+
113
+ ## Usage Examples
114
+
115
+ ### Client Components
135
116
 
136
117
  ```typescript
137
- // components/ProductList.tsx
138
118
  "use client";
139
119
 
140
- import { useState, useEffect } from "react";
120
+ import { useEffect, useState } from "react";
141
121
  import { storefront } from "@/lib/storefront";
142
122
 
143
123
  export default function ProductList() {
144
- const [products, setProducts] = useState([]);
145
-
124
+ const [products, setProducts] = useState<string[]>([]);
125
+
146
126
  useEffect(() => {
147
- async function loadProducts() {
148
- const sdk = storefront(); // No cookies() needed on client-side
149
-
150
- // Tokens are automatically managed by StorefrontSDKInitializer
151
- const { data } = await sdk.catalog.listProducts();
152
- if (data) setProducts(data.products);
153
- }
154
-
155
- loadProducts();
127
+ const sdk = storefront.session();
128
+
129
+ sdk.catalog.listProducts({ limit: 5 }).then(({ data }) => {
130
+ setProducts(data?.products.map((product) => product.name) ?? []);
131
+ });
156
132
  }, []);
157
-
133
+
158
134
  return (
159
- <div>
160
- {products.map(product => (
161
- <div key={product.id}>{product.name}</div>
135
+ <ul>
136
+ {products.map((name) => (
137
+ <li key={name}>{name}</li>
162
138
  ))}
163
- </div>
139
+ </ul>
164
140
  );
165
141
  }
166
142
  ```
167
143
 
168
144
  ### Server Components
169
145
 
170
- Server Components run on the server and can read cookies:
146
+ Use `public()` for public content and `session(await cookies())` when the read
147
+ depends on live session state.
171
148
 
172
149
  ```typescript
173
- // app/products/page.tsx
174
150
  import { storefront } from "@/lib/storefront";
175
151
  import { cookies } from "next/headers";
176
152
 
177
- export default async function ProductsPage() {
178
- const sdk = storefront(cookies());
179
-
180
- const { data: products } = await sdk.catalog.listProducts();
181
-
182
- return (
183
- <div>
184
- {products?.products.map(product => (
185
- <div key={product.id}>{product.name}</div>
186
- ))}
187
- </div>
188
- );
153
+ export default async function CartPage() {
154
+ const sdk = storefront.session(await cookies());
155
+ const { data: cart } = await sdk.cart.getCart();
156
+
157
+ return <pre>{JSON.stringify(cart, null, 2)}</pre>;
189
158
  }
190
159
  ```
191
160
 
192
161
  ### Server Actions
193
162
 
194
- Server Actions can both read and write cookies, perfect for authentication:
195
-
196
163
  ```typescript
197
- // app/actions.ts
198
164
  "use server";
199
165
 
200
166
  import { storefront } from "@/lib/storefront";
201
167
  import { cookies } from "next/headers";
202
168
 
203
- export async function loginWithEmail(email: string, password: string) {
204
- const sdk = storefront(cookies());
205
-
169
+ export async function loginWithPassword(email: string, password: string) {
170
+ const sdk = storefront.session(await cookies());
206
171
  const { data, error } = await sdk.auth.loginWithPassword({ email, password });
207
-
208
- if (data) {
209
- // Tokens are automatically saved to cookies
210
- return { success: true, user: data.user };
211
- }
212
-
213
- return { success: false, error: error?.message };
214
- }
215
- ```
216
-
217
- ### API Routes
218
-
219
- API Routes work identically to Server Actions:
220
172
 
221
- ```typescript
222
- // app/api/products/route.ts
223
- import { storefront } from "@/lib/storefront";
224
- import { cookies } from "next/headers";
225
- import { NextResponse } from "next/server";
226
-
227
- export async function GET() {
228
- try {
229
- const sdk = storefront(cookies());
230
- const { data, error } = await sdk.catalog.listProducts();
231
-
232
- if (error) {
233
- return NextResponse.json({ error: error.message }, { status: 400 });
234
- }
235
-
236
- return NextResponse.json(data);
237
- } catch (error) {
238
- return NextResponse.json(
239
- { error: "Internal server error" },
240
- { status: 500 }
241
- );
173
+ if (error) {
174
+ return { success: false, error: error.message };
242
175
  }
243
- }
244
- ```
245
-
246
- ### Root Layout (Special Case)
247
-
248
- Root Layout requires explicit flag since it's outside request context. Passing this flag will instruct the SDK to fallback to MemoryStore when rendering the root layout as the root layout runs on both server and client before cookie context is available.
249
-
250
- ```typescript
251
- // app/layout.tsx
252
- import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
253
- import { storefront } from "@/lib/storefront";
254
-
255
- // Root Layout requires explicit flag - no request context available
256
- const sdk = storefront({ isRootLayout: true });
257
- const { data: storeConfig } = await sdk.store.getStoreConfig();
258
176
 
259
- export default function RootLayout({ children }: { children: React.ReactNode }) {
260
- return (
261
- <html lang="en">
262
- <body>
263
- <StorefrontSDKInitializer />
264
- <h1>Welcome to {storeConfig?.store_config?.brand.name}</h1>
265
- {children}
266
- </body>
267
- </html>
268
- );
177
+ return { success: true, user: data?.user ?? null };
269
178
  }
270
179
  ```
271
180
 
272
- ## Static Site Generation (SSG) & Build-Time Optimization
273
-
274
- The SDK provides powerful build-time optimizations through intelligent token caching.
275
-
276
- ### Configure Next.js for Build-Time Optimization
277
-
278
- Create or update your `next.config.ts` (or `next.config.js`) to enable automatic token caching during builds:
181
+ ### Static Generation
279
182
 
280
183
  ```typescript
281
- // next.config.ts
282
- import type { NextConfig } from "next";
283
- import { PHASE_PRODUCTION_BUILD } from 'next/constants';
284
-
285
- const nextConfig = (phase: string): NextConfig => {
286
- const isBuild = phase === PHASE_PRODUCTION_BUILD;
287
-
288
- return {
289
- env: {
290
- // Enable build-time token caching during production builds and when explicitly set
291
- NEXT_BUILD_CACHE_TOKENS: process.env.NEXT_BUILD_CACHE_TOKENS ?? (isBuild ? 'true' : 'false'),
292
- // Critical: tells SDK to use MemoryStore during SSG/Build/ISR to avoid cookie context failures
293
- NEXT_IS_BUILD: isBuild ? 'true' : 'false',
294
- },
295
-
296
- // Ensure static generation is enabled
297
- output: undefined, // Let Next.js decide based on usage
298
- };
299
- };
300
-
301
- export default nextConfig;
302
- ```
303
-
304
- ### SSG with generateStaticParams
305
-
306
- ```typescript
307
- // app/products/[slug]/page.tsx
308
184
  import { storefront } from "@/lib/storefront";
309
185
  import { notFound } from "next/navigation";
310
186
 
311
- interface ProductPageProps {
187
+ export default async function ProductPage({
188
+ params,
189
+ }: {
312
190
  params: Promise<{ slug: string }>;
313
- }
314
-
315
- export default async function ProductPage({ params }: ProductPageProps) {
191
+ }) {
316
192
  const { slug } = await params;
317
- const sdk = storefront(); // No cookies() - uses build-time storage
318
-
193
+ const sdk = storefront.public();
194
+
319
195
  const { data, error } = await sdk.catalog.getProductDetail({
320
- product_id_or_slug: slug
196
+ product_id_or_slug: slug,
321
197
  });
322
-
198
+
323
199
  if (error || !data) {
324
200
  notFound();
325
201
  }
326
-
327
- return (
328
- <div>
329
- <h1>{data.product.name}</h1>
330
- <p>SKU: {data.product.sku}</p>
331
- <p>Description: {data.product.short_description}</p>
332
- </div>
333
- );
202
+
203
+ return <h1>{data.product.name}</h1>;
334
204
  }
335
205
 
336
- // Generate static params from real API data
337
206
  export async function generateStaticParams() {
338
- const sdk = storefront(); // Token will be cached and reused
339
-
340
- const { data: productsData, error } = await sdk.catalog.listProducts({
341
- limit: 100
342
- });
343
-
344
- if (error || !productsData) {
345
- return [];
346
- }
347
-
348
- return productsData.products.map(product => ({
349
- slug: product.slug || product.id
350
- }));
207
+ const sdk = storefront.public();
208
+ const { data } = await sdk.catalog.listProducts({ limit: 100 });
209
+
210
+ return (
211
+ data?.products.map((product) => ({
212
+ slug: product.slug || product.id,
213
+ })) ?? []
214
+ );
351
215
  }
352
216
  ```
353
217
 
354
- ### Build Performance Benefits
355
-
356
- With token caching enabled:
357
- - ✅ Token created once and reused across all pages
358
- - ✅ 100 pages = ~1 anonymous token API call total
359
- - ✅ Faster builds, dramatically lower API usage
360
-
361
- ## Authentication Patterns
218
+ ## Authentication Model
362
219
 
363
- > **⚠️ Important:** Any authentication endpoint that returns tokens (like `loginWithPassword`, `verifyOtp`, `register`, etc.) **must** be called in contexts where cookies can be set and managed:
364
- > - ✅ **Server Actions** (recommended for authentication flows)
365
- > - ✅ **API Routes** (`/api` directory)
366
- > - ✅ **Client Components** (browser environment)
367
- > - ❌ **Server Components** (cannot set cookies, tokens won't persist)
368
- >
369
- > This ensures the SDK can automatically handle token storage and user session continuity.
370
-
371
- ### Anonymous Users
220
+ ### `StorefrontSDKInitializer`
372
221
 
373
- The SDK automatically creates anonymous tokens via the `StorefrontSDKInitializer` component imported in your root layout. If this component is not imported (not recommended), a new token will be minted for each request as a fallback. **It is highly recommended** to use the `StorefrontSDKInitializer` and ensure all token-returning endpoints are called from request contexts that can set cookies. [Authentication Patterns](#authentication-patterns).
222
+ `StorefrontSDKInitializer` is a client component that eagerly bootstraps the
223
+ anonymous session once on first load by calling `ensureAccessToken()`.
374
224
 
375
225
  ```typescript
376
- // This works everywhere - creates anonymous token automatically
377
- const { data: products } = await storefront(cookies()).catalog.listProducts();
226
+ import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
227
+
228
+ <StorefrontSDKInitializer />
378
229
  ```
379
230
 
380
- ### Email/Password Login
231
+ It accepts an optional `runtimeConfig` prop when you need client-only runtime
232
+ overrides:
381
233
 
382
234
  ```typescript
383
- // Server Action (✅ Recommended - can set cookies for token persistence)
384
- "use server";
385
- export async function loginUser(email: string, password: string) {
386
- const sdk = storefront(cookies());
387
-
388
- const { data, error } = await sdk.auth.loginWithPassword({ email, password });
389
-
390
- if (data) {
391
- // Tokens automatically saved to cookies
392
- redirect('/dashboard');
393
- }
394
-
395
- return { error: error?.message };
396
- }
235
+ <StorefrontSDKInitializer runtimeConfig={{ debug: true }} />
397
236
  ```
398
237
 
399
- ### Phone/OTP Login
238
+ ### Where token-returning endpoints should run
400
239
 
401
- ```typescript
402
- // Server Action - Step 1: Send OTP (✅ Recommended context)
403
- export async function sendOTP(phone: string, country_code: string) {
404
- const sdk = storefront(await cookies());
405
-
406
- return await sdk.auth.loginWithPhone({
407
- phone,
408
- country_code,
409
- register_if_not_exists: true
410
- });
411
- }
240
+ Calls that create or replace tokens should run in places that can persist the
241
+ resulting session cleanly:
412
242
 
413
- // Server Action - Step 2: Verify OTP (✅ Recommended - can set cookies for token persistence)
414
- export async function verifyOTP(otp: string, otp_token: string, otp_action: string) {
415
- const sdk = storefront(await cookies());
416
-
417
- const { data, error } = await sdk.auth.verifyOtp({
418
- otp,
419
- otp_token,
420
- otp_action
421
- });
422
-
423
- if (data) {
424
- // Tokens automatically saved to cookies
425
- return { success: true, user: data.user };
426
- }
427
-
428
- return { success: false, error: error?.message };
429
- }
430
- ```
243
+ - Client Components
244
+ - Server Actions
245
+ - Route Handlers
246
+
247
+ Server Components are best used for reads against an already-established
248
+ session, not for login/register/reset-password flows.
431
249
 
432
250
  ## API Reference
433
251
 
434
252
  ### `createStorefront(config?)`
435
253
 
436
- Creates a configured storefront function that works universally across all Next.js contexts.
254
+ Creates the configured Next.js storefront factory.
437
255
 
438
256
  ```typescript
439
257
  import { createStorefront } from "@commercengine/storefront-sdk-nextjs";
440
258
 
441
259
  export const storefront = createStorefront({
442
260
  debug: true,
443
- logger: (msg, ...args) => console.log('[DEBUG]', msg, ...args)
261
+ timeout: 15000,
444
262
  });
445
263
  ```
446
264
 
447
- **Parameters:**
448
- - `config` (optional): `StorefrontRuntimeConfig` - Advanced configuration options
265
+ The returned type is:
449
266
 
450
- **Returns:**
451
- - Universal `storefront()` function that works in all Next.js contexts
267
+ ```typescript
268
+ type NextJSStorefront = {
269
+ public: () => PublicStorefrontSDK;
270
+ session: {
271
+ (): SessionStorefrontSDK;
272
+ (cookieStore: NextCookieStore): SessionStorefrontSDK;
273
+ };
274
+ };
275
+ ```
452
276
 
453
277
  ### `StorefrontRuntimeConfig`
454
278
 
@@ -456,15 +280,12 @@ Optional configuration object for `createStorefront()`:
456
280
 
457
281
  ```typescript
458
282
  interface StorefrontRuntimeConfig {
459
- // Override environment variables
460
283
  storeId?: string;
461
284
  apiKey?: string;
462
285
  environment?: Environment;
463
286
  baseUrl?: string;
464
287
  timeout?: number;
465
288
  debug?: boolean;
466
-
467
- // Advanced options (not available via environment variables)
468
289
  accessToken?: string;
469
290
  refreshToken?: string;
470
291
  defaultHeaders?: SupportedDefaultHeaders;
@@ -475,167 +296,86 @@ interface StorefrontRuntimeConfig {
475
296
  }
476
297
  ```
477
298
 
478
- ### Universal `storefront()` Function
299
+ All core SDK types are re-exported from this package, so you can also import
300
+ `UserInfo`, `SessionStorefrontSDKOptions`, `components`, `operations`, and more
301
+ directly from `@commercengine/storefront-sdk-nextjs`.
479
302
 
480
- The function returned by `createStorefront()` works in all contexts with strict enforcement:
481
-
482
- ```typescript
483
- // Client-side (browser)
484
- const sdk = storefront();
303
+ ## Best Practices
485
304
 
486
- // Server-side (requires cookies for user continuity)
487
- const sdk = storefront(cookies());
305
+ - Create one `lib/storefront.ts` file and reuse it everywhere.
306
+ - Use `storefront.public()` for root layouts, static generation, and other
307
+ public reads.
308
+ - Use `storefront.session(await cookies())` for server-side session reads.
309
+ - Use `storefront.session()` in Client Components.
310
+ - Mount `StorefrontSDKInitializer` once in the root layout.
311
+ - Treat `public()` and `session()` as different semantics, not just different
312
+ runtimes.
488
313
 
489
- // Root Layout (special exception with explicit flag)
490
- const sdk = storefront({ isRootLayout: true });
314
+ ## Troubleshooting
491
315
 
492
- // Server-side without cookies - throws helpful error to protect user sessions
493
- const sdk = storefront(); // ❌ Throws error in server contexts
494
- ```
316
+ ### "Server session access requires cookies"
495
317
 
496
- ### Function Signatures
318
+ You called `storefront.session()` on the server without `cookies()`.
497
319
 
498
320
  ```typescript
499
- function storefront(): StorefrontSDK;
500
- function storefront(cookieStore: NextCookieStore): StorefrontSDK;
501
- function storefront(options: { isRootLayout: true }): StorefrontSDK;
502
- function storefront(cookieStore: NextCookieStore, options: { isRootLayout?: boolean }): StorefrontSDK;
503
- ```
321
+ // Wrong on the server
322
+ const sdk = storefront.session();
504
323
 
505
- ### `StorefrontSDKInitializer`
324
+ // Correct on the server
325
+ const sdk = storefront.session(await cookies());
506
326
 
507
- Client-side initializer component (must be imported from `/client`):
508
-
509
- ```typescript
510
- import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
511
-
512
- <StorefrontSDKInitializer />
327
+ // Correct for public reads
328
+ const publicSdk = storefront.public();
513
329
  ```
514
330
 
515
- No props needed - configuration comes from environment variables and your `lib/storefront.ts` file.
331
+ ### Root layout usage
516
332
 
517
- ## Error Handling
333
+ There is no special `isRootLayout` escape hatch anymore. Root layouts should use
334
+ `storefront.public()` for public reads and `StorefrontSDKInitializer` to eager
335
+ bootstrap the client session.
518
336
 
519
- All SDK methods return a consistent error structure:
337
+ ### Missing environment variables
520
338
 
521
- ```typescript
522
- const { data, error, response } = await storefront(cookies()).catalog.listProducts();
339
+ Make sure these are set:
523
340
 
524
- if (error) {
525
- console.error("API Error:", error.message, error.code);
526
- console.log("Status:", response.status);
527
- } else {
528
- console.log("Products:", data.products);
529
- }
341
+ ```bash
342
+ NEXT_PUBLIC_STORE_ID=your-store-id
343
+ NEXT_PUBLIC_API_KEY=your-api-key
344
+ NEXT_PUBLIC_ENVIRONMENT=staging
530
345
  ```
531
346
 
532
- ## Best Practices
533
-
534
- ### ✅ Do's
535
-
536
- - **Set required environment variables**: `NEXT_PUBLIC_STORE_ID` and `NEXT_PUBLIC_API_KEY` are mandatory
537
- - **Create one lib/storefront.ts file**: Use `createStorefront()` to configure advanced options
538
- - **Initialize once**: Call `StorefrontSDKInitializer` only in your root layout
539
- - **Use `storefront(cookies())`**: Always pass cookies in server contexts
540
- - **Handle errors**: Always check the error property in responses
541
- - **Use Server Actions**: For authentication flows that need to persist tokens
542
-
543
- ### ❌ Don'ts
544
-
545
- - **Don't call `cookies()` in Client Components**: It will throw an error
546
- - **Don't initialize multiple times**: The SDK handles singleton behavior
547
- - **Don't forget error handling**: API calls can fail for various reasons
548
- - **Don't skip environment variables**: Missing required variables will cause errors
549
-
550
- ## Troubleshooting
551
-
552
- ### Common Issues
553
-
554
- 1. **"Server context requires cookies for user continuity!"**
555
- ```typescript
556
- // ❌ Wrong - server context without cookies (breaks user sessions)
557
- storefront()
558
-
559
- // ✅ Correct - server context with cookies
560
- storefront(cookies())
561
-
562
- // ✅ Root Layout exception
563
- storefront({ isRootLayout: true })
564
- ```
565
-
566
- 2. **Missing Environment Variables**
567
- ```bash
568
- # Ensure your .env.local has the required variables:
569
- NEXT_PUBLIC_STORE_ID=your-store-id
570
- NEXT_PUBLIC_API_KEY=your-api-key
571
- ```
572
-
573
- 3. **"Cookie store passed in client environment"**
574
- ```typescript
575
- // ❌ Wrong - client component with cookies
576
- storefront(cookies())
577
-
578
- // ✅ Correct - client component without cookies
579
- storefront()
580
- ```
581
-
582
- 4. **Server Actions and async cookies()**
583
- ```typescript
584
- // ✅ Correct - Server Actions need await cookies()
585
- const sdk = storefront(await cookies());
586
-
587
- // ✅ Server Components and API Routes use cookies() directly
588
- const sdk = storefront(cookies());
589
- ```
590
-
591
347
  ## Migration Guide
592
348
 
593
- ### From Core SDK
349
+ ### From the previous Next.js wrapper API
594
350
 
595
351
  ```typescript
596
- // Before (core SDK)
597
- import { StorefrontSDK } from "@commercengine/storefront-sdk";
598
- const sdk = new StorefrontSDK({
599
- storeId: "...",
600
- tokenStorage: new BrowserTokenStorage()
601
- });
602
-
603
- // After (Next.js SDK)
604
- import { storefront } from "@/lib/storefront";
605
- const sdk = storefront(cookies());
352
+ // Before
353
+ storefront();
354
+ storefront(await cookies());
355
+ storefront({ isRootLayout: true });
356
+
357
+ // After
358
+ storefront.session();
359
+ storefront.session(await cookies());
360
+ storefront.public();
606
361
  ```
607
362
 
608
- ## Why This Pattern?
609
-
610
- **The Perfect DX Pattern provides:**
611
- - **One Config File**: All advanced configuration in `lib/storefront.ts`
612
- - **Environment Variables**: Basic config (storeId, apiKey) via env vars
613
- - **Universal Import**: Same `storefront()` import everywhere
614
- - **Strict User Continuity**: Enforces cookie passing to protect user sessions and analytics
615
- - **Explicit Exceptions**: Clear patterns for special cases like Root Layout
616
- - **Zero Guesswork**: Helpful errors guide developers to correct patterns
617
-
618
- **Result: Production-ready e-commerce with bulletproof user session management!** 🛡️
363
+ ### From direct core SDK usage
619
364
 
620
- ## API Reference
621
-
622
- For complete API documentation of all available endpoints, visit [SDK DOCS REFERENCE](https://llm-docs.commercengine.io/sdk/)
623
-
624
- The Next.js SDK provides access to all the same endpoints as the core SDK:
365
+ ```typescript
366
+ // Before
367
+ import { SessionStorefrontSDK } from "@commercengine/storefront-sdk";
625
368
 
626
- - `sdk.auth.*` - Authentication and user management
627
- - `sdk.customer.*` - Customer profiles and preferences
628
- - `sdk.catalog.*` - Products, categories, and search
629
- - `sdk.cart.*` - Shopping cart management
630
- - `sdk.order.*` - Order creation and tracking
631
- - `sdk.payments.*` - Payment methods and processing
632
- - `sdk.store.*` - Store configuration
633
- - `sdk.helpers.*` - Countries, currencies, utilities
369
+ // After
370
+ import { SessionStorefrontSDK } from "@commercengine/storefront-sdk";
371
+ ```
634
372
 
635
- ## Related Packages
373
+ Or, for the recommended DX:
636
374
 
637
- - [`@commercengine/storefront-sdk`](../storefront-sdk) - Core Storefront SDK
375
+ ```typescript
376
+ import { createStorefront } from "@commercengine/storefront-sdk-nextjs";
377
+ ```
638
378
 
639
379
  ## License
640
380
 
641
- All Rights Reserved
381
+ All Rights Reserved