Skip to content

dipto0321/spendrift-fe

Repository files navigation

πŸ’° Spendrift

A modern, minimal personal finance tracking application built with a focus on clarity, scalability, and AI-assisted development.


πŸš€ Overview

Spendrift helps users track:

  • Daily expenses (Needs vs Wants)
  • Monthly budgets and savings targets
  • Financial reports (weekly / monthly / yearly)
  • Multi-year spending comparisons
  • Category breakdowns and analytics

The app is designed as a tracker-based system, where each tracker represents an independent financial workspace with its own currency (e.g., Bangladesh Tracker in BDT, Europe Tracker in EUR).

All features are backed by the real Spendrift API (FastAPI) β€” see Getting Started.


🧱 Tech Stack

  • TanStack Start β€” full-stack React framework (SSR + file-based routing)
  • React + TypeScript
  • TailwindCSS + ShadCN UI (Radix primitives)
  • TanStack Query β€” server-state, caching, and invalidation
  • Zod + React Hook Form β€” schema validation
  • Recharts (via ShadCN charts), Sonner (toasts)
  • Biome β€” formatter + linter
  • Vitest β€” unit tests
  • Sentry β€” error monitoring

⚑ Getting Started

Prerequisites

  • Node.js 20+ and pnpm
  • A running Spendrift API (FastAPI). The frontend expects it at http://localhost:8000 with the base path /api/v1. Interactive API docs live at http://localhost:8000/docs.

Setup

# 1. Install dependencies
pnpm install

# 2. Create your local env file
cp .env.example .env.local
# then set VITE_API_BASE_URL (default: http://localhost:8000/api/v1)

# 3. Start the dev server (http://localhost:3000)
pnpm dev

Environment variables

Variable Required Description
VITE_API_BASE_URL βœ… Base URL of the Spendrift API, including the /api/v1 prefix.
VITE_APP_TITLE optional App title override.
VITE_SENTRY_* / SENTRY_* optional Sentry monitoring (see .env.example).

Scripts

pnpm dev      # start the dev server on :3000
pnpm test     # run the Vitest unit suite
pnpm check    # Biome lint + format check
pnpm build    # production build
pnpm start    # serve the production build

πŸ—οΈ Architecture

Spendrift follows a Domain-Driven, Feature-Based Architecture. Each feature is self-contained and split into three layers:

src/features/<feature>/
 β”œβ”€β”€ domain/        # types + pure business logic (services.ts)
 β”œβ”€β”€ data/          # repository.ts (API calls), dto.ts (wire mapping), queryKeys.ts
 └── presentation/  # pages + React Query hooks (use*.ts)

Data flow & the repository seam

Pages and hooks never call fetch directly. Every feature talks to the API through its data/repository.ts, which is the single swap seam:

Page β†’ presentation/use*.ts (TanStack Query) β†’ data/repository.ts β†’ shared/api/client.ts

Two impedance mismatches are handled at the data/dto.ts boundary so the domain stays clean:

  • Money is a Decimal string on the wire (e.g. "1267.42") ↔ number in the domain.
  • Casing: API is snake_case ↔ domain is camelCase.

Auth

JWT access + refresh tokens (stored in localStorage) with a single-flight refresh-on-401 retry in shared/api/client.ts. Because tokens aren't readable during SSR, a client-side WorkspaceGate (in routes/__root.tsx) is the auth source of truth.

Key principles

  • Feature-based structure, cohesive domains
  • Separation of UI from business logic
  • Repositories as the single API seam
  • Composition over abstraction; avoid premature optimization

🌍 Tracker System

Each tracker is an independent financial context with its own currency:

  • πŸ‡§πŸ‡© Bangladesh Tracker (BDT)
  • πŸ‡ͺπŸ‡Ί Europe Tracker (EUR)

Each tracker owns its expenses, categories, budgets, dashboard, and reports. The active tracker is carried in the URL as ?tracker=<id>.


πŸ’Έ Features

Expense Tracking

  • Add / edit / delete expenses
  • Needs vs Wants tagging
  • Search, date-range, type, and category filtering
  • Per-category management (with safe "reassign to Uncategorized" on delete)

Budgeting

  • One budget per tracker per current month
  • Monthly limit + savings target
  • Remaining balance and a savings-health indicator (green / yellow / red)
  • Previous months become read-only history

Dashboard

  • Current-month spend, expense count, and budget remaining
  • Needs-vs-Wants split and top categories
  • Cashflow trend + recent expenses

Reports

  • Weekly / monthly / yearly spending
  • Category breakdown and Needs-vs-Wants
  • Year-over-year comparison
  • Total / min / max / average analytics
  • Custom calendar date ranges

πŸ“Š UI / UX Philosophy

Spendrift is designed to feel minimal, calm, modern, and data-focused β€” inspired by Linear, Notion, and modern fintech dashboards.

Design principles

  • Dark theme first
  • High readability and clear hierarchy
  • Meaningful colors (not decorative)
  • Reduced visual noise

Theme

An emerald-forward palette defined as oklch design tokens in src/styles.css (light and dark variants). The default is dark; a stored preference wins. Charts use ShadCN's chart components.


πŸ§ͺ Testing

Unit tests cover the pure domain/services functions (budgets, expenses, reports) with Vitest:

pnpm test

Tests run in an isolated vitest.config.ts (node environment, @/ alias) so they skip the full app plugin chain.


πŸ“ Project Structure

src/
 β”œβ”€β”€ features/          # dashboard, expenses, budgets, reports, trackers
 β”‚   └── <feature>/     # domain/ Β· data/ Β· presentation/
 β”œβ”€β”€ shared/
 β”‚   β”œβ”€β”€ api/           # apiFetch client + token storage
 β”‚   β”œβ”€β”€ ui/            # shared UI (AppSidebar, StatCard, ThemeToggle…)
 β”‚   β”œβ”€β”€ hooks/
 β”‚   └── utils/
 β”œβ”€β”€ components/ui/     # ShadCN-generated primitives
 β”œβ”€β”€ routes/            # TanStack Start file-based routes
 └── styles.css

πŸ” Development Workflow

  1. Plan the feature structure first
  2. Break it into small steps
  3. Implement incrementally behind the repository seam
  4. Verify (tests + run the app)
  5. Commit using conventional commits
feat(expenses): add expense list UI
fix(budget): correct remaining balance calculation
refactor(api): back reports with the real API

πŸ€– AI-Assisted Development

This project leans on AI for architecture planning, code explanation, UI exploration, and refactoring β€” used as a mentor and assistant, not an autopilot. The goal is learning by building, not blind generation.


🚧 Roadmap

  • Investment tracking
  • Loan management
  • AI-powered financial insights
  • Multi-user SaaS support
  • Mobile optimization
  • SSR auth via httpOnly cookies (currently a client-side gate)

πŸ–ΌοΈ Screenshots

Sign In

Sign In

Sign Up

Sign Up

Dashboard

Dashboard

Expense List

Expenses

Budget

Budget

Reports

Reports


πŸ“œ License

Copyright (c) 2026 Dipto Karmakar

Licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file for full terms.

In plain English:

  • You may study and use this code for personal/educational purposes
  • If you modify and distribute it, you must open-source your version under AGPL-3.0
  • You may not use this in a commercial product or SaaS without written permission from the author
  • You must credit the original author (Dipto Karmakar) in any derivative work

For commercial licensing inquiries: diptokmk47@gmail.com


✨ Author

Dipto Karmakar β€” Frontend engineer focused on React / TypeScript, domain-driven design, high-performance UI, and AI-assisted workflows. Spendrift is a personal initiative to explore modern fintech UX and scalable SaaS architecture.

About

A modern, minimal personal finance tracking application

Resources

License

Stars

Watchers

Forks

Contributors