ce-nextjs-patterns
4
总安装量
4
周安装量
#48965
全站排名
安装命令
npx skills add https://github.com/commercengine/skills --skill ce-nextjs-patterns
Agent 安装分布
opencode
4
gemini-cli
4
claude-code
4
github-copilot
4
codex
4
kimi-cli
4
Skill 文档
Next.js Patterns
For basic setup, see setup/.
Impact Levels
- CRITICAL – Breaking bugs, security holes
- HIGH – Common mistakes
- MEDIUM – Optimization
References
| Reference | Impact |
|---|---|
references/server-vs-client.md |
CRITICAL – storefront(cookies()) vs storefront() |
references/token-management.md |
HIGH – Cookie-based token flow in Next.js |
Mental Model
The storefront() function adapts to the execution context:
| Context | Usage | Token Storage |
|---|---|---|
| Client Components | storefront() |
Browser cookies |
| Server Components | storefront(cookies()) |
Request cookies |
| Server Actions | storefront(cookies()) |
Request cookies (read + write) |
| Root Layout | storefront({ isRootLayout: true }) |
Memory fallback |
| Build time (SSG) | storefront() |
Memory (no user context) |
Setup
1. Install
npm install @commercengine/storefront-sdk-nextjs
2. Create Config
// lib/storefront.ts
export { storefront } from "@commercengine/storefront-sdk-nextjs";
3. Root Layout
// app/layout.tsx
import { StorefrontSDKInitializer } from "@commercengine/storefront-sdk-nextjs/client";
import { storefront } from "@/lib/storefront";
// Root Layout requires explicit flag â no request context available
const sdk = storefront({ isRootLayout: true });
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<StorefrontSDKInitializer />
<h1>Welcome to My Brand Store</h1>
{children}
</body>
</html>
);
}
4. Environment Variables
# .env.local
NEXT_PUBLIC_STORE_ID=your-store-id
NEXT_PUBLIC_API_KEY=your-api-key
NEXT_BUILD_CACHE_TOKENS=true # Faster builds with token caching
Key Patterns
Server Component (Data Fetching)
// app/products/page.tsx
import { storefront } from "@/lib/storefront";
import { cookies } from "next/headers";
export default async function ProductsPage() {
const sdk = storefront(cookies());
const { data, error } = await sdk.catalog.listProducts({
page: 1, limit: 20,
});
if (error) return <p>Error: {error.message}</p>;
return (
<div>
{data.products.map((product) => (
<div key={product.id}>{product.name}</div>
))}
</div>
);
}
Server Actions (Mutations)
// app/actions.ts
"use server";
import { storefront } from "@/lib/storefront";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
export async function loginWithEmail(email: string) {
const sdk = storefront(cookies());
const { data, error } = await sdk.auth.loginWithEmail({
email,
register_if_not_exists: true,
});
if (error) return { error: error.message };
return { otp_token: data.otp_token, otp_action: data.otp_action };
}
export async function verifyOtp(otp: string, otpToken: string, otpAction: string) {
const sdk = storefront(cookies());
const { data, error } = await sdk.auth.verifyOtp({
otp,
otp_token: otpToken,
otp_action: otpAction,
});
if (error) return { error: error.message };
redirect("/account");
}
export async function addToCart(cartId: string, productId: string, variantId: string | null) {
const sdk = storefront(cookies());
const { data, error } = await sdk.cart.addDeleteCartItem(
{ id: cartId },
{ product_id: productId, variant_id: variantId, quantity: 1 }
);
if (error) return { error: error.message };
return { cart: data.cart };
}
Static Site Generation (SSG)
// app/products/[slug]/page.tsx
import { storefront } from "@/lib/storefront";
// Pre-render product pages at build time
export async function generateStaticParams() {
const sdk = storefront(); // No cookies at build time
const { data } = await sdk.catalog.listProducts({ limit: 100 });
return (data?.products ?? []).map((product) => ({
slug: product.slug,
}));
}
export default async function ProductPage({ params }: { params: { slug: string } }) {
const sdk = storefront(); // No cookies for static pages
const { data, error } = await sdk.catalog.getProductDetail({
product_id_or_slug: params.slug,
});
if (error) return <p>Product not found</p>;
const product = data.product;
return (
<div>
<h1>{product.name}</h1>
<p>{product.selling_price}</p>
{/* AddToCartButton is a Client Component */}
</div>
);
}
Client Component
"use client";
import { storefront } from "@/lib/storefront";
export function AddToCartButton({ productId, variantId }: Props) {
async function handleClick() {
const sdk = storefront(); // No cookies in client components
const { data, error } = await sdk.cart.addDeleteCartItem(
{ id: cartId },
{ product_id: productId, variant_id: variantId, quantity: 1 }
);
}
return <button onClick={handleClick}>Add to Cart</button>;
}
Common Pitfalls
| Level | Issue | Solution |
|---|---|---|
| CRITICAL | Missing cookies() in Server Components |
Use storefront(cookies()) for user-specific data on the server |
| CRITICAL | Auth in Server Components instead of Actions | Auth endpoints that return tokens MUST be in Server Actions, not Server Components |
| HIGH | Missing StorefrontSDKInitializer |
Required in root layout for automatic anonymous auth and session continuity |
| HIGH | Using cookies() in Client Components |
Client Components use storefront() (no cookies) â tokens managed via browser cookies |
| MEDIUM | Slow builds | Set NEXT_BUILD_CACHE_TOKENS=true for token caching during SSG |
| MEDIUM | Root Layout missing isRootLayout flag |
Root Layout runs outside request context â use storefront({ isRootLayout: true }) |
See Also
setup/– Basic SDK installationauth/– Authentication flowscart-checkout/– Cart management
Documentation
- Next.js Integration: https://www.commercengine.io/docs/sdk/nextjs-integration
- Token Management: https://www.commercengine.io/docs/sdk/token-management
- LLM Reference: https://llm-docs.commercengine.io/sdk/