Skip to main content

Architecture & Tech stack

Tech stack

LayerTechnology
FrameworkReact 18 + TypeScript 4.9
BuildCreate React App 5 + CRACO 7
Routingreact-router-dom v6 (BrowserRouter)
StylingTailwind CSS 3 + CSS variables (design tokens)
HTTPAxios 1.3
Formsreact-hook-form 7
Toastreact-hot-toast
Iconslucide-react
CAPTCHA@marsidev/react-turnstile (Cloudflare Turnstile)
QR Codeqrcode
Monorepo@kioskgaming/ui, @kioskgaming/page-loading

Not included: Redux, Zustand, React Query, Capacitor.


Directory structure

kioskgaming_agent/
├── src/
│ ├── index.tsx # Entry point, Service Worker registration
│ ├── App.tsx # Router + AuthProvider
│ ├── index.css # Tailwind + CSS variables
│ ├── config/env.ts # Centralized environment variables
│ ├── constants/index.ts # API URL, storage keys, custom events
│ ├── types/index.ts # TypeScript interfaces
│ ├── services/api.ts # HTTP client + all API functions
│ ├── hooks/ # useAuth, ledger hooks, zerox methods
│ ├── pages/ # Route pages
│ ├── components/
│ │ ├── auth/ # Login, forgot password, ProtectedRoute
│ │ ├── layout/ # AppLayout, AgentPageLayout
│ │ ├── credits/ # Buy credits, distribute, withdraw from shop
│ │ ├── dashboard/ # AgentHierarchyMiniTree
│ │ ├── finance/ # Withdrawal limits panel
│ │ ├── players/ # AgentPlayerDetailPanel
│ │ ├── shops/ # ShopGovernanceModal, status badge
│ │ └── ui/ # PortalEmptyState
│ └── utils/ # format, ledger, sanitize helpers
├── public/
│ ├── _redirects # Netlify / Cloudflare Pages
│ ├── .htaccess # Apache SPA fallback
│ └── web.config # IIS / Azure Static Web Apps
├── craco.config.js
├── tailwind.config.js
└── package.json

Entry points

FileRole
src/index.tsxMount React, register Service Worker (production only)
src/App.tsxDefine routes, wrap AuthProvider
src/services/api.tsBackend integration layer (~834 lines)

State management

No Redux/Zustand. State architecture:

PatternLocationPurpose
React Contexthooks/useAuth.tsxAuth state (user, token, login/logout)
Local useStateEach page/componentUI state, form, modal
Custom hooksuseAgentTransactions, useAgentOnlineBalanceLedger, useSupportedZeroxMethodsData fetching with reload
localStorageAuth tokens, user data, zerox methods cache (24h TTL)
Custom Eventswindow.dispatchEventCross-component sync

Custom events

EventConstantWhen dispatched
agent-auth-token-changedAGENT_AUTH_TOKEN_CHANGED_EVENTLogin / logout
auth:unauthorizedAxios interceptor receives 401

Storage keys

KeyContent
agent_auth_tokenAgent bearer token
agent_user_dataAgent profile (JSON)

Authentication flow

sequenceDiagram
participant U as Agent user
participant A as Agent Portal
participant B as Backend

U->>A: Enter username/email + password
A->>B: POST /agent-auth/login
alt OTP required (2FA)
B-->>A: needsOtp + pendingToken
U->>A: Enter OTP
A->>B: POST /agent-auth/verify-otp
end
B-->>A: accessToken + agent profile
A->>A: Save token to localStorage
  • Header: Authorization: Bearer {token}
  • 401 → dispatch auth:unauthorized → auto logout
  • ProtectedRoute redirects to /login if not authenticated

Environment variables

VariableRequiredDescriptionDefault
REACT_APP_API_BASE_URLYesBackend API base URLhttp://localhost:3001/api
REACT_APP_TURNSTILE_ENABLEDNoEnable Cloudflare Turnstilefalse
REACT_APP_TURNSTILE_SITE_KEYWhen Turnstile enabledSite key''
REACT_APP_APP_NAMENoDisplay app nameKiosk Gaming — Agent
REACT_APP_CLIENT_TELEGRAM_SUPPORT_URLNoTelegram support link
REACT_APP_CLIENT_ANDROID_APK_URLNoAndroid APK download link
REACT_APP_CLIENT_IOS_VIDEO_URLNoiOS setup video
PORTNoDev server port3003
warning

Backend must set AGENT_FRONTEND_URL to the app origin so payment redirects to /payment/success, /payment/cancelled, /payment/error.


npm scripts

ScriptDescription
npm startDev server port 3003 (CRACO)
npm run buildProduction build → build/ directory
npm testRun tests (CRACO)

Special configuration

CRACO + Monorepo UI

craco.config.js imports configureKioskgamingUi from ../packages/ui so webpack resolves the shared UI package.

Capacitor

Not included — this is a pure web app with no native wrapper.

Service Worker (PWA)

  • public/sw.js + serviceWorkerRegistration.ts
  • Registers only when NODE_ENV === 'production'

Deploy (Static SPA)

FilePlatform
public/_redirectsNetlify, Cloudflare Pages — /* → /index.html 200
public/.htaccessApache — rewrite non-file routes → index.html
public/web.configIIS / Azure Static Web Apps
cd kioskgaming_agent
npm install
npm run build
# Deploy build/ directory to static host

Shared UI package

Shared components from @kioskgaming/ui:

  • PortalCreditTransactionsLedger, PortalUsdWalletLedgerTable
  • CreditTransactionDetailModal, UsdWalletTransactionDetailModal
  • WithdrawOtpStep, WithdrawBlockedAlert
  • FormField, Modal, Button, Input, Select, Textarea
  • PlayerFraudIndicatorsPanel, SupportDownloadRail

Overview diagram

flowchart TB
subgraph Client["kioskgaming_agent"]
Index[index.tsx] --> App[App.tsx]
App --> Auth[AuthProvider]
Auth --> Router[React Router]
Router --> Public["/login, /forgot-password"]
Router --> Protected["ProtectedRoute + Pages"]
Protected --> Layout[AppLayout]
Layout --> API[services/api.ts]
end

subgraph Backend["kioskgaming_backend"]
API -->|Bearer token| AgentAPI["/agent/*"]
API --> AuthAPI["/agent-auth/*"]
API --> PaymentAPI["/payment/*"]
end

subgraph Storage["Browser"]
Auth --> LS["localStorage: agent_auth_token"]
end