Skip to content

Frontend Architecture

DIIZZYFPS edited this page Mar 5, 2026 · 1 revision

Frontend Architecture

sAIve's frontend is a Single Page Application (SPA) built with React, TypeScript, and Vite, packaged inside an Electron shell for desktop distribution.


Tech Stack Overview

  • Core: React 18, TypeScript, Vite
  • Data Fetching & State: TanStack Query v5 (React Query), Axios
  • Styling: TailwindCSS, Shadcn UI (Radix UI primitives)
  • Routing: React Router DOM (HashRouter)
  • Charts: Recharts (Line, Radar, Bar) and amCharts (Sankey Flow)
  • Local AI Inference: @huggingface/transformers running in a dedicated Web Worker via WebGPU.

File Structure

sAIve/src/
├── components/       # Reusable UI components (Sidebar, Cards, Inputs, Shadcn UI)
├── context/          # React Contexts (SettingsContext, AiContext)
├── hooks/            # Custom hooks (e.g., useServerEvents)
├── lib/              # Utilities (api config, shadcn utils)
├── pages/            # Top-level route components (Index, Transactions, Budget, etc.)
├── workers/          # Web Workers (ai.worker.ts)
├── App.tsx           # Router and Theme Provider wrap
└── index.css         # Tailwind directives and CSS variables

State Management

sAIve avoids heavy global state libraries like Redux. Instead, it uses a combination of React Context and TanStack Query.

1. TanStack Query (Server State)

All financial data (transactions, budgets, historical assets) is considered "Server State" and is managed by useQuery and useMutation hooks.

  • Caching: Queries are cached to make page transitions instant.
  • Invalidation: Read Server-Sent Events below.

2. React Context (Client State)

Used for globally accessible UI or configuration state that doesn't belong in the database.

  • SettingsContext: Manages the user's selected currency (USD, EUR, GBP, etc.), the active AI Model selection, and whether the AI is enabled. State is persisted to localStorage.
  • AiContext: Manages the lifecycle and status (loading, ready, generating) of the background AI Web Worker. Provides the generate() and suggestCategory() functions to the rest of the application.

Real-Time Sync (SSE)

Unlike traditional CRUD apps that require you to manually call refetch() after a POST request, sAIve uses a decentralized real-time approach.

The useServerEvents hook runs at the top level of the app and listens to the backend's /events/{userId} stream.

When a write occurs anywhere (e.g. deleting a transaction on the Transactions page):

  1. The Backend fires a transactions_changed SSE event.
  2. The Frontend listens and catches it.
  3. useServerEvents looks up a mapping table and calls queryClient.invalidateQueries({ queryKey: ["transactions"] }).
  4. The Transactions Table (and the Dashboard summaries) instantly fetch the new data in the background and update seamlessly.

Local AI Engine Integration

To ensure the heavy computation of LLM inference doesn't freeze the React UI, the AI engine runs entirely inside a Web Worker (ai.worker.ts).

The Worker (ai.worker.ts)

  1. Instantiates a pipeline from @huggingface/transformers requesting WebGPU acceleration.
  2. Listens for load, generate, and interrupt messages from the main thread.
  3. Streams text tokens back to the main thread as they are generated using a TextStreamer.

The Context (AiContext.tsx)

  1. Silently initializes the Web Worker on boot.
  2. Handles the complex Promise resolution required to turn asynchronous worker messages (postMessage) back into awaitable generate() calls for the UI components.
  3. Provides specialized helper functions like suggestCategory().

The Chat Interface (AiChat.tsx)

  • Renders system and user messages.
  • Appends the System Context automatically under the hood: Before sending the user's prompt to the worker, AiChat fetches their recent transactions and current net worth, structuring it into a hidden system prompt so the local AI has real-time awareness of their finances.
  • Renders the streaming markdown responses.

Theming and Styling

  • Tailwind CSS: Utility-first styling forms the backbone of the application.
  • Shadcn UI: Unstyled, accessible component primitives (Dialogs, Selects, Buttons) that are customized via Tailwind.
  • Theme Provider: Supports light, dark, and system options, persisting the choice to localStorage and attaching the .dark class to the HTML root object automatically.
  • CSS Variables: Core colors (backgrounds, borders, primary accents, category colors) are defined as CSS variables in index.css to allow seamless swapping between Light and Dark mode variations.