Cory Copeland
Back to work

WorthOS

Active

An educational personal-finance organizer — organize income, expenses, debts, and goals, see key household-finance metrics, and generate a guardrailed AI-review prompt. Live public PWA plus a $29 offline Starter Kit.

  • Personal finance
  • Education
  • Self-hosted
  • PWA

Updated 2026-07-03

WorthOS

Overview

WorthOS is an educational personal-finance organizer — explicitly not a financial advisor. "Know what you're worth." A user manually enters their financial picture (income, expenses, savings, debts, investments, goals, assets) and gets back a live dashboard of household-finance metrics, cash-flow forecasts, and a debt-payoff projection — plus a copy-ready, guardrail-baked prompt they can paste into any AI chat tool for an educational review, never advice.

It started life as a LAN-only prototype called Money Map AI. It's now a live public PWA at worthos.corycopeland.dev, with a self-hosted cloud sync tier in progress and a $29 offline Starter Kit selling on Gumroad.

The problem

Personal-finance tools mostly sit at two extremes:

  • Connected-account trackers (Mint-style, or a real advisor app) want your bank credentials and, eventually, want to sell you a product.
  • A blank spreadsheet gives you total control and zero structure — most people never finish filling it in, let alone keep it updated.

There's no clean middle option for someone who wants an organized picture of their money — without linking accounts, without advice language, without a subscription just to see their own numbers. And increasingly, people ask AI chat tools financial questions with no structure behind the prompt, getting generic answers instead of ones grounded in their actual numbers.

Audience

  • Financial beginners overwhelmed by spreadsheets and jargon, who want a clear, organized picture of their money and better questions to bring to a qualified professional.
  • People wary of account-linking — WorthOS never asks for bank credentials; every number is typed in by the user and stored locally by default.
  • Casual AI-chat users who already ask ChatGPT or Claude about their finances and want that conversation grounded in real numbers instead of vague generalities.

Explicitly not for: DIY investors looking for buy/sell/hold recommendations. WorthOS won't give them one.

What I built

  • A manual intake wizard — profile, income, expenses, savings, debts, investments, goals, assets (with an optional link from an asset to the debt securing it).
  • A live dashboard — cash flow, savings rate, emergency-fund months, total debt, total investments, and a Total vs. Liquid net-worth split.
  • A cash-flow forecast — 6/12/24-month projection with recurring and one-off adjustments, charted.
  • A debt overview with an avalanche-vs-snowball payoff projection — explained, never recommended.
  • A goal tracker with progress, timelines, and a portfolio scenario projector.
  • Monthly review snapshots — a history view with a net-worth-over-time chart and category-trend sparklines.
  • A guardrailed AI-review prompt — the user's numbers summarized into a ready-to-paste prompt with the compliance guardrails built in, for use with any AI chat tool.
  • PDF export via the browser's print dialog — no PDF library shipped.
  • JSON backup/import. Everything free-tier is local-only, in localStorage — no account, no server round-trip.
  • A cloud tier (newer, still landing): magic-link auth and offline-first sync via a self-hosted Supabase instance, with a trial banner and subscription scaffolding. Stripe billing itself is designed but not wired yet — right now the cloud tier is live without payment enforcement.
  • A second distribution channel: a $29 one-time Starter Kit on Gumroad — a single-file, fully offline HTML build of the same tool, for people who don't want even a local web app talking to a server.

Product decisions

  • Compliance as architecture, not copy review. A formal banned-wording list (advisor, recommend, buy/sell/hold, guaranteed, "you should," etc.) is enforced by a recurring grep-based checklist across the whole codebase, with exactly two files allowed to contain those words — the disclaimer bar and the AI-prompt builder — and only to forbid them. The compliance posture is a build-time check, not a style guideline someone can forget.
  • A hard technical wall between the free/local and paid/cloud products. The offline Starter Kit build explicitly blanks the VITE_SUPABASE_* environment variables at build time, so cloud credentials can never leak into the distributable offline HTML — even as a cloud tier shipped for other users, the "your data never leaves your device" promise stays true for kit buyers by construction, not by promise.
  • Pre-sell before building the thing. The Starter Kit sales page shipped with a disabled CTA before a store link even existed, specifically to validate demand before writing the packaging, docs, or payment integration.
  • Entitlements derived server-side, never trusted from client state. The in-progress cloud paywall's is_entitled() Postgres function derives access from tier + stripe_status + trial_end rather than trusting a raw tier column, with every UI-level gate documented explicitly as "UX hints only" — real enforcement lives in Postgres. Notable because this discipline was designed before the billing tier that needs it actually shipped.
  • Atomic, symlink-swap deploys. Docker resolves a bind-mounted symlink at container start time, not per-request, so deploy.sh restarts (not recreates) the container after flipping a current symlink to a new release — with 5 releases retained on disk for instant rollback.

Technical architecture

  • Frontend: React 19 + Vite SPA, hand-written CSS design system (no Tailwind), local-first via localStorage (key moneyMapAI:v0.1, a naming fossil from the pre-rebrand era).
  • Deployment: self-hosted on LXC 209 (deployment-pve) behind Cloudflare Tunnel at worthos.corycopeland.dev. A separate demo instance at worthos-demo.corycopeland.dev runs the same build with data that resets on reload.
  • Cloud tier: a dedicated self-hosted Supabase instance on LXC 217 (worthos-db.corycopeland.dev) backs magic-link auth and offline-first sync; the Postgres entitlement function is designed, the Stripe checkout flow is not wired yet.
  • Distribution: the $29 Starter Kit is a single-file offline HTML build produced by npm run dist, packaged with plain-English docs (quick start, safe-use guide, an 8-prompt pack, a monthly-review checklist) and sold via Gumroad.

Design and brand

WorthOS started on a dark navy theme and moved to a calm, light, trust-first palette — off-white surfaces, deep-slate text, a desaturated teal accent — re-derived at the token level so every screen cascaded over in one pass. The most recent work has been almost entirely visual polish: soft clay-morph 3D illustrations (generated with fal.ai FLUX.2, WebP-optimized), an animated landing hero, and Manrope as the display typeface — no product-scope change, just a more premium, less spreadsheet-y feel.

Current status

  • Live public PWA at worthos.corycopeland.dev — not a LAN prototype. v0.1 through v0.3 shipped: intake, dashboard, forecasting, debt payoff, goal tracking, snapshot history.
  • $29 Starter Kit live on Gumroad, with real pre-sell validation before the payment integration was built.
  • Cloud foundation live (magic-link auth, offline-first sync via self-hosted Supabase) — but the Stripe billing gate is still "planned, not wired," so cloud sync is currently accessible without payment enforcement.

What I would do next

  • Wire the Stripe billing gate — the entitlements plumbing (is_entitled(), UI-hint-only gates) is already designed for this, so it's the one clear blocking step before the cloud tier can charge anyone.
  • Phase 1: in-app AI analysis using the same guardrailed prompt logic, without leaving the app.
  • Monthly email digest, household/couples mode (Cloud+), an advisor-share report, and scenario modeling — the roadmap phases after billing lands.

Proof