Skip to content

Repository files navigation

Budgeteer banner

Budgeteer

Vite React TypeScript Chakra UI Zustand AWS Amplify Apollo GraphQL

Developer Hub Contributing Guide API Reference Changelog License

Budgeteer is a privacy-aware personal finance app focused on:

  • Planning-first budgeting (scenarios + monthly plans)
  • CSV-based transaction imports (user-controlled; no bank credential scraping)
  • Safe staging/apply/undo for imports
  • Clear monthly tracking (planned vs actual)

Key docs:


Project status (Current vs goal)

Current (baseline is stable):

  • Frontend-only React SPA with Chakra UI + Zustand persisted local domain state.
  • Amplify/Cognito auth wired; AppSync GraphQL used primarily for shared backend models (notably UserProfile).
  • Core budgeting workflows exist:
    • Planner (scenario-based planning)
    • Tracker (planned vs actual)
    • Accounts + CSV import
  • CSV ingestion is designed to be deterministic and safe:
    • preview → stage → apply/undo
    • idempotent re-import via a strong transaction key
    • optional streaming parse for large files

Goal (roadmap direction):

  • Phase 1: tighten product surface coherence (copy/routes/storage keys; remove migration drift).
  • Phase 2: type hardening + domain boundaries (split store slices; replace high-risk any; add high-value tests).
  • Phase 3: Planner/Tracker UX polish (validation, clearer calculations, better empty states).
  • Phase 4: ingestion UX/perf enhancements (review tooling, inference UX, performance tuning).
  • Phase 5 (optional): cloud sync/backend alignment, gated by privacy constraints and an intentional data ownership model.

Known issues (current focus):

  • Phase 1 focus is tightening core UX and docs.
  • See TODO.md for the current backlog and prioritization.

🛠️ Tech Stack

  • React 19 + Vite 7 + TypeScript
  • Chakra UI
  • Zustand (persisted local state)
  • AWS Amplify (Cognito + AppSync) for identity and backend APIs

Getting started

npm install
npm run dev

Vite will choose an available port (typically http://localhost:5173, or the next available).

Optional env:

  • VITE_API_BASE_URL — base URL for any non-AppSync endpoints (if configured)

Available scripts

From package.json:

  • npm run dev — run the dev server
  • npm run check — lint + test + build (verification)
  • npm run build — typecheck + production build
  • npm run preview — preview the production build
  • npm run lint — run ESLint

Samples (CSV)

Sample CSVs live in the /samples folder:

  • samples/sample-transactions.csv — small curated sample
  • samples/History_07-28-25.csv — larger history-style export

See samples/README.md for format notes and what each file is for.

Expected columns (header required):

  • dateYYYY-MM-DD
  • description
  • amount — numeric
  • Optional: type (income|expense|savings), category, balance

Contributing

See CONTRIBUTING.md.

The accounts feature accepts CSV with the following columns (header required):

  • date – Transaction date in YYYY-MM-DD
  • description – Vendor/description text
  • amount – Number (normalized to absolute value)
  • type – One of income, expense, savings
  • category – Optional free text

Notes:

  • Amounts are normalized to absolute values (amount) while the original sign is kept in rawAmount.
  • Strong transaction key (used everywhere): account|date|signedAmount|normalized description[|bal:balance].
  • amount is stored absolute; rawAmount preserves the signed original (used in the strong key signedAmount component).
  • Transactions are sorted ascending by date after merge.

Example:

date,description,amount,type,category
2025-08-03,Walmart Grocery,89.12,expense,groceries
2025-08-05,Paycheck,2450.00,income,salary
2025-08-10,Transfer to Savings,200.00,savings,

🔐 Auth & demo mode tips

  • Auth is handled via AWS Amplify (Cognito) using aws-amplify/auth.
  • Demo Mode is a real end-to-end flow that runs the normal CSV import pipeline.
  • See docs/developer/demo-mode-mvp-plan.md for the design + checklist.
  • Persisted state is user-scoped in localStorage under keys like budgeteer:u:<scope>:....

🛠️ Troubleshooting

  • Dev server port in use: if 5173 is busy, stop the other process or run with a different port (e.g., npm run dev -- --port 5174).
  • Stale local data: use Settings → clear caches/reset, or clear keys prefixed with budgeteer: in devtools Application → Local Storage.
  • CSV import errors: ensure headers match date,description,amount,type,category and dates are YYYY-MM-DD.
  • Lint/type errors: run npm run lint and address reported issues; restart the dev server after large refactors.

Category Inference (Current & TODO)

Developer: Metrics Panel & Benchmark Toggle

The import modal includes a metrics panel (timings, duplicate ratio, rows/sec, per‑stage breakdown) automatically after a dry run. For deeper performance analysis you can enable the synthetic ingestion benchmark panel:

  1. Go to Settings → Developer section.
  2. Toggle "Show Ingestion Benchmark Panel".
  3. A fixed panel appears (dev only) allowing you to:
    • Generate synthetic CSVs of arbitrary sizes and duplicate ratios.
    • Simulate streaming (pre-parsed rows path).
    • View per-run wall / ingest / process timings, rows/sec, duplicate %.
    • Capture canonical baselines (5k / 10k / 60k / 100k) via the "Capture Baseline" button.
    • Persist captured baselines in localStorage (ingestionBaselineSnapshots) for regression comparison; clear them with "Clear Baselines".
    • Export JSON of detailed runs or baselines for historical tracking.

Tip: Use baseline snapshots before and after performance changes (e.g., enabling early dedupe short‑circuit) to quantify impact. Rows/sec = total rows ÷ ingest time (ms) * 1000.

These are planned follow‑ups to the ingestion category inference system:

  • Immediate inference: provided category (if meaningful) → keyword map (longest first) → regex rules.
  • Consensus pass: vendor root dominance (configurable thresholds) fills unlabeled.
  • Telemetry: per-source counts (provided, keyword, regex, consensus, none).

Planned enhancements:

  • Dev audit panel (per-transaction inference method) with accept/reject feedback.
  • Custom user-defined rules persisted & merged at runtime.
  • Visual analytics (sparklines / bars) for inference distribution.
  • Historical telemetry aggregation across imports.
  • Tooltips/UI polish for method explanations.

🧪 Testing

Run tests (headless):

npm test

Tests currently cover:

  1. Transaction normalization edge cases (sign parsing, mixed formats)
  2. Strong transaction key formatting & balance inclusion
  3. Category inference (immediate + consensus)
  4. Strong key utilities (getStrongTransactionKey, getUniqueTransactions, normalization abs behavior)

Add new tests adjacent to related modules (e.g. src/ingest/__tests__/). Keep them fast & deterministic.

Demo / Data Generation TODOs

  • Demo CSV generator: Adapt IngestionBenchmark logic to let demo users generate realistic synthetic CSV files (seeded) including:
    • Recurring paychecks, rent, utilities, subscriptions, groceries, fuel, shopping
    • Configurable row count (e.g. 500 / 2k / 5k)
    • Optional duplicate + noise injection
    • Multi-account output (separate or combined)
    • Deterministic seed for reproducible walkthroughs
    • One-click “Generate & Open in Import Modal” action
    • Future: parameter presets (Light / Typical / Heavy spender)

About

Budgetizer is a privacy-aware personal finance app featuring a scenario-based budget planner, transaction imports from bank CSVs, and monthly tracking. Built with React + Vite, TS and AWS Amplify, it focuses on deterministic ingestion, idempotent imports, secure account handling, and clear monthly tracking across plans, actuals, and savings.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages