Frameworks
Next.js App Router
Full setup guide for Next.js with server and client components
Install
npm install @behio/storefront-sdkClient Setup
import { BehioStorefront } from '@behio/storefront-sdk';
export const storefront = new BehioStorefront({
apiKey: process.env.NEXT_PUBLIC_BEHIO_API_KEY!,
});The public API key is safe to expose — it only grants read access to the storefront and scoped cart/checkout operations.
Provider
Wrap your app with BehioProvider in a client component:
'use client';
import { BehioProvider } from '@behio/storefront-sdk/react';
import { storefront } from '@/lib/behio';
export function Providers({ children }: { children: React.ReactNode }) {
return <BehioProvider client={storefront}>{children}</BehioProvider>;
}import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}Server Component — Product List
Fetch data directly on the server, zero client-side JavaScript:
import { storefront } from '@/lib/behio';
export default async function ProductsPage() {
const { items } = await storefront.catalog.getProducts({ limit: 12 });
return (
<div className="grid grid-cols-3 gap-4">
{items.map(product => (
<div key={product.id}>
<h3>{product.name}</h3>
<p>{product.price} {product.currency}</p>
</div>
))}
</div>
);
}Client Component — Add to Cart
Interactive features use hooks in 'use client' components:
'use client';
import { useAddToCart } from '@behio/storefront-sdk/react';
export function AddToCartButton({ productId }: { productId: string }) {
const addItem = useAddToCart();
return (
<button
onClick={() => addItem.mutateAsync({ productId, quantity: 1 })}
disabled={addItem.isPending}
>
{addItem.isPending ? 'Adding...' : 'Add to Cart'}
</button>
);
}Product Detail Page
Combine server-side data fetching with client-side interactivity:
import { storefront } from '@/lib/behio';
import { AddToCartButton } from './add-to-cart';
import { notFound } from 'next/navigation';
export default async function ProductPage({ params }: { params: { slug: string } }) {
const product = await storefront.catalog.getProduct(params.slug).catch(() => null);
if (!product) notFound();
return (
<div>
<img src={product.image} alt={product.name} />
<h1>{product.name}</h1>
<p>{product.price} {product.currency}</p>
<p>{product.description}</p>
<AddToCartButton productId={product.id} />
</div>
);
}Cart Page
Fully client-side with hooks:
'use client';
import { useCart, useUpdateCartItem, useRemoveCartItem, useCheckout } from '@behio/storefront-sdk/react';
export default function CartPage() {
const { data: cart, isLoading } = useCart();
const updateQty = useUpdateCartItem();
const removeItem = useRemoveCartItem();
const checkout = useCheckout();
if (isLoading) return <div>Loading cart...</div>;
if (!cart || cart.items.length === 0) return <div>Cart is empty</div>;
return (
<div>
{cart.items.map(item => (
<div key={item.id} className="flex items-center gap-4">
<span>{item.productName}</span>
<input
type="number"
value={Number(item.quantity)}
onChange={e => updateQty.mutateAsync({
itemId: item.id,
quantity: Number(e.target.value),
})}
/>
<button onClick={() => removeItem.mutateAsync(item.id)}>Remove</button>
</div>
))}
<p>Total: {cart.grandTotal} {cart.currency}</p>
</div>
);
}Environment Variables
NEXT_PUBLIC_BEHIO_API_KEY=pk_live_your_key