Palette
← Back to projects
Personal

FinLens

A deployed, self-hosted household finance tracker with PDF statement imports, manual transaction review, spending dashboards, central SSO, and a read-only MCP server.

TypeScript logo
React logo
Vite logo
Tailwind CSS logo
Hono logo
PostgreSQL logo
Drizzle logo
Better Auth logo
MCP logo
Docker logo
GitHub Actions logo
Caddy logo

Overview

FinLens is a deployed, self-hosted personal finance tracker built for household use as a private alternative to managing financial data in Excel. It combines a React dashboard, PDF statement imports, manual transaction review, category management, a Postgres-backed API, central Pior Labs authentication, and an internal read-only MCP server for conversational finance queries.

What I Built

  • I built the React 19 and Vite web application for reviewing household finances, including monthly dashboard summaries, category breakdowns, top merchants, transaction filtering, a review queue, statement history, responsive navigation, and purpose-built empty, error, and loading states.
  • I implemented PDF statement uploads that extract transaction data, persist uploaded files privately, create statement records, and insert transactions into a review queue.
  • I built the manual categorization workflow for transactions, including category creation, editing, favorites, colors, fallback handling, and review status updates.
  • I implemented the Hono API, Drizzle schema, and PostgreSQL persistence layer, then integrated Better Auth with the central Pior Labs OAuth 2.1/OpenID Connect service while preserving local sessions and linked user records.
  • I built a seven-tool read-only MCP server for spending summaries, month comparisons, transaction listing and search, category breakdowns, top merchants, and merchant-level spending queries, with validated inputs and structured outputs over stdio.

How It Works

  • Users reach the same private hostname over the trusted local network or Tailscale, authenticate through the central Pior Labs identity service, and enter a responsive dashboard built with the shared Pior Labs design system.
  • Statement PDFs pass through the authenticated Hono API, which stores uploads privately, parses transactions into PostgreSQL, and serves the review, categorization, statement, and dashboard workflows used by the React application.
  • The pnpm monorepo centralizes contracts, date and money helpers, the Drizzle schema, and finance queries; Docker runs the web, API, and MCP services, Caddy routes browser traffic, and the MCP server remains internal on stdio with no published network port.

Technical Highlights

  • Manual review over guessed categorization: I intentionally kept categorization human-controlled because merchant names alone are not accurate enough for household finance decisions, especially for mixed purchases like grocery and household items from the same store.
  • Central authentication without losing local history: Better Auth delegates sign-in to the Pior Labs OAuth 2.1/OpenID Connect service and links verified identities to existing local users so historical finance records remain attached to the same accounts.
  • Shared data model, seven conversational tools: The database package gives the API and MCP server one Drizzle schema, while its bounded analytics query layer powers seven read-only MCP tools that return text and structured data over private stdio transport without publishing another service port.
← Back to projects