P Pista Docs
✨ Documentation

Pista

Pista is an AI-powered, white-label ordering platform for cafés and restaurant chains. A brand configures its identity and menu once, and gets a polished mobile-first ordering app with AI recommendations, food intelligence, orders, loyalty and an admin dashboard.

This site has two parts: Developer docs (how Pista is built and how to run, extend and deploy it) and User guides (how customers order and how café owners run the admin dashboard).

What's included

🛍️ Customer app

Menu, item detail with AI "Know your cup", AI assistant, cart, checkout, orders, rewards.

📊 Admin dashboard

Analytics, orders, menu CRUD, customers, discounts, branding and settings.

🎨 White-label engine

Brand name, colours, font and AI flags — re-theme the whole app live.

🔐 Real backend

Prisma + SQLite, NextAuth email/password auth, REST API routes.


Getting started

Prerequisites

  • Node.js 18.18+ (Node 20 LTS recommended)
  • npm 9+

Install & run

cd pista
npm install        # also runs `prisma generate`
npm run setup      # creates the SQLite DB (prisma db push) + seeds data
npm run dev        # http://localhost:3000

Open http://localhost:3000. The marketing site is at /; click View live demo to open the ordering app at /menu. The app is mobile-first — narrow your window or use device emulation.

🔑 Demo admin login: demo@pista.app / password. This account has the admin role, so it can open the dashboard at /admin. New sign-ups are customers.

Useful scripts

ScriptWhat it does
npm run devStart the dev server with hot reload
npm run setupprisma db push + seed menu, users, sample orders
npm run seedRe-seed the database
npm run buildprisma generate + production build
npm startRun the production build

Architecture

Pista is a single Next.js 14 (App Router) application. The customer app and admin dashboard are route groups in the same project; both talk to the database through API route handlers (and a few server reads).

Browser (customer app / admin dashboard)
        │  fetch()
        ▼
Next.js App Router  ── pages (client components)
        │
        ├─ /api/menu, /api/menu/[id]      → read menu (public)
        ├─ /api/ai                        → scripted recommender
        ├─ /api/orders, /api/orders/[id]  → place / list / update orders
        ├─ /api/brand                     → white-label config
        ├─ /api/items, /api/items/[id]    → menu CRUD (admin)
        ├─ /api/discounts/*               → promo codes
        ├─ /api/admin/*                   → analytics, all-orders, customers
        └─ /api/auth/[...nextauth]        → NextAuth
        │
        ▼
   Prisma Client ──► SQLite (prisma/dev.db)

Tech stack

LayerChoice
FrameworkNext.js 14 (App Router), React 18
StylingTailwind CSS; brand colours via CSS variables
DatabaseSQLite via Prisma ORM
AuthNextAuth (credentials, JWT sessions), bcrypt
AIRule-based recommender (swappable for an LLM)

Project structure

pista/
├─ app/
│  ├─ layout.js              # root layout + providers + fonts
│  ├─ globals.css            # design tokens (white-label CSS vars)
│  ├─ page.js                # marketing landing (/)
│  ├─ menu/page.js           # ordering app home
│  ├─ item/[id]/page.js      # item detail + AI info
│  ├─ ai/page.js             # Pista AI assistant
│  ├─ cart, checkout, success, account, login, register
│  ├─ admin/                 # dashboard (layout + sub-pages)
│  │  ├─ layout.js           # sidebar + admin-role guard
│  │  ├─ page.js             # Overview (analytics)
│  │  ├─ orders, menu, customers, discounts, branding, settings
│  └─ api/                   # route handlers (REST)
├─ components/               # Providers, Header, BottomNav, ProductCard, AdminUI
├─ lib/                      # db.js, auth.js, admin.js, ai.js, menu.js
├─ prisma/                   # schema.prisma, seed.js, dev.db
└─ public/docs/              # this documentation site

Data model

Defined in prisma/schema.prisma. Array fields on Item (ingredients, allergens, tags, sizes) are stored as JSON strings and parsed by parseItem() in lib/db.js.

ModelKey fields
Brandname, brandHex, darkHex, font, subdomain, aiAssistant, aiCards, aiUpsell, aiLoyalty
Categoryid, label, sort
Itemname, categoryId, price, img, desc, kcal, caffeine, protein, sugar, origin, ingredients, allergens, tags, sizes, aiTip, live
Username, email, password (bcrypt), role (customer/admin), points
OrderuserId, subtotal, tax, reward, discount, discountCode, total, fulfilment, payment, status
OrderItemorderId, itemId, name, size, milk, unit, qty
Discountcode, percent, active

API reference

All routes live under /api. Auth is via the NextAuth session cookie. "Admin" routes require a user with role: "admin" and return 403 otherwise.

Menu

GET/api/menu?all=0|1
Public. Returns { categories, items }. all=1 (admin UI) includes hidden items.
GET/api/menu/[id]
Public. A single parsed item.

AI

POST/api/ai
Public. Body { query }. Returns { intro, picks:[{ item, why }] } scored over live items.

Orders

GET/api/orders
Auth. The signed-in user's orders.
POST/api/orders
Auth. Body { lines, fulfilment, payment, discountCode? }. Recomputes totals server-side, applies promo, awards points.
PATCH/api/orders/[id]
Admin. Body { status } — preparing → ready → completed → cancelled.

Menu management (admin)

POST/api/items
Admin. Create an item.
PUT/api/items/[id]
Admin. Full update.
PATCH/api/items/[id]
Admin. Quick update of live / price.
DELETE/api/items/[id]
Admin. Deletes if not referenced by past orders (else 409 — hide it instead).

Brand, discounts & admin data

GET/api/brand
Public. White-label config.
PUT/api/brand
Admin. Update brand config.
POST/api/discounts/validate
Public. Body { code }{ valid, percent } for checkout.
GET POST/api/discounts
Admin. List / create promo codes. PATCH|DELETE /api/discounts/[id] to toggle / remove.
GET/api/admin/stats
Admin. KPIs, 14-day series, top items, recent orders.
GET/api/admin/orders?status=
Admin. All orders with customer + line items.
GET/api/admin/customers
Admin. Users with order count, spend and points.

Auth

POST/api/register
Public. Body { name, email, password } — creates a customer.
GET POST/api/auth/[...nextauth]
NextAuth sign-in / session / sign-out.

Auth & roles

Authentication is handled by NextAuth's Credentials provider (lib/auth.js). Passwords are hashed with bcrypt; sessions are JWTs. The user's role is embedded in the JWT and exposed on session.user.role.

  • customer — default for sign-ups. Can order, view their orders and earn points.
  • admin — can open /admin and call admin APIs. The seeded demo@pista.app is an admin.

Server routes guard with requireAdmin() (lib/admin.js), which returns 401 when signed out and 403 for non-admins. The admin UI is additionally guarded in app/admin/layout.js.

🔒 To promote a user to admin, set role = "admin" in the database (e.g. via npx prisma studio).

White-label theming

Brand colours are CSS variables (RGB channels) defined in app/globals.css and consumed by Tailwind (bg-brand, text-brand-dark, bg-brand-tint). The BrandProvider in components/Providers.js loads the brand from /api/brand, applies the variables to :root, and the admin "Publish" button persists changes.

:root {
  --brand: 122 176 74;       /* pistachio */
  --brand-dark: 54 81 31;
  --brand-tint: ...;         /* derived */
}

Because every brand-coloured element reads these variables, changing the primary colour in Admin → Branding re-themes the entire customer app instantly.


AI recommender

The assistant is a transparent, rule-based recommender in lib/ai.js, served from POST /api/ai. It maps the user's free-text intent to scoring rules over item metadata (tags, caffeine, calories, protein, rating) and returns the top picks with a human-readable reason for each.

The return shape is { intro, picks: [{ item, why }] }. To switch to a real LLM, replace recommend() with an API call (e.g. the Claude API) that returns the same shape — no UI changes needed.


Deployment

Hosting the app

Pista runs anywhere Next.js does. For Vercel:

  1. Push the repo to GitHub and import it into Vercel.
  2. SQLite isn't suitable for serverless — switch DATABASE_URL to a hosted Postgres and change the Prisma provider to postgresql.
  3. Set env vars: DATABASE_URL, NEXTAUTH_URL, NEXTAUTH_SECRET (openssl rand -base64 32).
  4. Run prisma migrate deploy and seed once.

Hosting these docs

This docs site is a self-contained static page (public/docs/index.html). When the app runs it is served at /docs. To host it on its own, deploy the public/docs folder to any static host:

# preview locally
npx serve public/docs

# or drop public/docs into Netlify / GitHub Pages / Vercel
⚠️ Before production: change NEXTAUTH_SECRET, move off SQLite, and review the demo credentials.

User guide — for customers

How to order on a Pista-powered café app.

1. Browse the menu

Open the app and browse by category (Ice Blended, Hot Coffee, Tea, Food). The ✨ Picked for you row highlights signature and top-rated items. Tap any item to see details.

2. Know what you're ordering

Each item has a "Know your cup" card: bean origin, ingredients, allergens and nutrition (calories, protein, sugar, caffeine), plus an AI tip. Choose a size and milk, then Add to bag.

3. Ask Pista AI

Not sure what to get? Open Pista AI and tap a mood ("Cold & refreshing", "High protein", "Low caffeine") or type your own. It ranks the menu and explains why each pick fits — add any suggestion straight to your bag.

4. Checkout

Review your bag (with an AI pairing suggestion), then check out: choose pickup / dine-in / delivery, add a promo code, pick a payment method and place the order. You'll need an account — sign up takes a moment.

5. Track orders & earn rewards

Your Account shows order history, status and loyalty points (earned on every order).


User guide — for café owners

Running your store from the Pista admin dashboard at /admin (admin login required).

Overview

Your home screen: revenue, order count, average order value and customer count, a 14-day revenue chart, your top sellers, and the latest orders.

Orders

See every order, filter by status, and advance them: Preparing → Ready → Completed. Updates are saved instantly and reflected in the customer's account.

Menu

Add, edit and delete items. Set price, photo, description, nutrition, origin, ingredients, allergens, tags and an AI tip. Toggle an item live to show/hide it without deleting. (Items with past orders can be hidden but not deleted, to preserve history.)

Customers

Your registered customers with order counts, lifetime spend and points.

Discounts

Create promo codes (e.g. WELCOME10 for 10% off). Enable, disable or delete them; customers apply them at checkout.

Branding

Set your brand name, subdomain, colours and font. The live preview updates as you edit; click Publish to apply it to your whole customer app.

Settings

Store details and AI feature flags — turn the assistant, food-intelligence cards, smart upsells and AI loyalty on or off.


FAQ & troubleshooting

I can't open /admin

The dashboard requires the admin role. Sign in with demo@pista.app / password, or promote your user in the database.

The menu is empty

Run npm run setup (or npm run seed) to create and populate the database.

Login fails right after install

Make sure the database is seeded and NEXTAUTH_SECRET is set in .env. Restart npm run dev after changing env vars.

Build warns about Prisma / Next versions

Informational only. Versions are pinned for stability; upgrade deliberately.

How do I reset the data?

Delete prisma/dev.db and run npm run setup again.

Need more? See the API reference or the source in lib/ and app/api/.