17 KiB
Bill Tracker — Future Improvements
This document tracks potential future enhancements for Bill Tracker.
Last Updated: 2026-05-11
Current Version: v0.24.3
How to Use This Document
This file is a living document. Agents should:
- Read this file before proposing changes
- Add new recommendations with priority levels
- Never add completed items — move those to HISTORY.md instead
- Reference this file when dispatching improvement tasks
- Only Ripley can remove items from this list. Notify Ripley if something neds to be removed.
Priority Format
All items must include the priority emoji in their heading, matching the section they belong to:
| Priority | Emoji | Heading Format |
|---|---|---|
| CRITICAL | 🔴 | ### 🔴 Title — CRITICAL |
| HIGH | 🟠 | ### 🟠 Title — HIGH |
| MEDIUM | 🟡 | ### 🟡 Title — MEDIUM |
| LOW | 🔵 | ### 🔵 Title — LOW |
| NICE TO HAVE | 💭 | ### 💭 Title — NICE TO HAVE |
Items are grouped under their priority section heading (## 🔴 CRITICAL, ## 🟠 HIGH, etc.) and sorted most-impactful-first within each tier.
Pending Recommendations
🔴 Import XLSX Dual-Column Layout Not Parsed — CRITICAL
Priority: CRITICAL
Added: 2026-05-11 by Ripley
Description:
The real-world spreadsheet (backups/monthly bills.xlsx) uses a dual-column layout — each monthly sheet is split into two halves representing two payment periods:
- Left half (columns A-E): Bills due around the 1st of the month
- Right half (columns G-K): Bills due around the 15th of the month
Each half has its own Due Date | Bill | Amount | Paid Date | Date Cleared headers. The current parser only detects headers in the first row and processes columns linearly, so it captures the 1st-of-month bills but completely misses all 15th-of-month bills (roughly half the data).
Example from Apr 2026 sheet:
Left (1st): auto | Roadrunner ATV | $225.64 | paid 2026-03-01 (due ~1st)
Right (15th): | Amazon chase card | $366 | paid 2026-04-20 (due ~15th)
Rationale:
- This is the actual production spreadsheet the app needs to import
- ~100 monthly sheets spanning 2017–2026, each with two payment periods
- The 15th-of-month bills (credit cards, loans, subscriptions) are completely lost during import
- Without dual-column support, the import feature is broken for real data
- The "1st vs 15th" split is semantically meaningful — it maps to
due_dayin the bill model
Additional Issues in This Spreadsheet:
- Rows 1–2 contain paycheck/leftover summary data, not bills — parser must skip these
- Non-numeric amount values: "double pay", blank amounts, "past due" — need graceful handling
- Due date column contains non-date values: "auto" (autopay indicator), "24th" (day-of-month shorthand), account numbers like "9522104"
- Some sheets have slight column layout variations (extra column, merged cells)
- Sheet names have typos: "Januaru 2021", "Novevmber 2019", "Febuary 2023" — parser already handles these
- 3 non-month sheets ("2018 taxes", "debt totoals", "home ownership expenses") should be skipped — already handled by
NON_MONTH_SHEET_RE - "auto" in the Due Date column is an autopay flag, not a date — should be detected as a label, not parsed as a date
Implementation Notes:
- Modify
spreadsheetImportService.jsto detect dual-column headers in a single sheet row - When two sets of bill headers are found (A-E and G-K), process each half independently
- Left half rows should default
due_dayto ~1, right half rows should defaultdue_dayto ~15 - Each half produces its own set of rows with the same sheet name/month context
- Handle non-numeric amount cells gracefully (null amount, "double pay" as a note/label)
- "auto" in Due Date column → set
autopaylabel/detected label, don't try to parse as date - "24th" in Due Date column → parse as day-of-month (24)
- Skip rows where the bill name cell is blank AND the amount cell is blank or non-numeric
- Filter out paycheck/summary rows (Row 1: Paycheck amounts, Row 2: Left Over calculations)
- The
backups/monthly bills.xlsxfile is inbackups/(gitignored) for testing - Files to modify:
services/spreadsheetImportService.js, possiblyroutes/import.js - Estimated effort: 4-6 hours
🔴 No Confirmation Before Destructive Actions — CRITICAL
Priority: CRITICAL
Added: 2026-05-11 by Ripley
Description: Deleting a bill or payment is one click with no confirmation dialog and no undo. For a financial app, accidental data loss destroys user trust.
Rationale:
- Bills and payments represent real financial commitments and history
- No "are you sure?" prompt before delete
- No undo mechanism, no soft delete, no recovery
- One misclick = gone forever — unacceptable for financial data
- This is a trust and data integrity issue, not a UX nicety
Implementation Notes:
- Add confirmation dialog to all delete actions (bills, payments, categories)
- Consider soft delete (
deleted_atcolumn) with a grace period before permanent removal - Add undo toast after delete that allows restoration within a short window
- Files to modify:
BillModal.jsx,BillsTableInner.jsx,TrackerPage.jsx,CategoriesPage.jsx - Estimated effort: 3-4 hours
🟠 HIGH
🟠 No Search or Filter Across Bills — HIGH
Priority: HIGH
Added: 2026-05-11 by Ripley
Description: No way to find a bill by name, category, or amount. Users must scroll through the entire list to find anything. Every bill tracker on the market has instant search.
Rationale:
- With dozens of bills, scrolling is slow and error-prone
- No search bar on BillsPage, TrackerPage, or CalendarPage
- Can't filter by category, amount range, autopay status, or billing cycle
- Can't quickly find "where's that electric bill?" without visually scanning
- Table stakes for any list-based app
Implementation Notes:
- Add search input to BillsPage (filter by name, category, notes)
- Add filter chips/dropdowns for category, billing cycle, autopay, active/inactive
- Add search to TrackerPage (filter visible rows by bill name)
- Consider a global
Cmd+K/Ctrl+Kcommand palette for instant bill lookup - Files to modify:
BillsPage.jsx,TrackerPage.jsx,client/api.js - Estimated effort: 6-8 hours
🟠 No Visible Overdue Indicators — HIGH
Priority: HIGH
Added: 2026-05-11 by Ripley
Description:
Overdue bills aren't visually flagged on the tracker. An unpaid past-due bill looks the same as one not due yet. The notify_overdue setting exists but there's no visual distinction in the UI.
Rationale:
- The whole point of a bill tracker is to not miss payments
- Overdue bills should be impossible to overlook — red highlight, badge count, sticky alert
- Data model supports overdue notifications but tracker grid shows no overdue state
- Users scanning the tracker won't notice a missed bill buried in the list
Implementation Notes:
- Add overdue detection: if today > due date for current month and no payment logged, mark overdue
- Red/amber background on overdue tracker rows
- Overdue count badge in Sidebar next to Tracker nav link
- Optional: overdue summary banner at top of TrackerPage
- Files to modify:
TrackerPage.jsx,Sidebar.jsx,routes/tracker.js(add overdue count to API response) - Estimated effort: 4-6 hours
🟠 Filtered Export for Reports — HIGH
Priority: HIGH
Added: 2026-05-11 by Ripley (upgraded from LOW)
Description: No way to export filtered data (e.g., "all bills in category X for last 6 months", "everything overdue in 2026"). Export dumps everything or nothing.
Rationale:
- Exporting filtered reports is core functionality for a bill tracker, not a nice-to-have
- Users need "all Q1 utility bills" or "overdue payments this year" for reconciliation and tax prep
/api/export/user-excelexports everything — no query params for date range, category, or status- This is how people actually use financial data outside the app
Implementation Notes:
- Add query params to export endpoints:
category_id,start,end,status(paid/unpaid/overdue) - Files to modify:
routes/export.js,client/pages/DataPage.jsx - Estimated effort: 6 hours
🟡 MEDIUM
🟡 No Bill Template / Duplicate Bill — MEDIUM
Priority: MEDIUM
Added: 2026-05-11 by Ripley
Description: Creating a new bill means filling 10+ fields every time. No way to duplicate an existing bill or use a template. If you have 3 utilities from the same provider, you're retyping everything.
Rationale:
- Bill creation has many fields (name, category, due day, amount, autopay, website, account, 2FA, notes)
- Common pattern: similar bills from same provider or same category with slight variations
- "Duplicate bill" is table stakes in every bill tracker
- Reduces friction and errors during bill setup
Implementation Notes:
- Add "Duplicate" button/action on each bill row and in BillModal
- Pre-fill all fields from source bill, clear
nameand set "(Copy)" suffix - Files to modify:
BillModal.jsx,BillsPage.jsx,routes/bills.js(POST endpoint can acceptsource_bill_idparam) - Estimated effort: 3-4 hours
🟡 No Partial Payment Support — MEDIUM
Priority: MEDIUM
Added: 2026-05-11 by Ripley
Description:
The UI only supports logging a single payment per bill per month. The payments table schema supports multiple entries per bill, but the frontend doesn't surface this. Split payments (half now, half later) can't be tracked.
Rationale:
- Many bills get paid in installments (medical, tuition, large utilities)
- Payment plan arrangements require tracking multiple payments against one bill
- The data model already supports it — it's purely a frontend gap
- Without this, users either over-record or under-record partial payments
Implementation Notes:
- Show payment history per bill in tracker (expandable row or modal tab)
- Allow "Add partial payment" with amount + date, summing to bill total
- Display remaining balance on partially-paid bills
- Files to modify:
TrackerPage.jsx,routes/payments.js, possiblyBillModal.jsx - Estimated effort: 6-8 hours
🟡 No Year-Over-Year Comparison in Analytics — MEDIUM
Priority: MEDIUM
Added: 2026-05-11 by Ripley
Description: Analytics shows monthly trends within a single year but there's no "this month vs same month last year" view. Users can't evaluate whether spending is improving.
Rationale:
- The whole point of analytics is answering "am I doing better or worse?"
- Within-year trends are useful but don't show long-term improvement
- Comparing April 2026 to April 2025 is the natural question people ask
- Available in every competing app (YNAB, Monarch, etc.)
Implementation Notes:
- Add YoY comparison toggle or tab to AnalyticsPage
- Query: same month range across current and previous year, diff the totals
- Show percentage change and absolute change per category
- Files to modify:
AnalyticsPage.jsx,routes/analytics.js(add YoY endpoint or params) - Estimated effort: 6-8 hours
🟡 No Bulk Actions — MEDIUM
Priority: MEDIUM
Added: 2026-05-11 by Ripley
Description: Every action is one-at-a-time. Can't select multiple bills and mark them paid, skip them for a month, or change their category.
Rationale:
- End-of-month reconciliation means marking many bills as paid in a row
- Category reorganization affects multiple bills at once
- Skipping seasonal bills for summer/winter requires individual clicks
- Bulk actions are standard in any list-based management UI
Implementation Notes:
- Add checkbox selection to BillsPage rows (with select-all toggle)
- Bulk action toolbar: Mark Paid, Skip This Month, Change Category, Delete
- Backend: batch endpoints or loop with progress indicator
- Files to modify:
BillsPage.jsx,BillsTableInner.jsx,routes/bills.js,routes/payments.js - Estimated effort: 8-10 hours
Architecture: Business Logic Mixed with Route Handlers
Priority: MEDIUM
Added: 2026-05-08 by Neo
Description: Many routes contain business logic that should be extracted to service layers.
Rationale:
bills.jscontainsparseDueDay(),parseInterestRate()— validation logictracker.jscontains date/range calculations that are reused across routesadmin.jshas complex OIDC config building mixed with routinganalytics.jshas complex date-building logic (buildMonths,monthKey, etc.)
Implementation Notes:
- Files to modify: Multiple route files + new service files in
/services/ - Estimated effort: 8 hours
- Proposed structure:
/services/billsService.js /services/trackerService.js /services/analyticsService.js /services/authService.js (existing) /services/oidcService.js (existing) /services/cleanupService.js (existing) - Route handlers should call services, not contain business logic
🔵 LOW
🔵 Payment Method Tracking and Summary — LOW
Priority: LOW
Added: 2026-05-11 by Ripley
Description:
The payments table has a method column (free-text) but no way to see "how much did I pay via autopay vs manual vs credit card this month." No standardized method options, no summary.
Rationale:
- Useful for reconciling credit card statements vs bank statements
- Autopay vs manual tracking helps identify bills that should be switched to autopay
- Payment method breakdown is a common analytics view in financial apps
- Current
methodfield is unvalidated free text — no consistency
Implementation Notes:
- Standardize payment methods: enum or controlled list (autopay, bank_transfer, credit_card, check, cash, other)
- Add payment method breakdown to analytics or summary page
- Files to modify:
routes/payments.js,AnalyticsPage.jsxorSummaryPage.jsx, schema migration for method validation - Estimated effort: 4-6 hours
🔵 No Keyboard Navigation or Shortcuts — LOW
Priority: LOW
Added: 2026-05-11 by Ripley
Description:
Only a skip link exists for keyboard accessibility. No Cmd+K to find a bill, no Esc to close modals, no arrow keys to navigate the tracker grid. Power users and accessibility need keyboard support.
Rationale:
- Keyboard accessibility is required for WCAG compliance
- Power users navigate faster with keyboard shortcuts
- Modal dismiss on
Escis expected behavior in any modern app - Command palette (
Cmd+K) pairs with the search feature (also missing)
Implementation Notes:
Esccloses any open modal/dialogCmd+K/Ctrl+Kopens search/command palette- Arrow keys navigate tracker rows when grid is focused
- Tab order follows logical flow, not DOM order
- Files to modify:
App.jsx,BillModal.jsx,TrackerPage.jsx, all dialog components - Estimated effort: 6-8 hours
Add comprehensive unit and integration tests
Priority: LOW
Added: 2026-05-08 by Scarlett
Description:
Currently no unit tests exist for components or hooks. The only testing appears to be functional tests in test-functional.js. Component-level testing is missing.
Rationale: Code quality and maintainability. Unit tests catch regressions and document component behavior. Bill Tracker has complex business logic (bill calculations, monthly state, analytics) that should be tested.
Implementation Notes:
- Set up Jest + React Testing Library
- Test key components: BillModal, TrackerPage row, BillsTableInner
- Test hooks: useAuth, custom form hooks
- Test utility functions in
client/lib/utils.js - Consider vitest for faster test execution
- Add CI integration for test execution
- Files likely to be modified: Add
client/test/directory, addjest.config.cjs - Estimated effort: 8-12 hours for baseline coverage
Features: Missing Bill Grouping and Reorganization API
Priority: LOW
Added: 2026-05-08 by Neo
Description: No way to reorder bills, drag-and-drop, or group by custom criteria.
Rationale:
billstable hasdue_dayordering but no manual sort order- Frontend likely orders by
due_dayonly - Users cannot create bill groups or categories for bills
- No way to mark bills as "hidden" or "archived" without deactivating
Implementation Notes:
- Files to modify:
/home/kaspa/.openclaw/Projects/bill-tracker/db/schema.sql,/routes/bills.js - Estimated effort: 6 hours
- Add:
sort_ordercolumn to bills table (default NULL, ordered first by sort_order then due_day)PUT /api/bills/reorderendpoint accepting{bill_id: new_index}PUT /api/bills/:id/archivedto soft-dearchive (setsarchivedflag)
💭 NICE TO HAVE
Add consistent form state management pattern
Priority: MEH
Added: 2026-05-08 by Scarlett
Description:
Form state management is inconsistent across components. Some use useState for each field, others use form libraries. Validation patterns vary.
Rationale: Consistency and maintainability. A consistent pattern makes it easier to add new forms and reduce bugs.
Implementation Notes:
- Consider react-hook-form for complex forms
- Create reusable form field components (InputField, SelectField, etc.)
- Standardize validation approach
- Files likely to be modified:
client/components/*.jsx - Estimated effort: 4-6 hours for migration