Build a single-page ordering storefront using React 19, Vite, and @craveup/storefront-sdk. This guide covers project setup, fetching menus, and managing a cart — all in the browser.
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 React project
npm create vite@latest my-storefront -- --template react-ts
cd my-storefront
2. Install the SDK
npm install @craveup/storefront-sdk
3. Set environment variables
Create a .env file in the project root:
VITE_CRAVEUP_API_KEY=sk_live_your_api_key
VITE_LOCATION_ID=loc_your_location_id
VITE_LOCATION_SLUG=your-restaurant-slug
Vite exposes variables prefixed with VITE_ to client code via import.meta.env.
4. Create the storefront client
import { createStorefrontClient } from '@craveup/storefront-sdk';
export const storefront = createStorefrontClient({
apiKey: import.meta.env.VITE_CRAVEUP_API_KEY,
});
5. Fetch and display the menu
import { useEffect, useState } from 'react';
import { storefront } from './lib/storefront';
import type { MerchantApiResponse } from '@craveup/storefront-sdk';
const LOCATION_SLUG = import.meta.env.VITE_LOCATION_SLUG;
function App() {
const [merchant, setMerchant] = useState<MerchantApiResponse | null>(null);
useEffect(() => {
storefront.merchant.getBySlug(LOCATION_SLUG).then(setMerchant);
}, []);
if (!merchant) return <p>Loading...</p>;
return (
<div style={{ maxWidth: 800, margin: '0 auto', padding: 32 }}>
<h1>{merchant.name}</h1>
<p>{merchant.bio}</p>
<h2>Locations</h2>
{merchant.locations.map((loc) => (
<div key={loc.id} style={{ padding: 16, border: '1px solid #ddd', borderRadius: 8, marginTop: 12 }}>
<strong>{loc.restaurantDisplayName}</strong>
<p>{loc.addressString}</p>
</div>
))}
</div>
);
}
export default App;
6. Add cart functionality
Create a simple hook to manage the ordering session and cart state.
import { useState, useCallback } from 'react';
import { storefront } from '../lib/storefront';
import type { StorefrontCart } from '@craveup/storefront-sdk';
const LOCATION_ID = import.meta.env.VITE_LOCATION_ID;
export function useCart() {
const [cartId, setCartId] = useState<string | null>(null);
const [cart, setCart] = useState<StorefrontCart | null>(null);
const startSession = useCallback(async () => {
const session = await storefront.orderingSessions.start(LOCATION_ID, {
marketplaceId: LOCATION_ID,
});
if (session.cartId) setCartId(session.cartId);
return session.cartId;
}, []);
const addItem = useCallback(async (productId: string, quantity = 1) => {
const id = cartId ?? (await startSession());
if (!id) return;
const result = await storefront.cart.addItem(LOCATION_ID, id, {
productId,
quantity,
selections: [],
itemUnavailableAction: 'remove_item',
});
setCart(result.cart);
setCartId(result.cartId);
}, [cartId, startSession]);
const refreshCart = useCallback(async () => {
if (!cartId) return;
const updated = await storefront.cart.get(LOCATION_ID, cartId);
setCart(updated);
}, [cartId]);
return { cart, cartId, addItem, refreshCart, startSession };
}
7. Run the dev server
Open the URL shown in the terminal (usually http://localhost:5173).
Next steps