Skip to content

Plan: Finances Phase D, native surface rebuild passes

URL: https://mkdocs.justinsforge.com/memory/plans/finances-phase-d-surface-passes-2026-07-06/

Date: 2026-07-06 Approved spec: Rebuild the 13 finance surfaces from their Flask-port skin (finances.css + Outfit) into CreatorTrack's native design system: components/ui primitives, app/theme.css tokens, inherited Geist/Geist Mono, charts through the locked wrapper components/Charts/Charts.tsx. One surface per pass; Justin approves each pass live on dev slot :3062 (branch feat/finances-surfaces, worktree ~/forge-suite-wt/feat/finances-surfaces, DB ct_feat_finances_surfaces) before it is committed. Data layer (lib/finance.ts loaders, write routes) stays; presentation is rebuilt. finances.css survives until the final surface pass so unmigrated tabs keep rendering. No new npm deps (shared cross-worktree node_modules). No merge to main, no deploy.

Amendment (2026-07-06, Task 0, commit adfd5d1): the standalone /finances door is RETIRED per Justin (clicks were escaping the workspace). The CreatorTrack finance node is the only door. Surfaces moved to components/finance/surfaces/*; /finances/* page routes are redirect shims (lib/finance-node.ts); all in-surface links are query-relative (?view=...). Surface passes verify on http://100.97.43.104:3062/justin/finances-5421?view=<surface> (not /finances/<surface>), and new links built in passes MUST be query-relative or use TxFilterBar's pathname-merge pattern. Out of scope: merge/deploy, new ingest logic, PNC SimpleFIN re-auth, legacy forge-finance-* unit and :8096 tunnel cleanup.

Workflow per surface task: implement, verify on http://100.97.43.104:3062/finances/<surface>, Justin approves in chat, then commit exactly feat(finances): <surface> iteration pass.

Progress (2026-07-06, session 2)

PHASE D COMPLETE (2026-07-06). Session 2 merged Tasks 0-3+9 + platform work to main (merge 3065fa7, deployed). Session 3 finished the rest on branch feat/finances-surfaces-2 (slot :3062): Tasks 4-8 + 10 (7a2e853..232ae8b), Task 11 Categorize (33174fc, incl. legacy-tid fix: queue now sends PG ids so single-row filing actually writes), Task 12 Receipts capture (2c7d3e9, new upload route + camera form, verified end-to-end), Task 13 Alerts + finances.css deletion (27ad172, alert_feed on top, pills/page-shell ported to native.css, orphan chart components removed, build gate passed, 13 tabs checked), Task 14 docs (this + module reference). Branch NOT yet merged; awaiting Justin's review + single merge. Continuation brief (patterns/gotchas): finances-phase-d-continuation-2026-07-06.

Task list

Task 0: Rebuild the finances shell (layout, sidebar, node-face chrome)

  • Files: app/finances/layout.tsx, components/finance/FinanceSidebar.tsx (or current sidebar path), components/apps/finance/FinanceApp.tsx, components/apps/finance/FinanceShell.tsx, components/apps/finance/finance.css
  • What: Drop the Outfit font, render surfaces inside native chrome on theme tokens; rebuild the sidebar/tab nav on components/ui (NavItem/Tabs); FinanceApp stops importing finances.css once all passes land (keep for now), swap fn-nav styling to tokens.
  • Verification: curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3062/finances returns 200; visual check on :3062.
  • Commit: feat(finances): native shell iteration pass

Task 1: Dashboard

  • Files: app/finances/page.tsx, new client components under components/finance/
  • What: Rebuild overview (net worth headline, spend chart via Charts.tsx, recent transactions, recurring, sync button) natively.
  • Verification: 200 on /finances; visual approval.
  • Commit: feat(finances): dashboard iteration pass

Task 2: Net Worth

  • Files: app/finances/networth/page.tsx, components/finance/*
  • What: Native rebuild of sections + NW grid; wire manual value edits to POST /api/finance/manual-values.
  • Verification: manual-value edit round-trips (row appears, page reflects new value); visual approval.
  • Commit: feat(finances): networth iteration pass

Task 3: Investments

  • Files: app/finances/investments/page.tsx, lib/finance-jobs/holdings.ts (readSsgaXlsx as_of parse, ~lines 319-325)
  • What: Native rebuild; fix SSGA as_of xlsx date-serial parse (guard "Date downloaded" row, UTC handling, reject non-date raw).
  • Verification: env -u PGPASSWORD PGDATABASE=ct_feat_finances_surfaces npx tsx smoke of readSsgaXlsx date branch; visual approval.
  • Commit: feat(finances): investments iteration pass

Task 4: Spending

  • Files: app/finances/spending/page.tsx, components/finance/*
  • What: Native rebuild (month nav, category breakdown, Charts.tsx area/donut, transaction drill-down).
  • Verification: 200 + visual approval.
  • Commit: feat(finances): spending iteration pass

Task 5: Budget

  • Files: app/finances/budget/page.tsx, components/finance/*
  • What: Native rebuild; wire targets/autoset UI to POST /api/finance/budgets (upsert, null/0 deletes).
  • Verification: setting a budget persists across reload in finance.budgets; visual approval.
  • Commit: feat(finances): budget iteration pass

Task 6: Business

  • Files: app/finances/business/page.tsx, components/finance/*
  • What: Restyle only (loader is @/lib/erpnext getBusinessData).
  • Verification: 200 + visual approval.
  • Commit: feat(finances): business iteration pass

Task 7: Recurring

  • Files: app/finances/recurring/page.tsx, components/finance/*
  • What: Native rebuild; keep recurring/action wiring; icons keyed by iconKey only.
  • Verification: recurring action round-trips; visual approval.
  • Commit: feat(finances): recurring iteration pass

Task 8: Cash Flow

  • Files: app/finances/cashflow/page.tsx, components/finance/*
  • What: Native rebuild of month flows on Charts.tsx.
  • Verification: 200 + visual approval.
  • Commit: feat(finances): cashflow iteration pass

Task 9: Accounts

  • Files: app/finances/accounts/page.tsx, components/finance/*
  • What: Native rebuild; manual-value entry point for source='manual' accounts (POST /api/finance/manual-values). Amendment (2026-07-06, Justin): add per-account profiles: clicking an account anywhere (dashboard buckets, accounts list) opens that account's profile in the Accounts surface (?view=accounts&acct=<id>): balance history, recent transactions for the account, metadata (institution, kind, scope, icon), manual-value editing for manual accounts.
  • Verification: manual account edit persists; account click-through from dashboard lands on the right profile; visual approval.
  • Commit: feat(finances): accounts iteration pass

Task 10: Transactions

  • Files: app/finances/transactions/page.tsx, components/finance/*
  • What: Native rebuild; edit/bulk-edit UI wired to POST /api/finance/transactions (category/scope/note/flags; route exists, no UI yet).
  • Verification: single + bulk edit persist (user_category=true on category edit); visual approval.
  • Commit: feat(finances): transactions iteration pass

Task 11: Categorize

  • Files: app/finances/categorize/page.tsx, components/finance/*
  • What: Native rebuild of queue UI; keep categorize/apply wiring.
  • Verification: apply round-trips; visual approval.
  • Commit: feat(finances): categorize iteration pass

Task 12: Receipts

  • Files: app/finances/receipts/page.tsx, new app/finances/receipts/upload/route.ts, components/finance/*
  • What: Native capture surface (phone upload to finance.receipts + image store; reconcile job lib/finance-jobs/receipts.ts already matches/attaches). Zero rows, clean slate.
  • Verification: upload a test image, row lands in finance.receipts, image served back via receipts/img; visual approval.
  • Commit: feat(finances): receipts iteration pass

Task 13: Alerts + legacy skin deletion

  • Files: app/finances/alerts/page.tsx, app/finances/layout.tsx, delete app/finances/finances.css, prune orphaned components/finance/* legacy components and unused lib/finance-ui.tsx exports, drop finances.css/Outfit imports in components/apps/finance/FinanceApp.tsx
  • What: Native rebuild with finance.alert_feed rendered at top; then delete the Flask skin entirely.
  • Verification: grep -r "finances.css\|Outfit" app/ components/ lib/ returns nothing; npx next build --webpack passes; all 13 tabs visual-checked.
  • Commit: feat(finances): alerts iteration pass + legacy skin removal

Task 14: Register and document

  • Files: /home/justinwieb/forge/memory/general/reference_creatortrack_finance_module.md, this plan (check off), new handoff if session ends mid-list
  • What: Update module reference (surfaces now native, receipts capture live), note Phase D complete through task N.
  • Verification: grep -q "Phase D" /home/justinwieb/forge/memory/general/reference_creatortrack_finance_module.md
  • Commit: (forge repo) docs(finances): Phase D surface passes recorded

[Claude Code, 2026-07-06]