[Restaurant Name] · Menu + Ordering
A restaurant marketing + ordering site. Menu syncs from Square so the owner edits once. Orders route to the kitchen via Square. The site charges nothing extra.
Source of truth
Square is the source for menu items, prices, modifiers, and inventory. The site reads Square Catalog at build time and caches. Orders POST to Square Orders API. Reservations link out to OpenTable or Resy.
Tech stack
Next.js 15 (App Router) + React + Tailwind v4. Square Web SDK for the payment card form, Square Orders API for order creation. Cloudinary for food photography. Resend for confirmation emails. ISR (Incremental Static Regen) for menu pages, revalidating every 5 minutes.
Deploy
git push origin main. Vercel auto-deploys. Square webhook configured to revalidate the menu page on catalog updates.
File map
app/page.tsxhome: hero photo, today's specials, ordering CTA, location/hoursapp/menu/page.tsxfull menu, categorized, sourced from Square Catalogapp/order/page.tsxcart + checkoutapp/order/confirmation/[orderId]/page.tsxpost-order screenapp/locations/[slug]/page.tsxper-location page (hours, address, photos, map)app/api/order/route.tsPOST -> Square Orders + Square Paymentsapp/api/webhook/square/route.tsSquare webhook: catalog.updated triggers revalidationlib/square.tsSquare SDK clientlib/cart.tslocalStorage cart with modifier support
.env keys
SQUARE_ACCESS_TOKENSQUARE_LOCATION_IDSQUARE_WEBHOOK_SIGNATURE_KEYSQUARE_ENVIRONMENTproduction|sandboxNEXT_PUBLIC_SQUARE_APPLICATION_ID(Web SDK)RESEND_API_KEYRESEND_FROM_EMAIL
Hard rules
- Menu prices come from Square. Never hardcode a price in JSX.
- Cart modifiers map to Square modifier IDs. Test that a "no cilantro" modifier reaches the printer.
- Pickup-only for v0. Delivery is a different beast (DoorDash Drive integration is a separate template).
- Tax + tip computed via Square (
calculateOrder), never client-side. State sales tax + alcohol rules are complex. - Photos of food are real, shot tight, well-lit. Stock photos of "delicious burger" kill orders.
- Confirmation page shows estimated ready time + pickup instructions (the exact door, parking note).
- Square webhook signature is verified before any state change.
Recent significant changes
- 2026-05-04: Scaffolded. Locked: Square direct (the restaurant already owns the hardware), pickup-only v0, no third-party marketplace integration (the whole point).
Next session: start here
- Get Square access from the restaurant. Sandbox first, production later.
- Sync menu: confirm
square.catalog.searchCatalogItemsreturns the actual items. - Build cart + checkout flow with sandbox cards.
- Test a real $1 order end-to-end. Confirm receipt prints in the kitchen.
- Set up Square webhook for catalog updates -> Next.js revalidation.