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