Skip to content

Latest commit

 

History

History
173 lines (127 loc) · 6.14 KB

File metadata and controls

173 lines (127 loc) · 6.14 KB

TonyMenu

Self-hostable digital restaurant menu, built on Next.js. Cloudflare is the recommended hosted target; Docker + SQLite is available when you do not want a Cloudflare account. Diners scan a QR code, browse a localized menu, and can ask an optional AI assistant for recommendations.

Restaurant owners manage the menu from /admin. QR codes should point to /; the app detects the locale and redirects diners to the localized menu.

Live demo

Try the public demo: https://demo.tonymenu.app

The demo is editable and public. Data resets automatically, so do not enter real customer data. Tony, the menu assistant, is enabled with a daily usage cap for the demo.

Mobile menu Mobile item detail Tony chat
Desktop admin

What it does

  • Public QR menu from /, with locale detection and localized category and item content.
  • Admin SPA at /admin for settings, categories, entries, variants, extras, images, opening hours, publishing, and translations.
  • Optional AI chat assistant that can recommend items from the current menu.
  • Privacy-safe catalog view tracking for basic analytics.
  • Cloudflare Access admin auth, so there is no in-app password system to run.

License

PolyForm Noncommercial 1.0.0 — free for personal, non-commercial, academic, charity, and government use.

Commercial use (running it for a paying restaurant, hosting it as a service, embedding it in a paid product) requires a separate license. See COMMERCIAL.md.

Stack

Component What
web/ Next.js 16 (App Router), deployed to Cloudflare Pages or static Docker
backend/ Hono API on Cloudflare Workers/D1 or Node/SQLite
web/workers/chat/ Chat service on Cloudflare Workers or Node, with SSE streaming and tool calls
packages/schemas/ Shared Zod schemas (@menu/schemas)
Auth Cloudflare Access, or trusted reverse-proxy header in Docker
Storage R2/KV on Cloudflare, or filesystem uploads + in-memory chat cache in Docker

Self-hosting

Cloudflare prerequisites: Node 22+, npm 10+, Git, and a Cloudflare account with Zero Trust enabled.

No-Cloudflare quick start:

cp .env.self-host.example .env
# set ADMIN_PASSWORD_HASH; see docs/self-hosting-without-cloudflare.md
docker compose up --build

Then open the proxy on port 8080.

Quick local setup:

git clone https://github.com/vekexasia/tony-menu.git
cd tony-menu

npm ci
cd web/workers/chat && npm ci && cd -

# Create .tony-menu.local.json and generated local config files
npm run initialize

# If you accepted placeholder IDs, provision Cloudflare resources, update
# .tony-menu.local.json, then regenerate
# (also create an R2 bucket if you want image uploads/catalog snapshots)
(cd backend && npx wrangler d1 create menu-db)
(cd web/workers/chat && npx wrangler kv namespace create MENU_CACHE)
(cd backend && npx wrangler r2 bucket create menu-public)
npm run config:generate

# Apply local migrations
(cd backend && npx wrangler d1 migrations apply menu-db --local)

# Terminal 1: backend API
cd backend && npm run dev

# Terminal 2: chat worker
cd web/workers/chat && npm run dev

# Terminal 3: frontend
cd web && npm run dev

Open the frontend dev server's root path for the diner menu.

/admin should be protected by Cloudflare Access. In local dev, point NEXT_PUBLIC_API_URL at a backend that can authenticate you, or run the backend with DEMO_MODE=true for demo-only access. The first migration seeds a settings row named "My Restaurant"; change it from /admin?s=settings.

Common commands

# Frontend
cd web && npm run dev
cd web && npm run build
cd web && npm run test:run
cd web && npm run deploy:cf      # CF_PAGES_PROJECT defaults to "menu"

# Backend API
cd backend && npm run dev
cd backend && npm run check
cd backend && npm run test:run
cd backend && npm run deploy

# Chat worker
cd web/workers/chat && npm run dev
cd web/workers/chat && npm run test:run
cd web/workers/chat && npm run deploy

Upgrading

When pulling a new version of TonyMenu into an existing self-hosted deployment:

git pull
npm install

# 1. Apply any new D1 migrations on the remote database BEFORE deploying
#    new worker code. Drizzle skips already-applied migrations automatically.
(cd backend && npx wrangler d1 migrations apply menu-db --remote)

# 2. Deploy the backend (and chat worker if changed).
(cd backend && npm run deploy)
(cd web/workers/chat && npm run deploy)

# 3. Deploy the frontend.
(cd web && npm run deploy:cf)

There is a brief window during step 2 where the migrated DB is being served by the previous worker revision. For low-traffic deployments this is invisible; for high-traffic ones, expect a few seconds of 5xx until the new revision propagates.

Per-release migration notes (data backfill rules, breaking API shape changes, admin UI changes that require operator action) live in CHANGELOG.md.

Documentation

Contact