Repository navigation
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.
- 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/transformersrunning in a dedicated Web Worker via WebGPU.
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
sAIve avoids heavy global state libraries like Redux. Instead, it uses a combination of React Context and TanStack Query.
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.
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 tolocalStorage. -
AiContext: Manages the lifecycle and status (loading,ready,generating) of the background AI Web Worker. Provides thegenerate()andsuggestCategory()functions to the rest of the application.
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):
- The Backend fires a
transactions_changedSSE event. - The Frontend listens and catches it.
-
useServerEventslooks up a mapping table and callsqueryClient.invalidateQueries({ queryKey: ["transactions"] }). - The Transactions Table (and the Dashboard summaries) instantly fetch the new data in the background and update seamlessly.
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).
- Instantiates a
pipelinefrom@huggingface/transformersrequesting WebGPU acceleration. - Listens for
load,generate, andinterruptmessages from the main thread. - Streams text tokens back to the main thread as they are generated using a
TextStreamer.
- Silently initializes the Web Worker on boot.
- Handles the complex Promise resolution required to turn asynchronous worker messages (postMessage) back into awaitable
generate()calls for the UI components. - Provides specialized helper functions like
suggestCategory().
- Renders system and user messages.
- Appends the System Context automatically under the hood: Before sending the user's prompt to the worker,
AiChatfetches 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.
- 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, andsystemoptions, persisting the choice tolocalStorageand attaching the.darkclass to the HTML root object automatically. -
CSS Variables: Core colors (backgrounds, borders, primary accents, category colors) are defined as CSS variables in
index.cssto allow seamless swapping between Light and Dark mode variations.