Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Book-Bite (Partner Portal) — Architecture and Operations

Book-Bite is the HungryHub Partner Portal — the web and mobile app used by restaurant partners to manage their bookings, packages, menus, vouchers, allotments, analytics, and account settings.


Tech stack

CategoryTechnology
FrameworkVue 3.5 + Vite 5
UI libraryVuetify 3.8 (Material Design)
State managementPinia 2
RouterVue Router 4
HTTP clientAxios 1.15 (camelCase ↔ snake_case via Humps)
MobileCapacitor 6 (iOS + Android)
Error trackingRollbar 2.26
Feature flagsGrowthBook 1.4
AnalyticsGoogle Analytics 4, Microsoft Clarity, MongoDB Charts
ValidationValibot 1.0
i18n4 languages: English, Thai, Chinese, Malay
TestingCypress 13 (component + e2e), Playwright 1.56 (e2e)
CIGitHub Actions + Netlify

What partners can do

AreaKey actions
BookingsView, create, edit, approve/reject, send SMS, send review links, check inventory
PackagesCreate/edit AYCE, Party Pack, Xperience, Hungry@Home packages; pricing rules; add-ons
AllotmentsManage daily/monthly allotments; view edit history
MenusMenu v1 & v2 management; gallery photos; QR codes; print
VouchersCreate/edit vouchers; view usage history
AnalyticsDashboard KPIs; performance review; benchmark reports; ranking analytics
ReviewsView and respond to guest reviews
AccountUser/staff management; billing; store setup; partner registration
MarketingCampaign management

Architecture

Browser / iOS / Android
        │
        ▼
  Vue 3 SPA (Vite build → dist/)
        │
        ├── Pinia stores       (client-side state)
        ├── src/api/           (26 domain API modules)
        └── Axios (request.util.js)
                │
                ├── Partner API:      madison.hungryhub.com/api/partner/v1/
                ├── Restaurant API:   .../api/v5/restaurants/
                ├── Price Engine:     APP_BASE_API_PRICE_ENGINE_URL
                ├── HH Menu:          menu.hungryhub.com
                └── Chrome service:   APP_CHROME_SERVICE (PDF/print)

Authentication: Bearer token stored in localStorage, auto-injected via Axios interceptor.

Mobile apps (iOS/Android) wrap the compiled Vue app via Capacitor — bundle ID com.hungryhub.partnerapp.


Repository structure

src/
  api/          26 domain API modules (booking, package, voucher, menu, ...)
  stores/       26 Pinia stores (one per domain)
  pages/        22 page sections
  components/   Feature + base UI components
  router/       13 route files (one per domain)
  composables/  Vue 3 composition hooks
  locales/      i18n translations (en, th, zh, ms)
  utils/        request.util.js, storage.util.js, ...
  plugins/      Vue plugins
android/        Android native project (Capacitor)
ios/            iOS native project (Capacitor)
tests/          Playwright e2e tests
cypress/        Cypress e2e + component tests

Deployment

Platform: Netlify

EnvironmentTriggerURL
ProductionPush to mainpartners.hungryhub.com
Staging previewPull requestAuto-generated Netlify preview URL

Build command: npm run build → outputs to dist/.

netlify.toml configuration:

  • SPA redirect: all routes → /index.html (200)
  • Assets cached for 1 year (/assets/*)
  • index.html never cached (always fresh)

CI/CD workflows

WorkflowTriggerPurpose
playwright.ymlPRE2e tests against Netlify preview
pr_agent.ymlPRAI-powered PR review
typos.ymlPRSpell check on changed files
clean-branches.ymlDailyDelete branches older than 60 days

Runners: self-hosted arc-runner-set-book-bite for heavy tests; ubuntu-latest for lightweight jobs.


Analytics

ToolPurposeProd property
Google Analytics 4Traffic, sessions, conversion eventsAccount 66127738 / Property 245030152
Microsoft ClaritySession recordings and heatmapsConfigured via APP_MICROSOFT_CLARITY_ID
MongoDB ChartsCustom business KPIs (booking volume, revenue)Embedded in the Analytics section of the portal

GA4 is initialised client-side via APP_GOOGLE_ANALYTICS_ID. Only the production build uses the real property; set a dev/staging measurement ID in non-prod environments to keep data clean.


Environment variables

VariablePurpose
APP_BASE_API_URLPartner API base URL
APP_BASE_API_RESTAURANT_URLRestaurant data API
APP_BASE_API_PRICE_ENGINE_URLDynamic pricing engine
APP_GOOGLE_API_KEYGoogle Maps / geocoding
APP_GOOGLE_ANALYTICS_IDGA4 measurement ID (prod: property 245030152, account 66127738)
APP_ROLLBAR_TOKENError reporting token
APP_MICROSOFT_CLARITY_IDClarity session analytics
APP_GROWTHBOOK_API_HOSTGrowthBook feature flag host
APP_GROWTHBOOK_CLIENT_KEYGrowthBook SDK key
APP_FIREBASE_*Firebase push notifications (4 vars)
APP_NETCORE_*NetCore email/SMS (4 vars)
APP_NODE_ENVdevelopment or production
APP_DEFAULT_LOCALEDefault language (en)

Mobile apps

Both iOS and Android apps wrap the compiled Vue app via Capacitor.

  • Bundle ID: com.hungryhub.partnerapp
  • App name: partner-portal
  • CapacitorCookies plugin enabled for session management
  • Updates require a new App Store / Play Store release when native code changes; web-only changes deploy via Netlify without a new app release

Testing

# Component tests (Cypress)
npm run test:unit        # interactive
npm run test:unit:ci     # headless

# E2E tests (Cypress)
npm run test:e2e         # interactive
npm run test:e2e:ci      # headless

# E2E tests (Playwright)
npm run test:e2e:playwright
npm run test:e2e:playwright:ui   # with UI mode

# Coverage
npm run coverage         # Playwright + lcov report

Playwright tests cover: login, booking list, create booking, edit booking, inventory.


Local development

git clone git@github.com:hungryhub-team/book-bite.git
cd book-bite
npm install
npm run dev              # starts on port 3001

Copy .env.example to .env and fill in API URLs and service keys.