Frontend Applications

Mobile PWA Client

Comprehensive technical guide to the DepthSight mobile PWA — state-machine navigation, strategy editor, AI chat, offline support via service worker, push notifications, and Google OAuth flow.

⏱️ 10 min read📊 Level: Intermediate

The DepthSight PWA (pwa/) is a React 19 mobile-optimized Progressive Web Application built with Vite 8, TypeScript 6, and Tailwind CSS 4. It provides full trading platform functionality on mobile devices — portfolio monitoring, strategy editing, backtesting, AI assistant, and push notifications — all installable as a standalone app.

Source: pwa/ — ~66 source files, ~17,500 lines total.


Architecture Overview

Unlike the web dashboard which uses react-router, the PWA employs a state-machine navigation pattern — the activeScreen state determines which component is rendered:

Rendering diagram...

Provider Hierarchy

QueryClientProvider (TanStack React Query)
  -> GoogleOAuthProvider
    -> AuthProvider (JWT auth)
      -> NotificationProvider (push notifications)
        -> SymbolSelectionSettingsProvider
          -> App

Defined in types.ts as a Screen enum with 14 screens:

Sources:

Bottom navigation is only shown for the 4 primary screens: Dashboard, Strategies, Research, Notifications.


State Management

Zustand Stores

StoreFileLinesPurpose
strategyEditorStorestores/strategyEditorStore.ts1,540Full editor state — filters, entry conditions, initialization, position management, foundation weights, symbol selection. Uses immer for immutable updates. 30+ action functions.
accountStorestores/accountStore.ts23Persisted selected API key ID (localStorage)

React Contexts

ContextFilePurpose
AuthContextcontexts/AuthContext.tsx (94 lines)User/token state, login/logout, token refresh
AIChatContextcontexts/AIChatContext.tsx (259 lines)Chat messages, session management, typing indicator
NotificationContextcontexts/NotificationContext.tsx (182 lines)In-app notifications + push subscription state
SymbolSelectionSettingsContextcontexts/SymbolSelectionSettingsContext.tsx (65 lines)Symbol selection mode configuration

API Layer

The API client (services/api.ts, 401 lines) uses a custom apiFetch<T>() function with automatic JWT refresh:

Sources:

API Endpoints by Domain:

DomainKey Endpoints
Authlogin, register, getMe, refresh
DashboardgetPortfolio, getPositions, getPortfolioEquity, closePosition
AI ChataiChat, getChatHistory, initChatSession, deleteChatSession
StrategiesgetSavedStrategies, getRunningStrategies, startStrategy, stopStrategy, saveStrategy
BacktestsgetBacktests, getBacktestDetails, runBacktest, getBacktestKlines
AccountgetAccountStatus, getPlans, createPayment, resetPaperAccount
API KeysaddApiKey, deleteApiKey, testApiKey
GamificationgetAchievements, getUserAchievements, getMyGenes
ConfiggetConfig, updateConfig

Screens (Pages)

ScreenComponentLinesDescription
DashboardDashboardScreen.tsx377Portfolio overview, PnL chart (Recharts), active positions list
StrategiesStrategiesScreen.tsx367Saved + running strategies with status badges, FAB to create new
ResearchResearchScreen.tsx194Backtest history with tabs for analytics
NotificationsNotificationsScreen.tsx165In-app notification list with read/unread state
AI ChatAIChatScreen.tsx385Full chat interface with message history, strategy JSON responses
EditorEditorHybridScreen.tsx → EditorScreen.tsx244 + 535Visual strategy builder optimized for mobile touch
BacktestResult(inline in App.tsx)~250KPI cards (PnL, win rate, drawdown, Sharpe), equity chart, trade table
ProfileProfileScreen.tsx665Account details, plans, billing history, achievements, referrals
SettingsSettingsScreen.tsx360Risk management configuration
AuthAuthScreen.tsx383Login/Register with Google OAuth
ForgotPasswordForgotPasswordScreen.tsx120Password reset request
ResetPasswordResetPasswordScreen.tsx147New password form

Strategy Editor (Mobile)

The mobile strategy editor is a touch-optimized version of the web editor with the same block system:

Editor Components

ComponentLinesPurpose
BlockInspectorModal2,021The largest file — comprehensive block parameter editor with dynamic inputs for every block type
BlockItem182Single block card with drag handle (via @dnd-kit)
ComponentPaletteModal227Block type picker organized by category
InitializationBlock224Position sizing, SL/TP, direction configuration
BlockLinkPopover102Dynamic value linking between blocks
FoundationWeightsModal177Foundation weight configuration
CollapsibleSection41Collapsible UI sections

Block Types

Defined in constants/blockConfig.ts (334 lines) — ~40+ block types organized into:

CategoryExamples
FoundationsOrderbook, Pattern, Trend, Level, RoundNumber, TapeAcceleration, MarketActivity, VolumeConfirmation, ReturnToLevel
FiltersTradingSession, TimeFilter, TrendFilter, VolatilityFilter, NATRFilter, ADXFilter, BTCStateFilter, Correlation
IndicatorsRSI, MACD, Bollinger Bands, Stochastic, EMA, SMA, ATR, ADX
Entry ConditionsMA Cross, Price vs Level, Volume Confirmation, Classic Pattern, Level Touch, Volatility Squeeze
ManagementTrailing Stop, Breakeven, Partial Exit, Scale In, DCA, Grid

Strategy Serialization

The editor serializes blocks to a JSON structure matching the backend schema:

Sources:

AI Chat Integration

The AI chat (contexts/AIChatContext.tsx, 259 lines + AIChatScreen.tsx, 385 lines) allows mobile users to:

  1. Generate strategies from text descriptions — sends prompt to backend, receives strategy JSON, loads into editor.
  2. Modify strategies — provides natural language instructions to adjust existing strategy parameters.
  3. Analyze backtests — requests performance explanations and improvement suggestions.

The geminiService.ts (51 lines) is a thin wrapper — the actual AI logic runs on the backend via /api/v1/ai/chat.


Service Worker & Offline Support

The PWA service worker (public/sw.js, 116 lines) implements a hybrid caching strategy:

Cache Strategy

Request TypeStrategyBehavior
Navigation (HTML)Network FirstTry network, fallback to cached index.html
Static assets (JS/CSS)Cache FirstServe from cache, update from network in background
API calls (/api/v1)Network OnlyNever cached — always fresh data

Lifecycle

Sources:

Update Flow

1. New SW detected → "Update available" toast
2. User taps "Reload" → postMessage({ type: "SKIP_WAITING" })
3. SW activates → clients.claim()
4. Page reloads automatically

Push Notifications

Defined in services/notificationService.ts (130 lines):

  1. Fetches VAPID public key from /api/v1/notifications/vapid_public_key.
  2. Subscribes via PushManager.subscribe({ userVisibleOnly: true, applicationServerKey }).
  3. Sends subscription to /api/v1/users/subscribe_push.
  4. On push event — shows browser notification with icon + vibration pattern.

Google OAuth Flow

Sources:

The Google credential (JWT) is sent to the backend, which validates it and returns an application JWT. The PWA stores this token in localStorage under depthsight_pwa_token.


Internationalization

SettingValue
Libraryi18next 26 + react-i18next 17
Languagesen, ru
NamespaceSingle pwa-common
Translation linesEN: 1,089, RU: 1,102
ScopeAuth, Dashboard, Analytics, Strategies, Editor, AI Chat, Profile, Settings, Notifications, Achievements (33 named)

Build & Deployment

ScriptCommand
devvite (port 5174)
buildvite build
linteslint .
previewvite preview

Production base path: base: "/pwa/" — deployed behind nginx at /pwa/ subpath.

Vite dev proxy:

Sources:

Web App Manifest:

Sources: