BillTracker is a self-hosted app for tracking recurring bills, monthly payments, due dates, categories, and personal bill history. It runs as a Node/Express server with a React frontend and stores data in SQLite. This product was produced with the assistance of AI. https://t1.scheller.ltd/
Go to file
null 59d32f4686 perf: composite DB indexes, notification N+1 batching, spending page double-fetch fix 2026-06-04 21:00:59 -05:00
.learnings v0.25.0: roadmap redesign, import CSRF fix, AdminDashboard removed 2026-05-11 21:42:36 -05:00
client perf: composite DB indexes, notification N+1 batching, spending page double-fetch fix 2026-06-04 21:00:59 -05:00
db perf: composite DB indexes, notification N+1 batching, spending page double-fetch fix 2026-06-04 21:00:59 -05:00
docs docs: update user-guide index with recent features (bank status, notifications, cash flow, batch import, merchant rules) 2026-06-04 03:14:54 -05:00
img v028.0 2026-05-16 10:56:56 -05:00
legacy push 2026-05-09 13:03:36 -05:00
middleware fix: login mode card update, OIDC service improvements, auth middleware refinements 2026-06-04 03:53:38 -05:00
public push 2026-05-09 13:03:36 -05:00
routes feat: bill rules manager page, merchant re-normalization, match suggestion scoring fix, cleanup pruning 2026-06-04 20:45:11 -05:00
scripts feat: merge pipeline workflow into bill-tracker (batch v0.36.0) 2026-06-03 20:28:37 -05:00
services perf: composite DB indexes, notification N+1 batching, spending page double-fetch fix 2026-06-04 21:00:59 -05:00
setup v0.22.3: fix ENV-seeded users skip first-login flow, add audit logging 2026-05-10 04:24:51 -05:00
tests chore: bump to v0.34.2, subscription badge fix on Tracker rows 2026-05-30 21:52:02 -05:00
utils push 2026-05-09 13:03:36 -05:00
workers fix: daily worker quarterly and annual bill cycle bugs 2026-06-03 21:55:15 -05:00
.dockerignore push 2026-05-09 13:03:36 -05:00
.env.example v0.35.0 2026-05-31 15:52:50 -05:00
.gitignore chore: roadmap audit v0.34.2 — remove completed FUTURE.md items, update partial statuses 2026-05-30 15:18:45 -05:00
.markdownlint.json v0.27.04 2026-05-15 01:36:56 -05:00
.rsyncignore initial commit 2026-05-03 19:51:57 -05:00
Dockerfile fix: Node 18->22 in Dockerfile for terser compat 2026-05-28 20:57:33 -05:00
FUTURE.md chore: reset tracked db file 2026-05-30 17:27:15 -05:00
HISTORY.md perf: composite DB indexes, notification N+1 batching, spending page double-fetch fix 2026-06-04 21:00:59 -05:00
NOTES.md push 2026-05-09 13:03:36 -05:00
README.md docs: update user-guide index with recent features (bank status, notifications, cash flow, batch import, merchant rules) 2026-06-04 03:14:54 -05:00
REVIEW.md push 2026-05-09 13:03:36 -05:00
SECURITY_AUDIT.md chore: seed demo data overhaul with modern bill data, security audit update (v0.34.2) 2026-05-30 22:05:42 -05:00
bill-tracker.code-workspace calendar 2026-05-04 13:14:32 -05:00
bills.db feat: reordering across management pages (Bills, Subscriptions, Categories, Snowball) — batch v0.34.1.2 2026-05-30 20:04:50 -05:00
components.json initial commit 2026-05-03 19:51:57 -05:00
deploy.sh initial commit 2026-05-03 19:51:57 -05:00
docker-compose.yml push 2026-05-09 13:03:36 -05:00
docker-entrypoint.sh initial commit 2026-05-03 19:51:57 -05:00
index.html refactor: component splits, PWA support, CommandPalette 2026-05-28 20:53:22 -05:00
jsconfig.json v0.27.04 2026-05-15 01:36:56 -05:00
package-lock.json feat: TOTP 2FA for login & profile setup flow 2026-06-04 04:10:14 -05:00
package.json feat: TOTP 2FA for login & profile setup flow 2026-06-04 04:10:14 -05:00
postcss.config.js initial commit 2026-05-03 19:51:57 -05:00
roadmap.md feat: Roadmap pulls from Forgejo issues (v0.35.1) 2026-05-31 19:37:01 -05:00
run-functional-test.js push 2026-05-09 13:03:36 -05:00
server.js feat: spending tracking page with category breakdowns 2026-06-04 04:31:25 -05:00
tailwind.config.js fix: GeorgiaDigits font-bleed fix (batch 0.33.8.2) 2026-05-29 18:42:11 -05:00
test-functional.js push 2026-05-09 13:03:36 -05:00
vite.config.mjs refactor: component splits, PWA support, CommandPalette 2026-05-28 20:53:22 -05:00

README.md

BillTracker

BillTracker logo

BillTracker is a private, self-hosted bill planning app for households and personal finance setups. It tracks recurring bills, monthly cash buckets, payments, due dates, categories, subscriptions, bank-synced transactions, imports, exports, backups, and debt payoff plans from one local installation.

It runs as a Node/Express app with a React/Vite frontend and stores data in SQLite. It is designed for people who want their bill data under their own control instead of inside a third-party budgeting service.

Demo Server: https://t1.scheller.ltd/
Username: guest · Password: guest123

Highlights

  • Monthly tracker with 1st-14th and 15th-31st bill buckets
  • Quick pay, skipped bills, monthly notes, amount overrides, and inactive bill history ranges
  • Period-aware balance cards, overdue command center, pin-due sorting, and compact desktop mode
  • Bills, categories, subscriptions, payment history, and custom billing schedules
  • SimpleFIN read-only bank sync with manual sync, auto-sync, transaction matching, and merchant rules
  • Historical payment import for merchant-rule matches, including month-crossing attribution fixes
  • Advisory non-bill filtering with a large pattern catalog for noisy bank transactions
  • Debt snowball and avalanche planning with APR math, projections, and amortization schedules
  • Calendar, summary, analytics, payoff simulator, and printable views
  • XLSX/CSV import, transaction CSV import, user SQLite export/import, Excel export, and admin backups
  • Local username/password auth with optional Authentik/OIDC SSO
  • Admin tools for users, backups, auth settings, bank sync, cleanup, status, and migrations
  • Email and push bill reminders through SMTP, ntfy, Gotify, Discord, or Telegram
  • Dark mode, PWA support, offline-ready shell, and keyboard command palette (Ctrl+K)

Screenshots

Screenshots below were refreshed from the linked demo server.

Login screen

Monthly tracker

Calendar money map

Analytics dashboard

Debt snowball planner

Data import and transaction matching

Subscription manager

Who This Is For

BillTracker is built for self-hosters who want a practical bill dashboard without sending personal finance data to a hosted budgeting product.

Good fit:

  • Home servers, NAS boxes, small VPS deployments, Portainer, or Docker Compose
  • Single-user or multi-user households
  • People who split monthly cash around the 1st and 15th
  • Users who want import/export and database backup control
  • Authentik/OIDC users who want optional SSO
  • SimpleFIN users who want read-only bank transaction syncing
  • People managing recurring services, debt, transactions, and monthly bills together

Not a replacement for:

  • Double-entry accounting
  • Investment tracking
  • Tax software
  • Direct bank connectivity without SimpleFIN

Bank sync requires a SimpleFIN Bridge account. BillTracker consumes SimpleFIN data; it does not host SimpleFIN server endpoints or connect directly to banks.

Quick Start With Docker

The included Compose file runs the published image on host port 3030 and stores persistent app data under /data inside the container.

docker compose up -d

Open:

http://localhost:3030

On first start, seed an admin account with:

environment:
  INIT_ADMIN_USER: admin
  INIT_ADMIN_PASS: change-this-password

Optional regular user seed:

environment:
  INIT_REGULAR_USER: regularuser
  INIT_REGULAR_PASS: changeme123

Passwords must be at least 8 characters. Remove or rotate first-run seed values after initial setup.

Persistent Data

For Docker, keep /data mounted. The container defaults to:

DB_PATH=/data/db/bills.db
BACKUP_PATH=/data/backups

Back up the mounted /data directory like you would any other sensitive financial data.

HTTPS And Cookies

Run BillTracker behind HTTPS for normal use. If TLS terminates at a reverse proxy, forward:

X-Forwarded-Proto: https

Recommended production posture:

HTTPS=true
COOKIE_SECURE=true
CSRF_SECURE=true
CSRF_SAME_SITE=strict

For plain HTTP development only:

COOKIE_SECURE=false
CSRF_SECURE=false

Leave CORS_ORIGIN unset for normal same-origin deployments. Set it only if the frontend and backend are intentionally served from different origins.

Node Install

Install dependencies:

npm install

Run the API and Vite UI for development:

npm run dev

Build and start production:

npm run build
npm start

The production server serves dist/ and listens on PORT, defaulting to 3000.

Useful scripts:

npm run dev:api
npm run dev:ui
npm run build
npm run check
npm test
npm start

npm run check runs backend CommonJS syntax checks and a Vite production build. npm test runs the Node test suite in tests/.

Product Map

Tracker

The Tracker is the main monthly view. It shows active bills for the selected month, grouped into 1st-14th and 15th-31st buckets.

You can record payments, quick-pay bills, skip a bill for the month, add monthly notes, override monthly amounts, reorder bills, and move between months. Summary cards show starting cash or bank-tracked balance, total paid, active-period balance, overdue amount, previous-month paid, and trend.

Compact tracker mode, available on wide screens, adds side-by-side buckets and quick subscription/autopay/2FA badges.

Bills And Categories

Bills store the recurring source data:

  • Name, expected amount, due day, category, and active state
  • Monthly, weekly, biweekly, quarterly, annual, and custom billing schedules
  • Autopay status, subscription metadata, two-factor badges, and display preferences
  • Monthly state such as skip flags, notes, and actual amount overrides
  • Optional debt fields such as balance, APR, minimum payment, and snowball flags
  • History ranges for inactive or past-only bills

Categories support custom colors, icons, descriptions, ordering, restore, and bill usage previews.

Bank Sync And Data Tools

SimpleFIN integration provides read-only bank syncing:

  • User-pasted SimpleFIN Bridge setup from the Data page
  • Manual "Sync Now" and background auto-sync
  • 90-day backfill support
  • Bank account selection for tracker balance projections
  • Merchant rules for matching transactions to bills
  • Historical import prompts when a new merchant rule finds prior payments
  • Late-attribution prompts or auto-fixes for payments that post just after month end

The Data page also handles:

  • XLSX and CSV spreadsheet import with preview
  • Transaction CSV import and column mapping
  • Transaction review, matching, ignoring, and status filters
  • User SQLite export/import
  • Excel workbook export
  • Import history with detailed stats
  • Demo data seeding for local trials

Subscriptions

Subscriptions are tracked as bill-backed recurring services. The page shows monthly and yearly impact, paused subscriptions, per-cycle amounts, subscription categories, and recommendations from recurring bank charges.

Snowball And Payoff

The Snowball page focuses on debt payoff planning:

  • Dave Ramsey-style snowball mode and avalanche comparison
  • Extra monthly payment settings
  • Minimum-only baseline vs. accelerated payoff projections
  • APR snapshots, amortization schedules, and payoff dates
  • Drag ordering, exclusion flags, readiness checks, and saved plans

The Payoff simulator can model a tracked debt or a custom outside debt without creating a new bill.

Calendar, Summary, And Analytics

Calendar shows bill due dates, paid dates, skipped bills, month progress, money markers, cash flow projections, and links back into Tracker or Snowball.

Summary handles income, starting amounts, planned expenses, paid status, monthly planning, reordering, and print-friendly output.

Analytics provides spending trends, expected vs. actual views, category breakdowns, pay-on-time heatmaps, forecasts, filters, and print output.

Admin And Status

Admin tools include user management, local/OIDC auth settings, SimpleFIN server enablement, backups, restore, cleanup, notification settings, status checks, and database migration operations.

The Status page surfaces application, database, runtime, daily worker, SimpleFIN, notifications, backups, maintenance, tracker, statistics, server clock, and recent-error health.

Background Workers

The daily worker handles:

  • Autopay marking
  • Bill due notifications
  • Session cleanup
  • Import history pruning
  • Backup scheduling
  • Bank sync scheduling

Worker status and recent activity are visible from Admin/Status.

Privacy Model

BillTracker is intended to run privately in your own environment.

  • Bill data stays in your SQLite database.
  • The app does not use third-party analytics, advertising, or telemetry.
  • Bank sync is optional and goes through the user's SimpleFIN Bridge account.
  • Login device details shown in Profile are visible to that user in the app UI.
  • Optional update checks are for software update availability, not bill-data collection.

Admins can manage users, reset passwords, configure authentication, and manage backups, but normal bill data is scoped to the signed-in user.

Authentication

BillTracker supports local username/password login by default. Admins can create users, reset passwords, promote or demote users, and activate or deactivate accounts.

Optional Authentik/OIDC login can be enabled from Admin. OIDC uses authorization code flow with PKCE, state and nonce validation, and openid-client token validation.

Important behavior:

  • Admin role is never granted by default through OIDC.
  • OIDC admin access requires a configured admin group.
  • Local login cannot be disabled unless OIDC is configured, enabled, and mapped to an admin group.
  • The default seeded admin is restricted to admin routes and cannot access personal tracker data.
  • OIDC provider name, issuer URL, client ID/secret, redirect URI, scopes, and admin group are configurable via Admin settings with environment variable fallbacks.

See Authentik-Integration.md for setup details.

Configuration

Most settings are configured in the web UI:

  • User settings: Settings and Profile
  • Server settings: Admin
  • Authentication settings: Admin
  • Notification settings: Admin and Profile
  • Backup and cleanup settings: Admin

Common environment variables:

PORT=3000
NODE_ENV=production
DB_PATH=/path/to/bills.db
BACKUP_PATH=/path/to/backups
INIT_ADMIN_USER=admin
INIT_ADMIN_PASS=change-this-password
INIT_REGULAR_USER=regularuser
INIT_REGULAR_PASS=changeme123
HTTPS=true
COOKIE_SECURE=true
CORS_ORIGIN=https://bills.example.com
CSRF_HTTP_ONLY=true
CSRF_SAME_SITE=strict
CSRF_SECURE=true
CSRF_COOKIE_NAME=bt_csrf_token
DATA_IMPORT_ENABLED=true

Worker settings:

WORKER_INTERVAL_MS=86400000
WORKER_AUTOPAY_ENABLED=true
WORKER_NOTIFICATIONS_ENABLED=true
WORKER_SESSION_CLEANUP_ENABLED=true
WORKER_IMPORT_CLEANUP_ENABLED=true

OIDC fallback environment variables are used when matching Admin database settings are blank:

OIDC_PROVIDER_NAME=authentik
OIDC_ISSUER_URL=https://auth.example.com/application/o/bills/.well-known/openid-configuration
OIDC_CLIENT_ID=<client-id>
OIDC_CLIENT_SECRET=<client-secret>
OIDC_TOKEN_AUTH_METHOD=client_secret_basic
OIDC_REDIRECT_URI=https://bills.example.com/api/auth/oidc/callback
OIDC_SCOPES="openid email profile groups"
OIDC_ADMIN_GROUP=bill-tracker-admins
OIDC_AUTO_PROVISION=true

Database-backed Admin settings take precedence over environment fallback values.

Secrets such as OIDC client secrets, SMTP passwords, push tokens, and SimpleFIN tokens are encrypted at rest. The app generates and stores its encryption key in the database on first use; no separate encryption-key environment variable is required.

Security Notes

  • Auth is required for user data routes.
  • Admin routes require an admin session.
  • User-owned bill, category, payment, import, export, transaction, and settings routes derive ownership from the authenticated session.
  • CSRF uses a double-submit cookie pattern. The SPA fetches /api/auth/csrf-token, stores the token in memory, and sends it as x-csrf-token on mutating requests.
  • The CSRF cookie defaults to HttpOnly; JavaScript does not need to read it through document.cookie.
  • Session cookies are HTTP-only and SameSite-protected.
  • Password changes rotate the current session and invalidate other sessions.
  • Rate limits protect local login, password changes, imports, exports, admin actions, backup actions, and OIDC routes.
  • Security headers include CSP nonces and standard hardening headers.
  • Audit logging records security-sensitive events such as login, logout, password changes, role changes, CSRF failures, and migration operations.

Backups and exports can contain sensitive financial data. The app writes SQLite backup files with restrictive permissions, but backup/export encryption is not implemented. Protect downloaded files and mounted volumes yourself.

Upgrading

For a Node install:

git pull
npm install
npm run build
npm start

Restart your process manager after building.

For Docker:

docker compose pull
docker compose up -d

If you build locally, rebuild the image and recreate the container.

The app initializes the schema and runs additive migrations on startup. The Docker entrypoint also runs scripts/migrate-db.js before starting unless:

RUN_DB_MIGRATIONS=false

Project Structure

bill-tracker/
|-- client/              # React app, routes, pages, components, hooks, and API client
|   |-- components/      # Shared UI, layout, admin, data, tracker, and snowball components
|   |-- contexts/        # React contexts
|   |-- hooks/           # Custom React hooks
|   |-- lib/             # Client utilities
|   `-- pages/           # Route pages
|-- db/                  # SQLite schema, migrations, and database helpers
|-- docs/                # Technical references and README screenshots
|-- legacy/              # Legacy static UI retained for reference
|-- middleware/          # Auth, CSRF, rate limit, security, and error middleware
|-- routes/              # Express API route handlers
|-- scripts/             # Utility, migration, deployment, and smoke-test scripts
|-- services/            # Business logic for bills, sync, auth, imports, status, workers, etc.
|-- workers/             # Background workers
|-- dist/                # Generated production build
|-- Dockerfile
|-- docker-compose.yml
|-- docker-entrypoint.sh
|-- server.js
`-- vite.config.mjs

Documentation

Known Limitations

  • Admin backups and user exports are not encrypted by the app.
  • Bank sync requires SimpleFIN; direct bank connections are not supported.
  • OIDC single logout is not implemented; users must log out from each device separately.
  • Rate limiting is in-memory, so counters reset on restart and are not shared across multiple app instances.
  • Multiple OIDC providers are not currently supported.
  • The XLSX parser dependency has known upstream security advisories; import routes are authenticated, file-size limited, and parse spreadsheet cells as data.

License

package.json declares the project license as ISC. No separate LICENSE file is included in this repository.