Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GB FoodHub

Production-ready monorepo for the GB FoodHub food ordering ecosystem in Gilgit Baltistan, Pakistan. Three apps share one Supabase backend:

App Path Purpose
Mobile mobile_app/ Flutter customer app — browse, cart, checkout, orders, profile
Web web/ Next.js dashboard — restaurant management, super admin, POS
Backend supabase/ PostgreSQL schema, RLS, seed data, storage, Edge Functions

Table of Contents

  1. Architecture
  2. Repository Structure
  3. Prerequisites
  4. Quick Start (All Apps)
  5. Full Flow
  6. Supabase Backend
  7. Mobile App (Flutter)
  8. Web App (Next.js)
  9. Scripts
  10. Environment Variables
  11. Authentication & User Roles
  12. How the Apps Work Together
  13. Common Development Tasks
  14. Design System
  15. Deployment
  16. Troubleshooting

Architecture

flowchart TB
  subgraph clients [Client Apps]
    Mobile["mobile_app\nFlutter + Riverpod"]
    Web["web\nNext.js 15 + React 19"]
  end

  subgraph supabase [Supabase]
    Auth[Auth]
    DB[(PostgreSQL + RLS)]
    Storage[Storage Buckets]
    Realtime[Realtime]
    Edge[Edge Functions]
  end

  Mobile --> Auth
  Mobile --> DB
  Mobile --> Storage
  Web --> Auth
  Web --> DB
  Web --> Storage
  Web --> Realtime
  Edge --> DB
Loading

Data flow summary

  • Both clients authenticate via Supabase Auth and read/write data through the anon key with Row Level Security (RLS) enforcing access.
  • The mobile app is the customer-facing ordering experience.
  • The web app is the operations layer: restaurant owners manage menus/orders; admins approve restaurants; cashiers run the POS.
  • Edge Functions run server-side jobs (notifications, payments, analytics, email workflows) using the service role key — never expose this key in client apps.

Repository Structure

gb-food-hub/
├── mobile_app/          # Flutter customer app
│   ├── lib/
│   │   ├── config/      # Supabase bootstrap
│   │   ├── core/        # Theme, routing, shared widgets
│   │   ├── features/    # Feature modules (auth, home, cart, orders, profile)
│   │   ├── services/    # Supabase client, notifications
│   │   └── shared/      # Shared models
│   ├── android/         # Android platform config
│   ├── web/             # Flutter web build assets
│   └── .env.example     # Mobile environment template
│
├── web/                 # Next.js dashboard + POS + admin
│   ├── app/             # App Router pages
│   ├── components/      # UI components and dashboard shell
│   ├── lib/             # Supabase client, API helpers, hooks, types
│   └── .env.example     # Web environment template
│
├── supabase/
│   ├── migrations/      # SQL schema + seed data (applied in order)
│   ├── functions/       # Deno Edge Functions
│   └── config.toml      # Local Supabase project config
│
├── scripts/
│   └── seed-notes.md    # Notes on demo seed data
│
└── docs/
    └── deployment.md    # Production deployment checklist

Prerequisites

Install these before running any app:

Tool Version Used by
Flutter SDK ≥ 3.4 (Dart ≥ 3.4) mobile_app
Node.js ≥ 18 (LTS recommended) web
Supabase CLI Latest supabase
Docker Desktop Latest Local Supabase (supabase start)

Optional (production mobile)

  • Firebase project + google-services.json (Android) / GoogleService-Info.plist (iOS) for push notifications
  • Android Studio or Xcode for device builds

Quick Start (All Apps)

Run these steps once to get the full stack running locally.

1. Start Supabase

From the repository root:

supabase start
supabase db reset
  • supabase start launches local Postgres, Auth, Storage, Studio, and Edge Functions runtime via Docker.
  • supabase db reset applies all migrations in supabase/migrations/ in order and runs seed data.

After start, note the local URLs and keys:

supabase status

Typical local endpoints:

Service URL
API http://127.0.0.1:54321
Studio (DB UI) http://127.0.0.1:54323
Postgres 127.0.0.1:54322

2. Configure environment files

Mobile (mobile_app/.env):

cd mobile_app
cp .env.example .env

Edit .env:

SUPABASE_URL=http://127.0.0.1:54321
SUPABASE_ANON_KEY=<anon key from supabase status>
API_BASE_URL=http://127.0.0.1:54321/functions/v1

Web (web/.env.local):

cd web
cp .env.example .env.local

Edit .env.local:

NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=<anon key from supabase status>
SUPABASE_SERVICE_ROLE_KEY=<service role key — server only, optional for local dev>

Never commit .env, .env.local, or real API keys to git.

3. Run the mobile app

cd mobile_app
flutter pub get
dart run build_runner build --delete-conflicting-outputs
flutter devices
flutter run -d <device-id>

Run on Chrome (web preview):

flutter run -d chrome

4. Run the web app

cd web
npm install
npm run dev

Open in browser:

Route Purpose
http://localhost:3000/signup Customer registration
http://localhost:3000/login Staff / admin login
http://localhost:3000/register Restaurant partner registration
http://localhost:3000/welcome Customer landing after sign-up
http://localhost:3000/dashboard Restaurant dashboard
http://localhost:3000/dashboard/menu Menu management
http://localhost:3000/dashboard/orders Live order queue
http://localhost:3000/dashboard/analytics Revenue charts
http://localhost:3000/dashboard/categories Category management
http://localhost:3000/dashboard/restaurants Restaurant settings
http://localhost:3000/admin Super admin (approve restaurants)
http://localhost:3000/pos POS billing terminal

5. Create demo staff accounts

From web/ (requires SUPABASE_SERVICE_ROLE_KEY in .env or .env.local):

cd web
npm run setup:demo

This creates the Gilgit Branch owner and cashier (see Full Flow — Platform setup) so you can log into the dashboard and POS immediately.

6. Deploy Edge Functions (local or remote)

supabase functions deploy dispatch-notification
supabase functions deploy payment-hook
supabase functions deploy scheduled-analytics
supabase functions deploy email-workflows

For local function testing, functions are available at http://127.0.0.1:54321/functions/v1/<function-name>.


Full Flow

End-to-end walkthrough of how the platform is set up and how each user type moves through the system.

Overview

flowchart LR
  subgraph setup [1. Setup]
    S1[Start Supabase] --> S2[Apply migrations]
    S2 --> S3[Configure .env files]
    S3 --> S4[Run setup:demo]
    S4 --> S5[Start mobile + web]
  end

  subgraph customer [2. Customer]
    C1[Web /signup] --> C2[Mobile login]
    C2 --> C3[Browse & cart]
    C3 --> C4[Checkout COD]
    C4 --> C5[Track order]
  end

  subgraph staff [3. Restaurant staff]
    R1[Web /login] --> R2[Dashboard]
    R2 --> R3[Manage menu]
    R2 --> R4[Advance orders]
  end

  subgraph admin [4. Platform admin]
    A1[Web /admin] --> A2[Approve restaurants]
  end

  setup --> customer
  setup --> staff
  customer --> R4
  staff --> C5
Loading

1. Platform setup flow

Run this once per environment (local Docker or hosted Supabase project).

Local development

Step Command / action Result
1 supabase start Postgres, Auth, Storage, Studio, Edge Functions runtime
2 supabase db reset Applies migrations + seed data (Gilgit Branch, categories, dishes)
3 Copy .env files Mobile and web point at http://127.0.0.1:54321
4 cd web && npm run setup:demo Creates demo owner + cashier accounts (see below)
5 flutter run + npm run dev Mobile and web apps running

Remote Supabase (production / shared dev)

Step Command / action Result
1 Create project at supabase.com Hosted Postgres + Auth
2 supabase login Authenticate CLI
3 supabase link --project-ref <ref> Link local repo to remote project
4 supabase db push Apply all migrations to remote
5 Set web/.env and mobile_app/.env with remote URL + anon key Clients connect to hosted backend
6 cd web && npm run setup:demo Demo staff accounts + Gilgit Branch on remote
7 Deploy Edge Functions + set secrets Notifications, payments, analytics

Demo accounts (created by npm run setup:demo):

Role Email Password Access
Restaurant owner owner@gilgit.gb GilgitOwner2026! Dashboard, menu, orders, POS
Cashier cashier@gilgit.gb GilgitCashier2026! POS, limited dashboard

Requires SUPABASE_SERVICE_ROLE_KEY in web/.env or web/.env.local.


2. Customer flow (order food)

Customers sign up on the web, then order on the mobile app with the same credentials.

sequenceDiagram
  participant W as Web (signup)
  participant M as Mobile App
  participant S as Supabase

  W->>S: POST /signup — email, password, full_name, phone
  S->>S: Auth user + profiles row (role: customer)
  W->>W: Redirect to /welcome

  M->>S: Sign in (email/password or Google OAuth)
  M->>S: Fetch approved restaurants, categories, food_items
  M->>M: Add items to cart (in-memory, single restaurant)
  M->>S: Create address (if none saved)
  M->>S: Insert orders + order_items + payments (COD, pending)
  M->>M: /success → /tracking/:id
  S-->>M: Realtime order status updates
Loading

Step-by-step

  1. Create account (web) — Open http://localhost:3000/signup, fill name, email, phone, password. On success you land on /welcome, which explains that ordering happens in the mobile app.
  2. Sign in (mobile) — Use the same email and password on /login (or Google OAuth). Auth trigger + app upsert ensure a profiles row exists.
  3. Browse (mobile) — Home shows featured restaurants and categories. Tap a restaurant → /restaurant/:id → dish detail → add to cart.
  4. Cart (mobile)/cart shows line items, delivery fee, 5% tax, total. Requires sign-in to proceed.
  5. Checkout (mobile)/checkout collects delivery address (saved or new), payment method (Cash on Delivery only), order summary.
  6. Place order (mobile) — Inserts into orders (status pending), order_items, and payments (method cod, status pending). Cart clears; redirect to /success.
  7. Track (mobile)/tracking/:id shows live status. Order history at /orders.

Web routes for customers

Route Purpose
/signup Customer registration
/welcome Post-signup landing (directs to mobile app)
/login Shared login — customers redirect here too, then to /welcome

Customers cannot access /dashboard, /admin, or /pos — middleware redirects them to /welcome.


3. Restaurant staff flow

Staff and owners use the web dashboard and POS. They never order through the web customer signup.

flowchart TD
  A[Staff visits /login] --> B{Valid credentials?}
  B -->|No| A
  B -->|Yes| C{profiles.role}
  C -->|restaurant_owner| D[/dashboard]
  C -->|restaurant_staff / cashier| D
  C -->|admin / super_admin| E[/admin or /dashboard]
  C -->|customer| F[/welcome — wrong portal]

  D --> G[useWorkspace loads restaurant]
  G --> H[Orders — realtime queue]
  G --> I[Menu — CRUD food_items]
  G --> J[Categories / Settings / Analytics]
  G --> K[/pos — walk-in sales]
Loading

Step-by-step

  1. Get access — Run npm run setup:demo for demo accounts, or have an admin set profiles.role to restaurant_owner / restaurant_staff / cashier and link restaurants.owner_id or restaurant_staff.
  2. Loginhttp://localhost:3000/login with staff credentials. resolvePostLoginPath() sends staff to /dashboard, admins to /admin.
  3. WorkspaceuseWorkspace resolves restaurant: owned → staff assignment → admin fallback (first approved restaurant).
  4. Manage orders/dashboard/orders lists orders for the restaurant. Realtime subscription refreshes when mobile customers place orders. Click Advance to move status: pendingconfirmedpreparingout_for_deliverydelivered.
  5. Manage menu/dashboard/menu and /dashboard/categories read/write food_items and categories scoped by restaurant_id (RLS enforced).
  6. Analytics/dashboard/analytics and /dashboard/revenue show metrics from analytics and order data.

Restaurant partner registration (/register) creates a customer account first; an admin must upgrade the role before dashboard access.


4. Platform admin flow

Admins and super admins manage the whole platform from /admin.

  1. Login — Same /login page; role admin or super_admin redirects to /admin.
  2. Platform stats — Total restaurants, users, revenue, orders.
  3. Approve restaurants — Pending restaurants (is_approved = false) from partner registration or manual inserts. Approve sets is_approved = true — restaurant appears in the mobile app.
  4. Reject — Removes or marks rejected listings.
  5. Platform orders — Recent orders across all restaurants.

To create a super admin locally: Supabase Studio → Authentication → create user → Table Editor → profiles → set role = super_admin.


5. POS flow (walk-in sales)

Cashiers and owners record in-store sales without the mobile app.

  1. Open http://localhost:3000/pos (requires staff role).
  2. Select items from the restaurant menu (food_items).
  3. Complete sale — createPosInvoice() inserts into pos_invoices.
  4. Invoice rolls into /dashboard/analytics and /dashboard/revenue.

6. End-to-end test (full order lifecycle)

Use this checklist to verify the entire stack works together:

# Actor Action Expected result
1 Dev supabase db reset + npm run setup:demo Gilgit Branch + demo staff exist
2 Customer Sign up at /signup Lands on /welcome
3 Customer Log in on mobile with same email Home shows Gilgit Branch
4 Staff Log in at /login as owner@gilgit.gb Dashboard loads Gilgit Branch
5 Staff Open /dashboard/orders Empty or existing queue visible
6 Customer Add Chapshuro (or any dish) → checkout → Place Order /success with order number
7 Staff Orders page refreshes (realtime) New order appears as pending
8 Staff Click Advance through statuses Status moves toward delivered
9 Customer Open /tracking/:id on mobile Status matches dashboard
10 Staff Run POS sale at /pos Invoice in analytics

Order status pipeline

pending → confirmed → preparing → out_for_delivery → delivered
                    ↘ cancelled / refunded

Data written on mobile checkout

Table Fields
orders user_id, restaurant_id, address_id, totals, status: pending
order_items food_item_id, name_snapshot, unit_price, quantity
payments method: cod, status: pending, amount

Supabase Backend

Migrations

Migrations run in numeric order. Do not rename applied migration files in production.

File What it does
0001_initial_schema.sql Full schema: tables, enums, indexes, RLS policies, storage buckets, realtime publication
0002_seed_demo_data.sql Demo restaurant "Gilgit Branch", GB dishes, sample orders, analytics
0003_restaurant_featured.sql Adds is_featured column; marks Gilgit Branch as featured
0004_auth_profile_trigger.sql Auto-creates profiles row when a user signs up via Auth

Create a new migration:

supabase migration new <descriptive_name>
# Edit the new file in supabase/migrations/
supabase db reset   # local: re-apply all migrations

Push to remote Supabase project:

supabase link --project-ref <your-project-ref>
supabase db push

You can also run migration helpers from web/:

cd web
npm run supabase:start
npm run supabase:reset
npm run supabase:new -- <name>
npm run supabase:push

Database Schema (tables)

Table Purpose
profiles User profile linked to auth.users; stores role, points, contact info
restaurants Restaurant listings (owner, location, fees, approval status)
restaurant_staff Staff/cashier assignments per restaurant
categories Food categories (Traditional, Fast Food, etc.)
food_items Menu items per restaurant
carts / cart_items Per-user shopping cart
addresses Delivery addresses
orders / order_items Placed orders with status tracking
payments Payment records (COD, card, JazzCash, EasyPaisa, Stripe)
favorites Saved restaurants or dishes
reviews Customer reviews with optional photos
notifications In-app notification inbox
pos_invoices Walk-in POS sales
analytics Daily per-restaurant metrics

Enums

  • user_role: customer, restaurant_owner, restaurant_staff, cashier, admin, super_admin
  • order_status: pendingconfirmedpreparingout_for_deliverydelivered (or cancelled / refunded)
  • payment_method: cod, card, stripe, jazzcash, easypaisa
  • payment_status: pending, paid, failed, refunded

Row Level Security (RLS)

RLS is enabled on all public tables. Key rules:

  • Customers can only read/write their own carts, addresses, orders, and favorites.
  • Restaurant staff (owner, staff, cashier) access data for restaurants they own or are assigned to via staff_restaurant_ids().
  • Admins / super_admins bypass restrictions via is_admin().
  • Public read is allowed for approved restaurants, active categories, and available menu items.

Helper functions (security definer):

  • is_admin() — true if current user has admin or super_admin role
  • staff_restaurant_ids() — restaurant IDs the current user can manage

Storage Buckets

Created in 0001_initial_schema.sql:

Bucket Public Purpose
food-images Yes Dish photos
restaurant-images Yes Restaurant logo/cover
user-avatars Yes Profile pictures
review-photos No Review attachments (owner/admin read)

Realtime

These tables broadcast changes via Supabase Realtime (used by web order dashboard):

  • orders
  • notifications
  • analytics
  • pos_invoices

Auth profile trigger

When a user signs up (email or OAuth), migration 0004 runs handle_new_user() to insert a profiles row with role customer. Migration 0006 adds an INSERT RLS policy so the mobile app can optionally upsert the same row when a session exists (PostgREST upsert requires INSERT privilege).

Edge Functions

Function Method Purpose
dispatch-notification POST Insert in-app notification (user_id, title, body, type, data)
payment-hook POST Upsert payment record from external payment provider webhook
scheduled-analytics GET/POST Aggregate today's orders per restaurant into analytics table
email-workflows POST Queue email workflow and log a notification (email, workflow, payload)

All Edge Functions require SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY as Deno environment secrets (set in Supabase dashboard → Edge Functions → Secrets).

Example — dispatch a notification:

curl -X POST http://127.0.0.1:54321/functions/v1/dispatch-notification \
  -H "Authorization: Bearer <service-role-key>" \
  -H "Content-Type: application/json" \
  -d '{"user_id":"<uuid>","title":"Order update","body":"Your order is preparing"}'

Local Supabase config

supabase/config.toml sets:

  • site_url = "http://localhost:3000" (web app)
  • additional_redirect_urls = ["gbfoodhub://auth"] (mobile OAuth deep link)

Mobile App (Flutter)

Tech stack

Package Purpose
flutter_riverpod / riverpod_annotation State management
go_router Declarative routing
supabase_flutter Auth + database
flutter_dotenv Environment config
dio HTTP client (Edge Functions / future APIs)
firebase_messaging + flutter_local_notifications Push notifications
flutter_secure_storage Secure token storage
cached_network_image, shimmer Image loading + skeleton UI
freezed / json_serializable Code generation for models

Architecture (clean architecture per feature)

lib/features/<feature>/
├── data/           # Supabase repositories (API calls)
├── domain/         # Repository interfaces, entities
└── presentation/   # Pages, Riverpod providers

Features:

Feature Key files Supabase tables
auth supabase_auth_repository.dart, auth_pages.dart auth.users, profiles
home catalog_repository.dart, home_page.dart categories, restaurants, food_items
cart cart_notifier.dart, cart_providers.dart In-memory + optional carts
orders supabase_order_repository.dart, order_pages.dart orders, order_items, payments
profile address_repository.dart, profile_pages.dart profiles, addresses

App routes

Defined in mobile_app/lib/core/routing/app_router.dart:

Route Screen
/splash, /onboarding App intro
/login, /register, /forgot-password, /otp Authentication
/ Home (featured restaurants, categories)
/search, /restaurants Discovery
/restaurant/:id, /food/:id Detail pages
/cart, /checkout, /success Ordering flow
/orders, /tracking/:id Order history & live tracking
/favorites, /notifications Saved items & alerts
/profile, /edit-profile, /change-password Account
/addresses, /settings, /reviews, /write-review Profile extras

Bootstrap flow

  1. main.dart loads .env via flutter_dotenv
  2. bootstrap.dart calls Supabase.initialize() with URL + anon key
  3. ProviderScope wraps the app; GoRouter handles navigation
  4. Theme from core/theme/app_theme.dart (light + dark)

Code generation

After changing Riverpod/Freezed/JSON models:

cd mobile_app
dart run build_runner build --delete-conflicting-outputs

Running on different targets

# List devices
flutter devices

# Android emulator / physical device
flutter run -d <android-device-id>

# iOS simulator (macOS only)
flutter run -d <ios-device-id>

# Chrome (Flutter web)
flutter run -d chrome

# Release builds
flutter build apk --release
flutter build appbundle --release   # Play Store
flutter build ipa --release         # App Store (macOS + Xcode)

Push notifications (production)

NotificationService uses Firebase Cloud Messaging + local notifications for foreground messages. For production:

  1. Create a Firebase project
  2. Add google-services.json to mobile_app/android/app/
  3. Add iOS Firebase config and enable push capabilities in Xcode
  4. Set FCM_SERVER_KEY or provider credentials for the dispatch-notification Edge Function

Web App (Next.js)

Tech stack

Package Purpose
Next.js 15 (App Router) Framework
React 19 UI
@supabase/ssr Server + browser Supabase clients with cookie auth
Tailwind CSS Styling
Recharts Analytics charts
Lucide React Icons

App structure

web/app/
├── page.tsx                    # Redirects to /dashboard
├── (auth)/
│   ├── login/                  # Staff / admin login
│   ├── signup/                 # Customer registration
│   ├── register/               # Restaurant partner registration
│   └── forgot-password/        # Password reset
├── welcome/                    # Customer landing after sign-up
├── auth/callback/              # OAuth redirect handler
├── dashboard/                  # Restaurant owner/staff area
│   ├── page.tsx                # Overview stats
│   ├── orders/                 # Live order management
│   ├── menu/                   # CRUD menu items
│   ├── categories/             # Category management
│   ├── restaurants/            # Restaurant profile
│   ├── analytics/              # Charts
│   ├── revenue/                # Revenue breakdown
│   └── settings/               # Account settings
├── admin/                      # Super admin panel
└── pos/                        # Point-of-sale terminal

Key libraries

Path Purpose
lib/supabase.ts Browser Supabase client
middleware.ts Auth guard for /dashboard, /admin, /pos
lib/hooks/use-workspace.ts Loads current user profile + assigned restaurant
lib/api/menu.ts Menu CRUD
lib/api/orders.ts Order queries and status updates
lib/api/restaurants.ts Restaurant management + admin approval
lib/api/analytics.ts Analytics data
lib/api/pos.ts POS invoice creation
lib/realtime.ts Subscribe to order changes per restaurant
lib/types.ts Shared TypeScript types matching DB schema

Authentication flow

  1. User logs in at /login with email + password (login-form.tsx)
  2. resolvePostLoginPath() routes by role: admin → /admin, staff → /dashboard, customer → /welcome
  3. Supabase session stored in cookies via @supabase/ssr
  4. middleware.ts guards /dashboard, /admin, /pos — redirects unauthenticated users to /login; customers to /welcome
  5. Admin routes (/admin) require profiles.role of admin or super_admin
  6. useWorkspace resolves the restaurant context: owned → staff assignment → admin fallback

See Full Flow for complete customer, staff, admin, and POS journeys.

Workspace resolution

useWorkspace determines which restaurant the dashboard operates on:

  1. Restaurant where owner_id = current user
  2. Else, restaurant from restaurant_staff assignment
  3. Else (admin only), first approved restaurant as fallback

Realtime orders

The orders dashboard uses subscribeToRestaurantOrders() to listen for orders table changes filtered by restaurant_id. The UI refreshes automatically when order status changes from the mobile app or POS.

NPM scripts

npm run dev          # Start dev server (port 3000)
npm run build        # Production build
npm run start        # Run production server
npm run lint         # ESLint
npm run typecheck    # TypeScript check
npm run setup:demo   # Create demo owner + cashier accounts

# Supabase helpers (run from web/)
npm run supabase:start
npm run supabase:stop
npm run supabase:status
npm run supabase:reset
npm run supabase:push
npm run supabase:pull
npm run supabase:new

Scripts

The scripts/ folder contains operational helpers and notes.

scripts/setup-demo-owner.mjs

Creates demo restaurant owner and cashier accounts in your Supabase project (local or remote):

cd web
npm run setup:demo

See Full Flow — Platform setup for credentials and what it creates.

scripts/seed-notes.md

Documents how demo seed data works:

  • Migration 0002_seed_demo_data.sql inserts a Gilgit Branch restaurant with traditional GB dishes (Chapshuro, Yak Skewers, Dowdo Soup, etc.), sample orders, and 7 days of analytics.
  • Seed data depends on an existing super_admin profile. In production, create users through Supabase Auth first, then update seeded owner_id / user_id references to match real auth user UUIDs.
  • Categories, food items, orders, and analytics are only inserted if they do not already exist (idempotent).

Environment Variables

Mobile (mobile_app/.env)

Variable Required Description
SUPABASE_URL Yes Supabase project URL (local: http://127.0.0.1:54321)
SUPABASE_ANON_KEY Yes Public anon key (safe in client)
API_BASE_URL Yes Edge Functions base URL (<SUPABASE_URL>/functions/v1)

Web (web/.env.local)

Variable Required Description
NEXT_PUBLIC_SUPABASE_URL Yes Supabase project URL (exposed to browser)
NEXT_PUBLIC_SUPABASE_ANON_KEY Yes Public anon key
SUPABASE_SERVICE_ROLE_KEY Server only Bypasses RLS — never prefix with NEXT_PUBLIC_

Edge Functions (Supabase dashboard secrets)

Secret Required Description
SUPABASE_URL Yes Auto-injected in hosted Supabase
SUPABASE_SERVICE_ROLE_KEY Yes For server-side DB writes
FCM_SERVER_KEY Production Firebase push dispatch (optional locally)

Authentication & User Roles

Sign-up flows

Client Route Method Profile creation
Web (customer) /signup Email/password, Google OAuth Auth trigger → role customer/welcome
Web (partner) /register Email/password, Google OAuth Auth trigger → role customer (admin upgrades later)
Mobile /register Email/password, Google OAuth Auth trigger + app upsert → role customer
Web (staff) /login Email/password only Existing staff accounts from setup or admin

Roles and access

Role Mobile app Web dashboard Admin panel POS
customer Full ordering No access* No No
restaurant_owner Ordering Full dashboard for owned restaurant No Yes
restaurant_staff Ordering Dashboard for assigned restaurant No Yes
cashier Ordering Limited dashboard No Yes
admin Ordering Dashboard (fallback restaurant) Yes Yes
super_admin Ordering Dashboard (fallback restaurant) Yes Yes

*Middleware redirects customers away from /dashboard, /admin, and /pos to /welcome. Staff areas require authentication.

Google OAuth setup

  1. Open Supabase dashboard → AuthenticationProviders → enable Google
  2. Add OAuth redirect URLs:
    • http://localhost:3000 (local web)
    • Your production web URL
    • gbfoodhub://auth (mobile deep link — configure in Android/iOS)
  3. For mobile OAuth, set redirectTo: 'gbfoodhub://auth' in signInWithGoogle()

Creating admin / restaurant owner users

Local dev (Supabase Studio):

  1. Open http://127.0.0.1:54323
  2. Create user in AuthenticationUsers
  3. In Table Editorprofiles, set role to super_admin or restaurant_owner
  4. For owners, insert a row in restaurants with owner_id = user UUID and is_approved = true

Production:

  1. Sign up normally, then update profiles.role via SQL or Studio
  2. Link restaurant: insert into restaurants (owner_id, name, slug, ...) values (...)

How the Apps Work Together

For step-by-step walkthroughs, see Full Flow.

Customer orders food (mobile → dashboard)

sequenceDiagram
  participant C as Mobile App
  participant S as Supabase
  participant W as Web Dashboard

  C->>S: Sign in (Auth)
  C->>S: Browse restaurants / food_items (RLS: public approved)
  C->>S: Add to cart (local state)
  C->>S: Place order → insert orders + order_items
  S-->>W: Realtime broadcast on orders table
  W->>S: Staff updates order status
  S-->>C: Customer sees updated status in /tracking/:id
Loading

Restaurant manages menu (web)

  1. Owner logs in at /login
  2. useWorkspace loads their restaurant
  3. Menu page reads/writes food_items filtered by restaurant_id
  4. RLS ensures staff can only edit their assigned restaurant's items

POS walk-in sale (web)

  1. Cashier opens /pos
  2. Adds items to cart from food_items
  3. createPosInvoice() inserts into pos_invoices
  4. Invoice appears in analytics/revenue reports

Admin approves new restaurant

  1. Super admin opens /admin
  2. fetchPendingRestaurants() loads restaurants where is_approved = false
  3. Approve sets is_approved = true — restaurant becomes visible in mobile app

Common Development Tasks

Reset local database to clean state

supabase db reset

Add a new menu category

  1. Insert into categories via web Categories page or SQL
  2. Mobile app reads active categories automatically via CatalogRepository.fetchCategories()

Test order flow end-to-end

Follow the End-to-end test checklist in Full Flow.

Quick version:

  1. Run npm run setup:demo and create a customer at /signup
  2. Log into web dashboard as owner@gilgit.gb
  3. Place order on mobile → watch it appear on /dashboard/orders
  4. Update status on web → verify tracking page on mobile

Add a new Edge Function

supabase functions new my-function
# Edit supabase/functions/my-function/index.ts
supabase functions serve my-function   # local test
supabase functions deploy my-function  # remote

Update TypeScript types after schema change

  1. Apply migration
  2. Update web/lib/types.ts to match new columns/enums
  3. Update Flutter models in mobile_app/lib/shared/models/

Lint and type-check web

cd web
npm run lint
npm run typecheck

Analyze Flutter code

cd mobile_app
flutter analyze

Design System

UI follows warm orange accents, soft white cards, GB-local food imagery, rounded mobile surfaces, and compact dashboard cards.

App Theme location
Mobile mobile_app/lib/core/theme/app_theme.dart
Web web/app/globals.css, web/tailwind.config.ts

Brand tokens in web CSS use names like brand-burnt, brand-cocoa, brand-sand.


Deployment

See docs/deployment.md for the production checklist. Summary:

Supabase (production)

  1. Create project at supabase.com
  2. Link CLI: supabase link --project-ref <ref>
  3. Push migrations: supabase db push
  4. Verify storage buckets exist (created by migration, or create manually in dashboard)
  5. Deploy all Edge Functions and set secrets
  6. Configure Auth redirect URLs for production domains

Mobile (production)

  1. Set production SUPABASE_URL and SUPABASE_ANON_KEY in mobile_app/.env
  2. Configure Firebase for push notifications
  3. Build release artifacts:
flutter build appbundle --release   # Google Play
flutter build ipa --release         # App Store

Web (production)

Deploy to Vercel, Netlify, or any Node host:

cd web
npm ci
npm run build
npm start

Set environment variables in the hosting dashboard. Add your production URL to Supabase Auth redirect allowlist.


Troubleshooting

Issue Solution
supabase start fails Ensure Docker Desktop is running
Mobile can't connect to Supabase Check SUPABASE_URL in .env; use http://127.0.0.1:54321 for local (not localhost on some Android emulators — use 10.0.2.2:54321 for Android emulator)
429 Too Many Requests on signup Supabase rate-limits repeated sign-ups; wait 1 minute or use a new email
Web dashboard shows no restaurant Ensure user has restaurant_owner role + restaurants row, or restaurant_staff assignment
Orders not updating live on web Confirm Realtime is enabled; check subscribeToRestaurantOrders subscription
RLS permission denied Verify user role and restaurant assignment; test query in Studio with user's JWT
build_runner conflicts Run dart run build_runner build --delete-conflicting-outputs
Android emulator Supabase URL Use http://10.0.2.2:54321 instead of 127.0.0.1

Useful commands

# Supabase logs
supabase functions logs dispatch-notification

# Flutter verbose run
flutter run -v

# Web production build test
cd web && npm run build && npm start

License

Private project — GB FoodHub, Gilgit Baltistan.

login creadential

Demo credentials (after running setup script): Owner: owner@gilgit.gb / GilgitOwner2026! Cashier: cashier@gilgit.gb / GilgitCashier2026!

// update Demo accounts are ready on your remote Supabase project.

Login at http://localhost:3000/login

Role Email Password Owner owner@gilgit.gb GilgitOwner2026! Cashier cashier@gilgit.gb GilgitCashier2026!

new Repo mein default admin login nahi hai — sirf owner/cashier demo accounts hain.

Demo logins (web /login) Role Email Password Restaurant owner owner@gilgit.gb GilgitOwner2026! Cashier cashier@gilgit.gb GilgitCashier2026! Login: http://localhost:3000/login Owner → /dashboard (menu, orders, banners UI, etc.)

Agar ye accounts nahi chalte, pehle ye chalao:

cd web npm run setup:demo Admin / super_admin Koi ready admin@... password seed nahi hai. Khud banana padta hai:

Supabase Dashboard → apna project → Authentication → Users → Add user Email + password set karo (jo chaho) Table Editor → profiles → us user ki row mein role = super_admin (ya admin) Phir /login pe wohi email/password se login → /admin / banners manage Note: Promo banners RLS sirf admin / super_admin ko write allow karti hai. Owner se banner save fail ho sakta hai — banners ke liye super_admin role zaroori hai.

new update Step 1 — SQL run karo Supabase Dashboard → SQL Editor → scripts/create-demo-auth-accounts.sql ka pura content paste → Run

Step 2 — Login credentials Role Email Password Opens Super Admin superadmin@gilgit.gb GilgitSuperAdmin2026! /admin Admin admin@gilgit.gb GilgitAdmin2026! /admin Owner owner@gilgit.gb GilgitOwner2026! /dashboard Cashier cashier@gilgit.gb GilgitCashier2026! /pos Login: http://localhost:3000/login Role dropdown se Super Admin / Admin select karo → email/password auto-fill → Login.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages