Designing QuidXy: a full-stack personal finance website


A QuidXy Field Note
Side project · May 31, 2026 · Self-hosted, internet-facing, single-user
Volume
01
Python Flask Plaid Cloudflare SQLite Security Full-Stack

I have always been interested in personal finance, and I'd been tracking everything in Excel for years. Eventually I decided to challenge myself and build a real platform. QuidXy is the result. It's live at quidxy.com, gated by my Google account, and nobody else can get in.

5
Weeks
54
Releases
16.3k
Lines of code
1
User · Me
01

The requirements

I like to stay ahead of my money. Excel got me most of the way for years, but it was manual entry, manual categorization, manual everything. I wanted to push myself and build something that did the hard work for me.

REQ 01
Zero subscription costs
I didn't want to pay $15 a month forever to look at my own data.
REQ 02
Fully secure
If it was going to touch real bank connections, it had to be done right.
REQ 03
Accessible from anywhere
A local-only dashboard wasn't going to cut it.
REQ 04
A well-rounded UI
Useful at a glance, not just a database with a CRUD form on top.
02

The architecture

The trust perimeter ends at my hardware. The dashboard is public at quidxy.com, but my home network has zero inbound ports. A Cloudflare Tunnel reaches outward; it never accepts an inbound connection. Cloudflare Access at the edge handles authentication via Google OAuth on an allowlist of exactly one email, mine. My Flask app then re-verifies Cloudflare's JWT against its JWKS on every request. Defense in depth, because the edge layer is configurable through a web dashboard and I don't want my data's security depending on me never misclicking a checkbox.

QuidXy system context diagram
Fig. 01 · System context · trust perimeter ends at my hardware

Plaid access tokens and the entire JSON blob of my financial state are Fernet-encrypted at rest, with a master key that lives outside the repo and is mode 600 on disk.

The security is only as good as your weakest link.

The full encryption story, the four SQL tables, the credential model, and what is encrypted versus not all deserve their own post.

03

The three surfaces

All three run off one Plaid integration, one transaction window, one transfer-exclusion rule, and one parent-category rollup. The same number can't be wrong in two places.

QuidXy Dashboard – widgets
QuidXy Dashboard – paycheck waterfall
QuidXy Dashboard – spending donut
Surface 01
Dashboard
Account balances with month-over-month deltas, a paycheck waterfall, upcoming expenses auto-detected by scanning recent transactions, bills with loan amortization, and a spending-by-category donut.
QuidXy Budget – sliders
QuidXy Budget – pacing
QuidXy Budget – categories
Surface 02
Budget
Per-category sliders rolled up to ~11 friendly parent buckets, with pacing feedback that tells me whether I'm on track for the month.
QuidXy Audit – monthly
QuidXy Audit – categories
QuidXy Audit – transactions
Surface 03
Audit
Monthly spend with a 3-month trailing average, projected month-end with a calendar of elapsed days, category drill-down, top merchants, and a searchable transaction log.
04

Getting Plaid to work

The proof of concept I started with was a smaller project called QuidDash. It relied on manually downloaded transaction files from each of my banks. That worked, but it wasn't practical and I couldn't see balances. I needed an aggregator.

I went to Plaid first. The thing that set Plaid apart for me was its OAuth flow: I could authorize my bank to share data with my app without my username and password ever passing through the middleman. That mattered.

My first attempt to connect failed. AI suggested my bank was only available to Plaid's Enterprise customers, so I went looking at alternatives and tried Teller.io. Teller's sandbox worked perfectly, but when I went to connect a real bank I learned how Teller actually works: it stores your bank login credentials on their servers. Username, password, sitting in their database. Hard no on requirement #2.

I went back to Plaid and started digging. Nothing in their docs said my bank was Enterprise-only. After a few days I found the real problem: when I ported the QuidDash configuration over, I was requesting both transactions AND investments from Plaid's link flow. My bank doesn't support investments, and Plaid filtered it out of the picker entirely rather than connecting with just what it did support. The AI's guess was wrong. The fix was a one-line change to the product list.

Once I got connected, it was game on.

05

On AI, on users, on what's next

Did I Use AI? Absolutely. AI was the typing hands. But the architectural decisions are mine: what to build, how the trust perimeter should work, what to encrypt, where to draw the lines between subsystems. There is a real difference between asking Claude to build a finance app and designing the system yourself, then using AI to implement it. This is the second thing.

Who else uses it? Just me. That is the point. QuidXy is built for one person, and almost every design decision flows from that constraint: no user management, no password reset flow, no concurrent-write handling. Single-user is a real, deliberate scope choice, not a limitation.

This is the first piece. The rest of the series goes deeper:

  1. 02
    The Plaid story
    The full QuidDash, Teller, and Cap One debugging chain.
  2. 03
    The security architecture
    How it stays reachable from anywhere with zero open ports. Three keys, one tunnel, one tripwire.
  3. 04
    The dashboard Coming soon
    Why drag-and-drop didn't last, and the upcoming-expenses pattern.
  4. 05
    The audit page Coming soon
    Inspired by Caleb Hammer's Financial Audit. Cashflow as a UI design problem.
  5. 06
    The budget Coming soon
    How the slider design replaced a kanban experiment.
Next in the series → Capital One wasn't blocking me. My config was.
End of Field Note 01