Skip to main content
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
VariableDescription
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

pnpm dev
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.

Email Support

Reach out to hello@craveup.com for direct support.