Build a fully functional ordering storefront using Next.js 15 (App Router) and @craveup/storefront-sdk. By the end of this guide you will fetch menus, display products, and add items to a cart.
Prerequisites
Node.js 18+ and a package manager (pnpm, npm, or yarn)
A Crave API key from the Dashboard
At least one live location in your merchant account
1. Create a Next.js project
npx create-next-app@latest my-storefront --typescript --app --tailwind
cd my-storefront
2. Install the SDK
npm install @craveup/storefront-sdk
3. Set environment variables
Create a .env.local file in the root of your project with the following variables:
NEXT_PUBLIC_CRAVEUP_API_KEY=sk_live_your_api_key
NEXT_PUBLIC_LOCATION_ID=loc_your_location_id
NEXT_PUBLIC_LOCATION_SLUG=your-restaurant-slug
Variable Description NEXT_PUBLIC_CRAVEUP_API_KEYLocation-scoped API key from the Dashboard NEXT_PUBLIC_LOCATION_IDThe location ID to load menus and accept orders for NEXT_PUBLIC_LOCATION_SLUGHuman-readable slug used for merchant lookups
Use different API keys per environment (development, staging, production). The SDK reads NEXT_PUBLIC_CRAVEUP_API_KEY by default.
4. Create the storefront client
Create a shared client instance that every server and client component can import.
import { createStorefrontClient } from '@craveup/storefront-sdk' ;
export const storefront = createStorefrontClient ({
apiKey: process . env . NEXT_PUBLIC_CRAVEUP_API_KEY ! ,
});
5. Fetch merchant data (Server Component)
Use a React Server Component to load the merchant and its locations at request time.
import { storefront } from '@/lib/storefront' ;
export default async function HomePage () {
const merchant = await storefront . merchant . getBySlug (
process . env . NEXT_PUBLIC_LOCATION_SLUG !
);
return (
< main className = "max-w-4xl mx-auto p-8" >
< h1 className = "text-3xl font-bold" > { merchant . name } </ h1 >
< p className = "text-gray-600 mt-2" > { merchant . bio } </ p >
< h2 className = "text-xl font-semibold mt-8" > Locations </ h2 >
< ul className = "mt-4 space-y-3" >
{ merchant . locations . map (( loc ) => (
< li key = { loc . id } className = "p-4 border rounded-lg" >
< p className = "font-medium" > { loc . restaurantDisplayName } </ p >
< p className = "text-sm text-gray-500" > { loc . addressString } </ p >
</ li >
)) }
</ ul >
</ main >
);
}
6. Start an ordering session and display the cart
Create a Client Component that starts a session and lets users add items.
'use client' ;
import { useEffect , useState } from 'react' ;
import { storefront } from '@/lib/storefront' ;
import type { StorefrontCart } from '@craveup/storefront-sdk' ;
const LOCATION_ID = process . env . NEXT_PUBLIC_LOCATION_ID ! ;
export default function OrderPage () {
const [ cart , setCart ] = useState < StorefrontCart | null >( null );
const [ cartId , setCartId ] = useState < string | null >( null );
useEffect (() => {
storefront . orderingSessions
. start ( LOCATION_ID , { marketplaceId: LOCATION_ID })
. then (( session ) => {
if ( session . cartId ) setCartId ( session . cartId );
});
}, []);
async function addItem ( productId : string ) {
if ( ! cartId ) return ;
const result = await storefront . cart . addItem ( LOCATION_ID , cartId , {
productId ,
quantity: 1 ,
selections: [],
itemUnavailableAction: 'remove_item' ,
});
setCart ( result . cart );
}
return (
< main className = "max-w-4xl mx-auto p-8" >
< h1 className = "text-2xl font-bold" > Order </ h1 >
< button
onClick = { () => addItem ( 'prod_margherita' ) }
className = "mt-4 px-4 py-2 bg-teal-600 text-white rounded"
>
Add Margherita Pizza
</ button >
{ cart && (
< div className = "mt-6 p-4 border rounded-lg" >
< p className = "font-medium" > Cart ( { cart . totalQuantity } items) </ p >
< p className = "text-lg mt-1" > Total: { cart . orderTotalWithServiceFeeFormatted } </ p >
</ div >
) }
</ main >
);
}
7. Run the dev server
Open http://localhost:3000 to see your merchant info, and navigate to /order to test the cart.
Next steps
Display Menu Fetch menus, categories, and products for a location.
Manage Cart Add, update, and remove items with modifiers.
Checkout Flow Collect customer details and process payments.
SDK Reference Full SDK documentation with all available modules.
Slack Community Ask questions and get help from the Crave team and community.
Discord Join our Discord server for real-time discussions.