Data Visualization and Charts
Relevant source files
The following files were used as context for generating this wiki page:
- frontend/components/charts/sankey-flow-chart.tsx
- frontend/components/charts/spending-by-category-chart.tsx
- frontend/lib/dashboard/sankey.ts
- frontend/lib/actions/dashboard.ts
- backend/app/routes/analytics.py
- frontend/components/charts/kpi-spark-card.tsx
- frontend/components/accounts/account-balance-chart.tsx
Introduction
The data visualization and charts system provides users with interactive insights into their financial health by processing raw transaction data into visual representations. The system supports multiple visualization types, including cash flow diagrams, trend lines, and category-based breakdowns. It utilizes a combination of Recharts on the frontend for rendering and Server Actions (Next.js) or FastAPI (Python) endpoints for data aggregation.
The scope of this system includes the calculation of income/expense history, balance trends over various horizons, and complex flow visualizations like Sankey diagrams. These visualizations allow users to identify spending patterns, track savings rates, and drill down into specific transaction details by interacting with chart elements.
Sources: CLAUDE.md:46-49, frontend/app/(dashboard)/page.tsx:75-108
System Architecture and Data Flow
The visualization architecture follows a decoupled pattern where data is aggregated on the server-side before being consumed by client-side chart components.
Data Fetching and Aggregation
Data flows from the PostgreSQL database through two primary paths depending on the service:
- Frontend Server Actions: Use Drizzle ORM to perform SQL aggregations (e.g.,
SUM,GROUP BY) based on user-selected date ranges and accounts. - Backend Analytics Routes: FastAPI endpoints provide similar aggregation logic using SQLAlchemy for Python-based consumers or specific analytics requests.
The diagram shows the flow of financial data from the database to the final UI components.
Sources: frontend/lib/actions/dashboard.ts:311-370, backend/app/routes/analytics.py:15-20
Visualization Components
1. Sankey Cash Flow
The Sankey diagram visualizes the flow of money from income sources to expense categories. It uses a "conservative" building logic that balances income and expenses by introducing synthetic nodes.
- Logic: If income exceeds expenses, a "Savings" node is added. If expenses exceed income, a "Funding Gap" node is added.
- Interactivity: Nodes and links are clickable, triggering a drill-down into specific transaction views.
| Feature | Implementation Detail |
|---|---|
| Logic Provider | buildConservativeSankey function |
| Primary Nodes | Income Categories, Expense Categories |
| Synthetic Nodes | Savings, Funding Gap |
| Interactive Logic | navigateToTransactions callback |
Sources: frontend/lib/dashboard/sankey.ts:40-65, frontend/components/charts/sankey-flow-chart.tsx:235-260
2. KPI Spark Cards
KPI Spark Cards provide high-level metrics (Total Balance, Spending, Income) paired with a simplified trend line (Sparkline).
- Sparkline Data: An array of
SparkDataPointobjects containingdateandvalue. - Trend Calculation: Shows percentage changes and indicates positive/negative movement via color-coding (Emerald for positive, Red for negative).
Sources: frontend/components/charts/kpi-spark-card.tsx:12-45, frontend/lib/actions/dashboard.ts:588-600
3. Account Balance and History
The system tracks balance trends over multiple horizons (7D, 30D, 90D, 1Y, etc.).
- Data Filling: For gaps in daily transaction records, the system calculates the most recent balance to provide a continuous line.
- Normalization: Frontend logic ensures that if a horizon extends before available data, the chart is clamped to the earliest data point.
This sequence illustrates how the balance chart handles time-horizon changes and data gaps.
Sources: frontend/components/accounts/account-balance-chart.tsx:103-155, frontend/lib/actions/dashboard.ts:140-170
4. Spending by Category
A horizontal bar chart representing expenses by category, sorted by amount.
- Net Amount Calculation: For linked transactions (reimbursements or splits), the system calculates the net amount of the group rather than using the raw primary transaction amount.
- Uncategorized Handling: Specifically identifies and sums transactions missing both user-defined and system categories.
Sources: frontend/lib/actions/dashboard.ts:311-350, frontend/components/charts/spending-by-category-chart.tsx:75-95
Key Data Structures
Sankey Data Structure
interface SankeyData {
nodes: {
name: string;
categoryId?: string | null;
categoryType?: "income" | "expense";
total?: number;
}[];
links: {
source: number;
target: number;
value: number;
}[];
}
Sources: frontend/lib/actions/dashboard.ts:536-544
Analytic API Parameters
| Parameter | Type | Description |
|---|---|---|
from_date | datetime | Start of the analytics window |
to_date | datetime | End of the analytics window |
account_id | UUID | Filter stats for a specific account |
uncategorized | boolean | If true, filters for transactions without categories |
Sources: backend/app/routes/analytics.py:17-24
Conclusion
The data visualization system transforms raw financial records into actionable intelligence using optimized server-side aggregation and responsive frontend components. By balancing data through the Sankey logic and ensuring continuity in balance history, the system provides a reliable view of both current status and historical trends. The tight integration between Recharts and Next.js Server Actions ensures that charts remain synchronized with the underlying PostgreSQL state.