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
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