Design philosophy
The architecture is built around three core principles:Domain-driven
Features are grouped by domain (menu, payments, notifications) rather than technical layer
Low coupling
Each module is self-contained with minimal dependencies on other parts of the system
High cohesion
Related functionality lives together, making it easy to locate and modify features
Directory structure
All application code lives in thesrc/ directory:
The directory structure reflects the application’s domain model, making it intuitive to navigate even for developers new to the codebase.
Layer breakdown
Core layer (lib/core/)
Contains app-wide singletons and shared utilities that don’t fit into a specific feature domain.
- Types
- Config
- Services
types.ts — The single source of truth for all TypeScript interfaces
src/lib/core/types.ts
Modules layer (lib/modules/)
Feature-specific business logic organized by domain. Each module is self-contained.
Example: Menu module
The menu/ module contains useMenuLogic.ts, a custom hook that handles:
- Table context hydration from route parameters
- Birthday mode activation based on table metadata
- Product filtering by menu type (FULL vs DRINKS_ONLY)
- Category-based grouping for section rendering
src/lib/modules/menu/useMenuLogic.ts
Services layer (lib/services/)
External API integrations that communicate with third-party services.
Mapbox
Directions API, polyline decoding, ETA calculation
HTML template rendering and file generation
Telegram
Bot API document upload with multipart/form-data
Stores layer (stores/)
Global state management using Zustand. Three independent stores handle all session state:
- useTableStore — Active table session and QR scan state
- useCartStore — Shopping cart, totals, discounts, service type
- useLocationStore — App mode, GPS coordinates, delivery route
Components layer (components/)
React Native UI components organized by feature:
scanner/— QR code scanning with camera and idempotency guardslocation/— GPS-based context switching and Mapbox integrationui/— Reusable UI components (banners, error states, toasts)
Why feature-based?
Compare the two approaches:- Feature-based (TableOrder)
- Type-based (alternative)
- All payment logic in one place
- Easy to add/remove complete features
- Clear domain boundaries
Adding a new feature like SMS notifications would require touching only one folder:
lib/services/smsService.ts. Removing Telegram integration means deleting a single file.App flow
The application follows a context-driven navigation pattern: Each mode has its own navigation stack, but they share the same cart and checkout flow. State is managed by Zustand stores that persist across mode switches.Next steps
State management
Learn how Zustand stores manage application state
Services
Explore external API integration patterns