@commercengine/storefront-sdk-nextjs 0.1.0-alpha.1 → 1.0.0-alpha.2

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,14 +1,15 @@
1
1
  # CommerceEngine Next.js SDK
2
2
 
3
- **Production-ready Next.js wrapper** for the CommerceEngine Storefront SDK. Handles the complexities of Next.js runtime environments, automatic token management, and cookie-based authentication across all contexts.
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.
4
4
 
5
- **✨ What makes this special:**
6
- - **🎯 Universal API** - Single `storefront()` function works everywhere
5
+ **✨ Perfect DX Pattern:**
6
+ - **🎯 One Config File** - Single `lib/storefront.ts` using `createStorefront()`
7
+ - **🌍 Universal API** - Same `storefront()` import works everywhere
7
8
  - **🔥 Automatic Tokens** - Creates and manages tokens automatically
8
- - **🧠 Smart Environment Detection** - Detects Server vs Client contexts
9
+ - **🧠 Smart Context Detection** - Detects Server vs Client vs Build contexts
9
10
  - **🍪 Cookie-based State** - Shared authentication via Next.js cookies
10
11
  - **⚡ Request Isolation** - Proper per-request SDK instances on server
11
- - **🛠 Zero Configuration** - Works with environment variables out of the box
12
+ - **🛠 Zero Complexity** - Environment variables + one lib file = done
12
13
 
13
14
  ## Installation
14
15
 
@@ -20,35 +21,79 @@ pnpm add @commercengine/storefront-sdk-nextjs
20
21
 
21
22
  ## Quick Start
22
23
 
23
- ### 1. Environment Variables
24
+ ### 1. Environment Variables (Required)
24
25
 
25
26
  Add your store configuration to `.env.local`:
26
27
 
27
28
  ```bash
28
29
  NEXT_PUBLIC_STORE_ID=your-store-id
29
- NEXT_PUBLIC_ENVIRONMENT=staging # or "production"
30
30
  NEXT_PUBLIC_API_KEY=your-api-key
31
31
  ```
32
32
 
33
- ### 2. Initialize in Root Layout
33
+ **Optional environment variables:**
34
+ ```bash
35
+ # Environment (defaults to "staging")
36
+ NEXT_PUBLIC_ENVIRONMENT=staging # or "production"
37
+
38
+ # Custom API endpoint (overrides environment default)
39
+ NEXT_PUBLIC_API_BASE_URL=https://your-custom-api.example.com
40
+
41
+ # Request timeout in milliseconds
42
+ NEXT_PUBLIC_API_TIMEOUT=10000
43
+
44
+ # Debug mode (defaults to false)
45
+ NEXT_PUBLIC_DEBUG_MODE=true
46
+
47
+ # Default customer group for pricing and promotions
48
+ NEXT_PUBLIC_DEFAULT_CUSTOMER_GROUP_ID=01JHS28V83KDWTRBXXJQRTEKA0
49
+ ```
50
+
51
+ ### 2. Create Your Storefront Configuration
52
+
53
+ Create `lib/storefront.ts` in your project:
54
+
55
+ ```typescript
56
+ // lib/storefront.ts
57
+ import {
58
+ createStorefront,
59
+ type StorefrontRuntimeConfig,
60
+ } from "@commercengine/storefront-sdk-nextjs";
61
+
62
+ // Optional advanced configuration (everything not in environment variables)
63
+ const storefrontConfig: StorefrontRuntimeConfig = {
64
+ debug: true,
65
+ timeout: 15000,
66
+ logger: (msg: string, ...args: any[]) =>
67
+ console.log("[STOREFRONT]", msg, ...args),
68
+ onTokensUpdated: (access: string, refresh: string) => {
69
+ console.log("🔥 TOKENS UPDATED:", {
70
+ access: access.slice(0, 20) + "...",
71
+ refresh: refresh.slice(0, 20) + "...",
72
+ });
73
+ },
74
+ onTokensCleared: () => {
75
+ console.log("🔄 TOKENS CLEARED");
76
+ },
77
+ };
78
+
79
+ // Create the configured storefront function
80
+ export const storefront = createStorefront(storefrontConfig);
81
+
82
+ // Re-export types for convenience
83
+ export type { StorefrontRuntimeConfig };
84
+ ```
85
+
86
+ ### 3. Initialize in Root Layout
34
87
 
35
88
  ```typescript
36
89
  // app/layout.tsx
37
- import { Environment, StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
90
+ import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
38
91
 
39
92
  export default function RootLayout({ children }: { children: React.ReactNode }) {
40
93
  return (
41
94
  <html lang="en">
42
95
  <body>
43
- <StorefrontSDKInitializer
44
- config={{
45
- storeId: process.env.NEXT_PUBLIC_STORE_ID || "",
46
- environment: process.env.NEXT_PUBLIC_ENVIRONMENT === "production"
47
- ? Environment.Production
48
- : Environment.Staging,
49
- apiKey: process.env.NEXT_PUBLIC_API_KEY,
50
- }}
51
- />
96
+ <StorefrontSDKInitializer />
52
97
  {children}
53
98
  </body>
54
99
  </html>
@@ -56,57 +101,39 @@ export default function RootLayout({ children }: { children: React.ReactNode })
56
101
  }
57
102
  ```
58
103
 
59
- ### 3. Use Anywhere with the Universal API
104
+ ### 4. Use Anywhere with Universal Import
60
105
 
61
106
  ```typescript
62
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
63
- import { cookies } from "next/headers";
107
+ // Import your configured storefront everywhere
108
+ import { storefront } from "@/lib/storefront";
109
+ import { cookies } from "next/headers"; // Only for server contexts
64
110
 
65
- // Client Component - No cookies needed
111
+ // Client Component - No cookies needed
66
112
  const products = await storefront().catalog.listProducts();
67
113
 
68
- // Server Component, Server Action, or API Route
114
+ // Server Component, Server Action, or API Route - MUST pass cookies
69
115
  const products = await storefront(cookies()).catalog.listProducts();
70
- ```
71
-
72
- ## Usage in Different Next.js Contexts
73
-
74
- ### Server Components
75
116
 
76
- Server Components run on the server and can **read** cookies but cannot **write** them. Each request gets its own SDK instance with independent token management.
117
+ // Root Layout - Special exception with explicit flag
118
+ const products = await storefront({ isRootLayout: true }).catalog.listProducts();
77
119
 
78
- ```typescript
79
- // app/products/page.tsx
80
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
81
- import { cookies } from "next/headers";
82
-
83
- export default async function ProductsPage() {
84
- const sdk = storefront(cookies());
85
-
86
- // This will generate a new anonymous token for this request
87
- // Note: Token cannot be persisted (cookies are read-only in Server Components)
88
- const { data: products } = await sdk.catalog.listProducts();
89
-
90
- return (
91
- <div>
92
- {products?.products.map(product => (
93
- <div key={product.id}>{product.name}</div>
94
- ))}
95
- </div>
96
- );
97
- }
120
+ // ✅ SSG/ISR (build contexts) - Automatic fallback to memory storage
121
+ // (NEXT_BUILD_CACHE_TOKENS=true enables this)
122
+ const products = await storefront().catalog.listProducts();
98
123
  ```
99
124
 
125
+ ## Usage in Different Next.js Contexts
126
+
100
127
  ### Client Components
101
128
 
102
- Client Components run in the browser and can both read and write cookies, enabling persistent authentication.
129
+ Client Components run in the browser and can persist tokens via cookies:
103
130
 
104
131
  ```typescript
105
132
  // components/ProductList.tsx
106
133
  "use client";
107
134
 
108
135
  import { useState, useEffect } from "react";
109
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
136
+ import { storefront } from "@/lib/storefront";
110
137
 
111
138
  export default function ProductList() {
112
139
  const [products, setProducts] = useState([]);
@@ -115,7 +142,7 @@ export default function ProductList() {
115
142
  async function loadProducts() {
116
143
  const sdk = storefront(); // No cookies() needed on client-side
117
144
 
118
- // This will create and persist tokens via cookies
145
+ // Tokens are automatically managed by StorefrontSDKInitializer
119
146
  const { data } = await sdk.catalog.listProducts();
120
147
  if (data) setProducts(data.products);
121
148
  }
@@ -133,51 +160,62 @@ export default function ProductList() {
133
160
  }
134
161
  ```
135
162
 
163
+ ### Server Components
164
+
165
+ Server Components run on the server and can read cookies:
166
+
167
+ ```typescript
168
+ // app/products/page.tsx
169
+ import { storefront } from "@/lib/storefront";
170
+ import { cookies } from "next/headers";
171
+
172
+ export default async function ProductsPage() {
173
+ const sdk = storefront(cookies());
174
+
175
+ const { data: products } = await sdk.catalog.listProducts();
176
+
177
+ return (
178
+ <div>
179
+ {products?.products.map(product => (
180
+ <div key={product.id}>{product.name}</div>
181
+ ))}
182
+ </div>
183
+ );
184
+ }
185
+ ```
186
+
136
187
  ### Server Actions
137
188
 
138
- Server Actions run on the server and can both read and write cookies, making them perfect for authentication flows.
189
+ Server Actions can both read and write cookies, perfect for authentication:
139
190
 
140
191
  ```typescript
141
192
  // app/actions.ts
142
193
  "use server";
143
194
 
144
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
195
+ import { storefront } from "@/lib/storefront";
145
196
  import { cookies } from "next/headers";
146
197
 
147
198
  export async function loginWithEmail(email: string, password: string) {
148
199
  const sdk = storefront(cookies());
149
200
 
150
- // This will create and persist tokens via cookies
151
201
  const { data, error } = await sdk.auth.loginWithPassword({ email, password });
152
202
 
153
203
  if (data) {
154
- // Tokens are automatically saved to cookies by the SDK
204
+ // Tokens are automatically saved to cookies
155
205
  return { success: true, user: data.user };
156
206
  }
157
207
 
158
208
  return { success: false, error: error?.message };
159
209
  }
160
-
161
- export async function addToCart(productId: string, quantity: number) {
162
- const sdk = storefront(cookies());
163
-
164
- // Uses existing authentication from cookies
165
- const { data } = await sdk.cart.addItem({
166
- product_id: productId,
167
- quantity
168
- });
169
-
170
- return data;
171
- }
172
210
  ```
173
211
 
174
212
  ### API Routes
175
213
 
176
- API Routes work identically to Server Actions - they can read and write cookies.
214
+ API Routes work identically to Server Actions:
177
215
 
178
216
  ```typescript
179
217
  // app/api/products/route.ts
180
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
218
+ import { storefront } from "@/lib/storefront";
181
219
  import { cookies } from "next/headers";
182
220
  import { NextResponse } from "next/server";
183
221
 
@@ -198,16 +236,110 @@ export async function GET() {
198
236
  );
199
237
  }
200
238
  }
239
+ ```
240
+
241
+ ### Root Layout (Special Case)
242
+
243
+ Root Layout requires explicit flag since it's outside request context:
244
+
245
+ ```typescript
246
+ // app/layout.tsx
247
+ import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
248
+ import { storefront } from "@/lib/storefront";
249
+
250
+ // Root Layout requires explicit flag - no request context available
251
+ const sdk = storefront({ isRootLayout: true });
252
+ const { data: storeConfig } = await sdk.store.getStoreConfig();
253
+
254
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
255
+ return (
256
+ <html lang="en">
257
+ <body>
258
+ <StorefrontSDKInitializer />
259
+ <h1>Welcome to {storeConfig?.store_config?.brand.name}</h1>
260
+ {children}
261
+ </body>
262
+ </html>
263
+ );
264
+ }
265
+ ```
266
+
267
+ ## Static Site Generation (SSG) & Build-Time Optimization
268
+
269
+ The SDK provides powerful build-time optimizations through intelligent token caching.
270
+
271
+ ### Enable Build-Time Token Caching
272
+
273
+ ```bash
274
+ # Enable caching during builds
275
+ NEXT_BUILD_CACHE_TOKENS=true pnpm build
276
+ ```
277
+
278
+ ### SSG with generateStaticParams
279
+
280
+ ```typescript
281
+ // app/products/[slug]/page.tsx
282
+ import { storefront } from "@/lib/storefront";
283
+ import { notFound } from "next/navigation";
284
+
285
+ interface ProductPageProps {
286
+ params: Promise<{ slug: string }>;
287
+ }
288
+
289
+ export default async function ProductPage({ params }: ProductPageProps) {
290
+ const { slug } = await params;
291
+ const sdk = storefront(); // No cookies() - uses build-time storage
292
+
293
+ const { data, error } = await sdk.catalog.getProductDetail({
294
+ product_id_or_slug: slug
295
+ });
296
+
297
+ if (error || !data) {
298
+ notFound();
299
+ }
300
+
301
+ return (
302
+ <div>
303
+ <h1>{data.product.name}</h1>
304
+ <p>SKU: {data.product.sku}</p>
305
+ <p>Description: {data.product.short_description}</p>
306
+ </div>
307
+ );
308
+ }
201
309
 
310
+ // Generate static params from real API data
311
+ export async function generateStaticParams() {
312
+ const sdk = storefront(); // Token will be cached and reused
313
+
314
+ const { data: productsData, error } = await sdk.catalog.listProducts({
315
+ limit: 100
316
+ });
317
+
318
+ if (error || !productsData) {
319
+ return [];
320
+ }
321
+
322
+ return productsData.products.map(product => ({
323
+ slug: product.slug || product.id
324
+ }));
325
+ }
326
+ ```
327
+
328
+ ### Build Performance Benefits
329
+
330
+ With token caching enabled:
331
+ - ✅ Token created once and reused across all pages
332
+ - ✅ 100 pages = ~1 anonymous token API call total
333
+ - ✅ Faster builds, dramatically lower API usage
202
334
 
203
335
  ## Authentication Patterns
204
336
 
205
337
  ### Anonymous Users
206
338
 
207
- The SDK automatically creates anonymous tokens when needed:
339
+ The SDK automatically creates anonymous tokens:
208
340
 
209
341
  ```typescript
210
- // This works in any context - creates anonymous token automatically
342
+ // This works everywhere - creates anonymous token automatically
211
343
  const { data: products } = await storefront(cookies()).catalog.listProducts();
212
344
  ```
213
345
 
@@ -235,7 +367,7 @@ export async function loginUser(email: string, password: string) {
235
367
  ```typescript
236
368
  // Server Action - Step 1: Send OTP
237
369
  export async function sendOTP(phone: string, country_code: string) {
238
- const sdk = storefront(cookies());
370
+ const sdk = storefront(await cookies());
239
371
 
240
372
  return await sdk.auth.loginWithPhone({
241
373
  phone,
@@ -246,7 +378,7 @@ export async function sendOTP(phone: string, country_code: string) {
246
378
 
247
379
  // Server Action - Step 2: Verify OTP
248
380
  export async function verifyOTP(otp: string, otp_token: string, otp_action: string) {
249
- const sdk = storefront(cookies());
381
+ const sdk = storefront(await cookies());
250
382
 
251
383
  const { data, error } = await sdk.auth.verifyOtp({
252
384
  otp,
@@ -263,354 +395,165 @@ export async function verifyOTP(otp: string, otp_token: string, otp_action: stri
263
395
  }
264
396
  ```
265
397
 
266
- ## Token Management & Cookie Behavior
267
-
268
- ### How It Works
269
-
270
- 1. **Server Components**: Generate tokens but can't persist them (read-only cookies)
271
- 2. **Client Components**: Generate and persist tokens via `document.cookie`
272
- 3. **Server Actions/API Routes**: Generate and persist tokens via Next.js `cookies()`
273
- 4. **Shared State**: All contexts read from the same cookie storage
274
-
275
- ### Cookie Configuration
276
-
277
- The SDK uses secure cookies with sensible defaults:
278
-
279
- ```typescript
280
- // Advanced cookie configuration (optional)
281
- <StorefrontSDKInitializer
282
- config={{
283
- storeId: "your-store-id",
284
- apiKey: "your-api-key",
285
- tokenStorageOptions: {
286
- prefix: "ce_", // Cookie name prefix
287
- maxAge: 30 * 24 * 60 * 60, // 30 days
288
- path: "/",
289
- secure: true, // HTTPS only (auto-detected)
290
- sameSite: "Lax",
291
- }
292
- }}
293
- />
294
- ```
295
-
296
398
  ## API Reference
297
399
 
298
- ### `storefront()`
400
+ ### `createStorefront(config?)`
299
401
 
300
- **Universal function** that works in all Next.js contexts:
402
+ Creates a configured storefront function that works universally across all Next.js contexts.
301
403
 
302
404
  ```typescript
303
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
304
- import { cookies } from "next/headers";
305
-
306
- // ✅ Client-side (browser)
307
- const sdk = storefront();
308
-
309
- // ✅ Server-side (requires cookies for token persistence)
310
- const sdk = storefront(cookies());
311
-
312
- // ❌ Server-side without cookies (helpful error message)
313
- const sdk = storefront(); // Throws clear error with instructions
314
- ```
315
-
316
- ### `StorefrontSDKInitializer`
317
-
318
- **Client-side initializer** component (must be imported from `/client`):
319
-
320
- ```typescript
321
- import { Environment, StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
322
-
323
- <StorefrontSDKInitializer
324
- config={{
325
- storeId: "your-store-id",
326
- environment: Environment.Production, // or Environment.Staging
327
- apiKey: "your-api-key",
328
-
329
- // Optional: Advanced configuration
330
- tokenStorageOptions: {
331
- prefix: "ce_", // Cookie prefix (default)
332
- maxAge: 30 * 24 * 60 * 60, // 30 days
333
- secure: true, // Auto-detected from environment
334
- sameSite: "Lax",
335
- },
336
- }}
337
- />
338
- ```
339
-
340
- ## Error Handling
341
-
342
- All SDK methods return a consistent error structure:
343
-
344
- ```typescript
345
- const { data, error, response } = await storefront(cookies()).catalog.listProducts();
405
+ import { createStorefront } from "@commercengine/storefront-sdk-nextjs";
346
406
 
347
- if (error) {
348
- console.error("API Error:", error.message, error.code);
349
- console.log("Status:", response.status);
350
- } else {
351
- console.log("Products:", data.products);
352
- }
407
+ export const storefront = createStorefront({
408
+ debug: true,
409
+ logger: (msg, ...args) => console.log('[DEBUG]', msg, ...args)
410
+ });
353
411
  ```
354
412
 
355
- ## Static Site Generation (SSG) & Build-Time Optimization
413
+ **Parameters:**
414
+ - `config` (optional): `StorefrontRuntimeConfig` - Advanced configuration options
356
415
 
357
- The SDK provides powerful build-time optimizations for SSG/ISR that dramatically reduce API calls during the build process through intelligent token caching.
416
+ **Returns:**
417
+ - Universal `storefront()` function that works in all Next.js contexts
358
418
 
359
- ### Automatic Build-Time Token Caching
419
+ ### `StorefrontRuntimeConfig`
360
420
 
361
- Enable automatic token caching during production builds:
421
+ Optional configuration object for `createStorefront()`:
362
422
 
363
423
  ```typescript
364
- // next.config.ts
365
- import type { NextConfig } from "next";
366
- import { PHASE_PRODUCTION_BUILD } from 'next/constants';
367
-
368
- const nextConfig = (phase: string): NextConfig => {
369
- const isBuild = phase === PHASE_PRODUCTION_BUILD;
424
+ interface StorefrontRuntimeConfig {
425
+ // Override environment variables
426
+ storeId?: string;
427
+ apiKey?: string;
428
+ environment?: Environment;
429
+ baseUrl?: string;
430
+ timeout?: number;
431
+ debug?: boolean;
370
432
 
371
- return {
372
- env: {
373
- // Enable build-time token caching during production builds
374
- NEXT_BUILD_CACHE_TOKENS: process.env.NEXT_BUILD_CACHE_TOKENS ?? (isBuild ? 'true' : 'false'),
375
- },
376
- };
377
- };
378
-
379
- export default nextConfig;
433
+ // Advanced options (not available via environment variables)
434
+ accessToken?: string;
435
+ refreshToken?: string;
436
+ defaultHeaders?: SupportedDefaultHeaders;
437
+ logger?: (message: string, ...args: any[]) => void;
438
+ onTokensUpdated?: (accessToken: string, refreshToken: string) => void;
439
+ onTokensCleared?: () => void;
440
+ tokenStorageOptions?: NextJSTokenStorageOptions;
441
+ }
380
442
  ```
381
443
 
382
- ### SSG with generateStaticParams
444
+ ### Universal `storefront()` Function
383
445
 
384
- Create static product pages during build:
446
+ The function returned by `createStorefront()` works in all contexts with strict enforcement:
385
447
 
386
448
  ```typescript
387
- // app/products/[slug]/page.tsx
388
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
389
- import { notFound } from "next/navigation";
449
+ // Client-side (browser)
450
+ const sdk = storefront();
390
451
 
391
- interface ProductPageProps {
392
- params: Promise<{ slug: string }>;
393
- }
452
+ // Server-side (requires cookies for user continuity)
453
+ const sdk = storefront(cookies());
394
454
 
395
- export default async function ProductPage({ params }: ProductPageProps) {
396
- const { slug } = await params;
397
- const sdk = storefront(); // No cookies() - uses build-time storage
398
-
399
- // Get product detail by slug or ID
400
- const { data, error } = await sdk.catalog.getProductDetail({
401
- product_id_or_slug: slug
402
- });
403
-
404
- if (error || !data) {
405
- notFound();
406
- }
407
-
408
- const { product } = data;
409
-
410
- return (
411
- <div>
412
- <h1>{product.name}</h1>
413
- <p>SKU: {product.sku}</p>
414
- <p>Type: {product.product_type}</p>
415
- <p>Description: {product.short_description}</p>
416
- </div>
417
- );
418
- }
455
+ // Root Layout (special exception with explicit flag)
456
+ const sdk = storefront({ isRootLayout: true });
419
457
 
420
- // Generate static params from real API data
421
- export async function generateStaticParams() {
422
- const sdk = storefront(); // No cookies() - uses build-time storage
423
-
424
- const { data: productsData, error } = await sdk.catalog.listProducts({
425
- limit: 100 // Generate pages for first 100 products
426
- });
427
-
428
- if (error || !productsData) {
429
- console.error("Error fetching products for static generation:", error);
430
- return [];
431
- }
432
-
433
- return productsData.products.map(product => ({
434
- slug: product.slug || product.id
435
- }));
436
- }
458
+ // Server-side without cookies - throws helpful error to protect user sessions
459
+ const sdk = storefront(); // ❌ Throws error in server contexts
437
460
  ```
438
461
 
439
- ### SSG Test Page Example
440
-
441
- Create a page that makes multiple API calls during build to test token reuse:
462
+ ### Function Signatures
442
463
 
443
464
  ```typescript
444
- // app/ssg-test/page.tsx
445
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
446
-
447
- export default async function SSGTestPage() {
448
- const sdk = storefront(); // No cookies() - uses build-time storage
449
-
450
- // Make multiple API calls - token will be created once and reused
451
- const { data: products, error: productsError } = await sdk.catalog.listProducts({
452
- limit: 10
453
- });
454
-
455
- const { data: categories, error: categoriesError } = await sdk.catalog.listCategories({
456
- nested_level: 1
457
- });
458
-
459
- const { data: anonymousToken, error: tokenError } = await sdk.auth.getAnonymousToken();
460
-
461
- const buildTime = new Date().toISOString();
462
-
463
- return (
464
- <div>
465
- <h1>SSG Test Page</h1>
466
- <p><strong>Built at:</strong> {buildTime}</p>
467
-
468
- <div>
469
- <h2>Build-time API Results:</h2>
470
-
471
- <div>
472
- <h3>Products Call:</h3>
473
- {productsError ? (
474
- <p style={{ color: 'red' }}>Error: {productsError.message}</p>
475
- ) : (
476
- <p>✅ Success: Found {products?.products?.length || 0} products</p>
477
- )}
478
- </div>
479
-
480
- <div>
481
- <h3>Categories Call:</h3>
482
- {categoriesError ? (
483
- <p style={{ color: 'red' }}>Error: {categoriesError.message}</p>
484
- ) : (
485
- <p>✅ Success: Found {categories?.categories?.length || 0} categories</p>
486
- )}
487
- </div>
488
-
489
- <div>
490
- <h3>Anonymous Token Call:</h3>
491
- {tokenError ? (
492
- <p style={{ color: 'red' }}>Error: {tokenError.message}</p>
493
- ) : (
494
- <p>✅ Success: User ID {anonymousToken?.user?.id}</p>
495
- )}
496
- </div>
497
- </div>
498
- </div>
499
- );
500
- }
465
+ function storefront(): StorefrontSDK;
466
+ function storefront(cookieStore: NextCookieStore): StorefrontSDK;
467
+ function storefront(options: { isRootLayout: true }): StorefrontSDK;
468
+ function storefront(cookieStore: NextCookieStore, options: { isRootLayout?: boolean }): StorefrontSDK;
501
469
  ```
502
470
 
503
- ### Build Performance Benefits
504
-
505
- With token caching enabled, you'll see dramatic performance improvements:
506
-
507
- **Without Caching:**
508
- - 🔴 Each page creates its own token
509
- - 🔴 100 pages = 100+ anonymous token API calls
510
- - 🔴 Slower builds, higher API usage
511
-
512
- **With Caching:**
513
- - ✅ Token created once and reused across all pages
514
- - ✅ 100 pages = ~3 anonymous token API calls total
515
- - ✅ Faster builds, dramatically lower API usage
471
+ ### `StorefrontSDKInitializer`
516
472
 
517
- ### Build Logs to Monitor
473
+ Client-side initializer component (must be imported from `/client`):
518
474
 
519
- When build caching is working, you'll see these logs:
475
+ ```typescript
476
+ import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
520
477
 
521
- ```
522
- 🚀 [BuildCache] Using BuildCachingMemoryTokenStorage with key: store:staging
523
- 🟡 [BuildCache] No cached token found for key: store:staging
524
- 🟠 [BuildCache] Caching new access token for key: store:staging
525
- 🔵 [BuildCache] Using instance token for key: store:staging
526
- 🟢 [BuildCache] Using cached token for key: store:staging
478
+ <StorefrontSDKInitializer />
527
479
  ```
528
480
 
529
- **Key Indicators:**
530
- - ✅ Only 1-3 "Automatically created anonymous session" messages
531
- - ✅ Many "Using instance token" or "Using cached token" messages
532
- - ✅ Minimal "Caching new access token" messages
481
+ No props needed - configuration comes from environment variables and your `lib/storefront.ts` file.
533
482
 
534
- ### Manual Override
483
+ ## Error Handling
535
484
 
536
- You can manually control build caching:
485
+ All SDK methods return a consistent error structure:
537
486
 
538
- ```bash
539
- # Enable caching for this build
540
- NEXT_BUILD_CACHE_TOKENS=true pnpm build
487
+ ```typescript
488
+ const { data, error, response } = await storefront(cookies()).catalog.listProducts();
541
489
 
542
- # Disable caching for this build
543
- NEXT_BUILD_CACHE_TOKENS=false pnpm build
490
+ if (error) {
491
+ console.error("API Error:", error.message, error.code);
492
+ console.log("Status:", response.status);
493
+ } else {
494
+ console.log("Products:", data.products);
495
+ }
544
496
  ```
545
497
 
546
498
  ## Best Practices
547
499
 
548
500
  ### ✅ Do's
549
501
 
502
+ - **Set required environment variables**: `NEXT_PUBLIC_STORE_ID` and `NEXT_PUBLIC_API_KEY` are mandatory
503
+ - **Create one lib/storefront.ts file**: Use `createStorefront()` to configure advanced options
550
504
  - **Initialize once**: Call `StorefrontSDKInitializer` only in your root layout
551
505
  - **Use `storefront(cookies())`**: Always pass cookies in server contexts
552
506
  - **Handle errors**: Always check the error property in responses
553
507
  - **Use Server Actions**: For authentication flows that need to persist tokens
554
- - **Environment variables**: Store sensitive config in environment variables
555
508
 
556
509
  ### ❌ Don'ts
557
510
 
558
511
  - **Don't call `cookies()` in Client Components**: It will throw an error
559
512
  - **Don't initialize multiple times**: The SDK handles singleton behavior
560
513
  - **Don't forget error handling**: API calls can fail for various reasons
561
- - **Don't rely on Server Component token persistence**: They can't write cookies
514
+ - **Don't skip environment variables**: Missing required variables will cause errors
562
515
 
563
516
  ## Troubleshooting
564
517
 
565
518
  ### Common Issues
566
519
 
567
- 1. **"Cookie store passed in client environment"**
520
+ 1. **"Server context requires cookies for user continuity!"**
568
521
  ```typescript
569
- // ❌ Wrong
570
- storefront(cookies()) // in client component
522
+ // ❌ Wrong - server context without cookies (breaks user sessions)
523
+ storefront()
571
524
 
572
- // ✅ Correct
573
- storefront() // in client component
525
+ // ✅ Correct - server context with cookies
526
+ storefront(cookies())
527
+
528
+ // ✅ Root Layout exception
529
+ storefront({ isRootLayout: true })
574
530
  ```
575
531
 
576
- 2. **"SDK not initialized"**
577
- ```typescript
578
- // Make sure StorefrontSDKInitializer is in your root layout
579
- <StorefrontSDKInitializer config={{ ... }} />
532
+ 2. **Missing Environment Variables**
533
+ ```bash
534
+ # Ensure your .env.local has the required variables:
535
+ NEXT_PUBLIC_STORE_ID=your-store-id
536
+ NEXT_PUBLIC_API_KEY=your-api-key
580
537
  ```
581
538
 
582
- 3. **"Cookies can only be modified in Server Action"**
583
- This is expected behavior. Server Components can't persist tokens, but they can still make API calls with per-request tokens.
584
-
585
- 4. **Server Environment Detection Error**
586
- ```
587
- 🚨 Server Environment Detected!
539
+ 3. **"Cookie store passed in client environment"**
540
+ ```typescript
541
+ // ❌ Wrong - client component with cookies
542
+ storefront(cookies())
588
543
 
589
- You're calling storefront() on the server without cookies.
590
- Please pass the Next.js cookie store:
544
+ // Correct - client component without cookies
545
+ storefront()
546
+ ```
547
+
548
+ 4. **Server Actions and async cookies()**
549
+ ```typescript
550
+ // ✅ Correct - Server Actions need await cookies()
551
+ const sdk = storefront(await cookies());
591
552
 
592
- Correct usage:
593
- import { cookies } from 'next/headers';
553
+ // Server Components and API Routes use cookies() directly
594
554
  const sdk = storefront(cookies());
595
-
596
- ❌ Your current usage:
597
- const sdk = storefront(); // Missing cookies!
598
555
  ```
599
556
 
600
- ### Debug Mode
601
-
602
- Enable detailed logging during development:
603
-
604
- ```typescript
605
- <StorefrontSDKInitializer
606
- config={{
607
- storeId: "your-store-id",
608
- apiKey: "your-api-key",
609
- debug: true, // Enable debug logging
610
- }}
611
- />
612
- ```
613
-
614
557
  ## Migration Guide
615
558
 
616
559
  ### From Core SDK
@@ -622,105 +565,36 @@ const sdk = new StorefrontSDK({
622
565
  storeId: "...",
623
566
  tokenStorage: new BrowserTokenStorage()
624
567
  });
625
- await sdk.auth.getAnonymousToken(); // Manual token creation
626
568
 
627
569
  // After (Next.js SDK)
628
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
629
- const sdk = storefront(cookies()); // Automatic token management
570
+ import { storefront } from "@/lib/storefront";
571
+ const sdk = storefront(cookies());
630
572
  ```
631
573
 
632
- ### From Previous Next.js SDK Version
574
+ ### From Previous SDK Versions
633
575
 
634
576
  ```typescript
635
577
  // Before (old pattern)
636
- import { getStorefrontSDK } from "@commercengine/storefront-sdk-nextjs";
578
+ import { getStorefrontSDK, storefront } from "@commercengine/storefront-sdk-nextjs";
637
579
  const sdk = getStorefrontSDK(cookies());
580
+ const sdk2 = storefront(cookies(), { debug: true });
638
581
 
639
- // After (new universal pattern)
640
- import { storefront } from "@commercengine/storefront-sdk-nextjs";
582
+ // After (createStorefront pattern)
583
+ import { storefront } from "@/lib/storefront"; // Your configured function
641
584
  const sdk = storefront(cookies());
642
585
  ```
643
586
 
644
- ## TypeScript Support
645
-
646
- The SDK provides complete TypeScript support with auto-generated types:
647
-
648
- ```typescript
649
- import type {
650
- StorefrontSDK,
651
- ApiResult,
652
- UserInfo,
653
- NextJSSDKConfig,
654
- Environment
655
- } from "@commercengine/storefront-sdk-nextjs";
656
-
657
- // All API responses are properly typed
658
- const { data }: ApiResult<ProductListResponse> = await storefront(cookies()).catalog.listProducts();
659
-
660
- // IntelliSense works for all nested properties
661
- console.log(data?.products[0].name);
662
- ```
663
-
664
- ## User Information
665
-
666
- Get current user information from tokens:
667
-
668
- ```typescript
669
- const sdk = storefront(cookies());
670
-
671
- const userInfo = await sdk.getUserInfo();
672
- const isLoggedIn = await sdk.isLoggedIn();
673
- const isAnonymous = await sdk.isAnonymous();
674
- const userId = await sdk.getUserId();
675
- const customerId = await sdk.getCustomerId();
676
- ```
677
-
678
- ## Advanced Usage
679
-
680
- ### Custom Token Storage
681
-
682
- ```typescript
683
- import { TokenStorage } from "@commercengine/storefront-sdk-nextjs";
684
-
685
- class RedisTokenStorage implements TokenStorage {
686
- async getAccessToken(): Promise<string | null> {
687
- // Your Redis implementation
688
- }
689
-
690
- async setAccessToken(token: string): Promise<void> {
691
- // Your Redis implementation
692
- }
693
-
694
- // ... implement other methods
695
- }
696
-
697
- // Use with the core SDK directly if needed
698
- import { StorefrontSDK } from "@commercengine/storefront-sdk-nextjs";
699
-
700
- const sdk = new StorefrontSDK({
701
- storeId: "your-store-id",
702
- apiKey: "your-api-key",
703
- tokenStorage: new RedisTokenStorage(),
704
- });
705
- ```
706
-
707
- ## Why This Wrapper Exists
708
-
709
- **The core SDK is powerful but complex for Next.js:**
710
- - Manual token storage setup and configuration
711
- - Server/client runtime environment handling
712
- - Cookie configuration for SSR/SSG
713
- - Request isolation and per-request instances
714
- - Next.js-specific execution model complexities
587
+ ## Why This Pattern?
715
588
 
716
- **This wrapper handles it all automatically:**
717
- - Universal `storefront()` API that works everywhere
718
- - Request-scoped server instances with React cache
719
- - Cookie-based token persistence across boundaries
720
- - Environment detection and configuration
721
- - Build-time optimizations for SSG/ISR
589
+ **The Perfect DX Pattern provides:**
590
+ - **One Config File**: All advanced configuration in `lib/storefront.ts`
591
+ - **Environment Variables**: Basic config (storeId, apiKey) via env vars
592
+ - **Universal Import**: Same `storefront()` import everywhere
593
+ - **Strict User Continuity**: Enforces cookie passing to protect user sessions and analytics
594
+ - **Explicit Exceptions**: Clear patterns for special cases like Root Layout
595
+ - **Zero Guesswork**: Helpful errors guide developers to correct patterns
722
596
 
723
- **Result: Production-ready e-commerce with zero complexity!** 🚀
597
+ **Result: Production-ready e-commerce with bulletproof user session management!** 🛡️
724
598
 
725
599
  ## API Reference
726
600