Behio Storefront SDK
Frameworks

Next.js App Router

Full setup guide for Next.js with server and client components

Install

npm install @behio/storefront-sdk

Client Setup

lib/behio.ts
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:

app/providers.tsx
'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>;
}
app/layout.tsx
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:

app/products/page.tsx
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:

app/products/[slug]/add-to-cart.tsx
'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:

app/products/[slug]/page.tsx
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:

app/cart/page.tsx
'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

.env.local
NEXT_PUBLIC_BEHIO_API_KEY=pk_live_your_key

On this page