Technical Architecture

Three-platform system: Node.js backend, React web client, and native iOS app connected via REST API and WebSocket.

3
Platforms
60+
AI Actions
20+
DB Tables
18+
API Routes

1 Tech Stack

Server (Backend) Node.js

  • Fastify 5 — HTTP framework
  • @fastify/websocket — real-time chat
  • TypeScript — strict mode, ESM
  • Supabase — PostgreSQL + Auth
  • OpenAI API — GPT-4o / GPT-5
  • Zod 4 — runtime validation
  • Vitest — testing

Web (Frontend) React

  • React 19 — UI library
  • Vite 7 — build tool
  • TypeScript — strict mode
  • Zustand — state management
  • TanStack Query — server state
  • Tailwind CSS 4 — styling
  • Recharts — charts

iOS (Mobile) Swift

  • SwiftUI — declarative UI
  • URLSession — HTTP + WebSocket
  • Combine — reactive data flow
  • Keychain — secure storage
  • Certificate pinning — security
  • 17 chart views — native charts
  • Localization — EN + RU

2 System Architecture

Client Layer
iOS App (Swift/SwiftUI)
Web App (React/Vite)
REST API Clients
↓ HTTPS / WSS
Web Server (Caddy — reverse proxy, TLS)
api.monaime.app → :3004
monaime.app → static files
Application Layer (Fastify + PM2)
Auth Middleware (JWT)
REST Routes (18+)
WebSocket Handler
Rate Limiter
AI Processing Layer
Command Parser (GPT-4o-mini)
Entity Resolver (fuzzy match)
Action Registry (60+ actions)
Response Generator (GPT-4o)
Business Logic Layer
Finance Module
Trigger Engine
Scheduler
Notifications
Memory (RAG)
Data Layer
PostgreSQL (Supabase)
Row-Level Security
pgvector (embeddings)
DB Functions & Triggers

3 Server Directory Structure

Server/src/ ├── index.ts # Entry point, service startup, graceful shutdown ├── app.ts # Fastify app setup (CORS, JWT, WS, multipart) ├── config/ # Environment validation (Zod), Supabase clients ├── core/ │ ├── action-registry.ts # Central command dispatcher │ ├── base-action.ts # Abstract base class for all actions │ ├── entity-resolver.ts # Fuzzy matching (exact, normalized, prefix, contains) │ └── types.ts # IAction, IModule, ActionContext interfaces ├── middleware/ │ ├── auth.middleware.ts # JWT validation via Supabase Auth │ ├── error.middleware.ts # Global error handler │ └── rate-limit.middleware.ts # Per-user rate limiter (30 msg/min) ├── models/ │ ├── types.ts # Entity interfaces (User, Wallet, Transaction, etc.) │ └── schemas.ts # Zod validation schemas for requests ├── modules/finance/ │ ├── index.ts # Finance module registration │ └── actions/ # 60+ action files (create-wallet, add-transaction, etc.) ├── services/ │ ├── ai.service.ts # OpenAI API (GPT-4o / GPT-5) │ ├── command-parser.ts # Natural language → structured commands │ ├── action-executor.ts # Routes commands to action registry │ ├── context.service.ts # User context caching (60s TTL) │ ├── memory.service.ts # Conversation summarization + RAG │ ├── scheduler.service.ts # Hourly tasks (recurring templates, reminders) │ ├── triggers/ # TriggerEngine + 7 trigger types │ └── ... # 20+ service files ├── routes/ # 18+ route files (REST endpoints) ├── websocket/ │ ├── chat.handler.ts # WebSocket connection handler │ ├── message.processor.ts # Message processing pipeline │ ├── confirmation.handler.ts # Dangerous action confirmations │ └── ws.utils.ts # WSSender helper (cards, streaming) ├── prompts/ # AI system prompts (English only) ├── locales/ # i18n translations (RU + EN) └── utils/ # Text normalization, validators

4 Chat Message Processing Flow

1

User Sends Message

Natural language via WebSocket (wss://api.monaime.app/ws/chat). First message must include auth token.

2

Rate Limit + Command Parsing

Rate limiter checks (30 msg/min). CommandParser calls GPT-4o-mini to extract structured command (action type, parameters) from natural language.

3

Entity Resolution

EntityResolver resolves text references to real IDs using fuzzy matching: exact → normalized → prefix → contains. Wallets, categories, contacts, etc.

4

Validation & Safety Check

CommandValidator checks if action is dangerous (delete_wallet, delete_transaction, close_debt). If dangerous — sends confirmation request to user.

5

Action Execution

ActionExecutor routes to the correct action in ActionRegistry. Action validates params (Zod), performs DB operations, returns result.

6

AI Response Generation

AIService streams response via GPT-4o. Includes action result, user context, conversation history. Response is streamed chunk-by-chunk via WebSocket.

7

Cards & Data Updates

Server sends entity cards (card, batch-cards, grouped-cards) and data_updated events for client cache invalidation.

5 WebSocket Message Protocol

Type Direction Description
{ token }Client → ServerAuthentication (first message)
authenticatedServer → ClientAuth success confirmation
messageBothText message (user input / bot response)
stream_startServer → ClientAI response streaming begins
stream / stream_chunkServer → ClientPartial AI response chunk
stream_endServer → ClientAI response streaming complete
cardServer → ClientSingle entity card (transaction, wallet, etc.)
batch-cardsServer → ClientArray of cards
grouped-cardsServer → ClientCards organized in named groups
data_updatedServer → ClientCache invalidation signal with data snapshot
typingServer → ClientBot is processing
errorServer → ClientError message
stop_generationClient → ServerStop current AI generation

6 Key Server Services

AIService

OpenAI API wrapper. Supports GPT-4o and GPT-5. Streaming responses, function calling for command parsing.

CommandParser

Parses natural language into structured commands using GPT-4o-mini. Extracts action type, parameters, entities.

EntityResolver

4-step fuzzy matching: exact, normalized (remove spaces), prefix, contains. Supports entity aliases.

ContextService

Caches user context (wallets, categories, contacts) with 60s TTL to reduce DB queries.

TriggerEngine

7 trigger types: budget limits, goal milestones, salary detection, anomalies, recurring reminders, debt reminders, suggestions.

SchedulerService

Hourly background tasks: process recurring templates, check reminders, debt due dates. Budget spent is computed at query time (no cron needed).

MemoryService

Conversation summarization with OpenAI embeddings (text-embedding-3-small). Stored in pgvector for semantic search (RAG).

ActionHistoryService

Logs all CRUD operations for undo functionality. Stores previous and new state. Auto-cleans (keeps 50 per user).

7 iOS App Architecture (MVVM)

iOS/MoneyChat/ ├── App/ # MoneyChatApp.swift (entry point), AppDelegate ├── Config/ # API URLs, Supabase credentials, DesignTokens ├── Models/ │ ├── ChatMessage.swift # ChatMessage, EntityData, EntityType enum │ ├── CardModels.swift # CardEntity enum (942 lines, full Codable) │ └── StatsModels.swift # Stats-related data models ├── Services/ # 13 service files (singletons) │ ├── AuthService.swift # Supabase auth, token refresh, Keychain │ ├── WebSocketService.swift # WSS connection, auto-reconnect, ping │ ├── APIService.swift # REST API client for all entities │ ├── HTTPClient.swift # URLSession + certificate pinning │ ├── KeychainService.swift # Secure credential storage │ ├── CacheService.swift # In-memory cache (5-min TTL) │ └── EntityCache.swift # Persistent UserDefaults cache ├── ViewModels/ │ ├── ChatViewModel.swift # Chat messages, WS handling (928 lines) │ └── StatsViewModel.swift # Statistics data loading ├── Views/ # 71 Swift files │ ├── Auth/ # LoginView │ ├── Chat/ # ChatView, ChatInputBar, MessageRow │ ├── Components/ # 30 card views, edit views, UI utilities │ ├── Charts/ # 17 native chart views │ └── Stats/ # StatsView dashboard └── Resources/ # 226 icons, color sets, EN/RU localization
🔒
iOS Security Certificate pinning (SHA-256), Keychain for tokens, proactive token refresh before expiry, auto-logout on refresh failure. All communication via HTTPS/WSS.

8 Web App Architecture

Web/src/ ├── api/ # HTTP client, chat, transactions, wallets API ├── components/ │ ├── chat/ # Chat interface, messages, input, cards │ ├── sidebar/ # Wallets, categories, budgets panels │ ├── sheets/ # Modal dialogs for CRUD operations │ ├── analytics/ # Charts (Recharts) & analytics panels │ └── ui/ # Base components (Radix UI primitives) ├── hooks/ # React hooks (useChat, useWebSocket, useWallets, etc.) ├── store/ # Zustand stores (auth, chat, UI, undo) ├── pages/ # LoginPage, ActionHistoryPage, Settings ├── types/ # TypeScript interfaces for all entities ├── locales/ # i18n (EN + RU) └── App.tsx # Root component with routing
📱
Responsive Layout Desktop: Sidebar + Chat + Analytics. Tablet: Sidebar + Chat (analytics as modal). Mobile: Tab-based navigation (Chat | Sidebar | Analytics).

9 Authentication Flow

1

Sign In

User signs in via Supabase Auth (email/password or OAuth). Returns access_token, refresh_token, expires_in.

2

Token Storage

iOS: stored in Keychain. Web: stored in Zustand (persisted to localStorage). Server never stores tokens.

3

API Requests

REST: Authorization: Bearer <token> header. WebSocket: first message contains { token }. Server validates via supabase.auth.getUser(token).

4

Token Refresh

Proactive refresh 5 min before expiry. On refresh: WebSocket reconnects with new token. HTTP client uses new token automatically.

10 Environment Variables

Variable Required Description
PORTNo (3000)Server port
HOSTNo (0.0.0.0)Server host
NODE_ENVNodevelopment / production / test
SUPABASE_URLYesSupabase project URL
SUPABASE_ANON_KEYYesSupabase anon key (for client auth checks)
SUPABASE_SERVICE_KEYYesSupabase service role key (for DB operations)
OPENAI_API_KEYYesOpenAI API key
JWT_SECRETYesJWT secret (min 32 chars)
CORS_ORIGINNoAllowed CORS origins (comma-separated)
FIXER_API_KEYNoFixer.io API key for exchange rates
AI_MODEL_FAMILYNogpt-4o or gpt-5 (default: gpt-5)