- Python 53.6%
- HTML 34.9%
- CSS 7.8%
- JavaScript 3.4%
- Dockerfile 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| app | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| favicon.ico | ||
| LICENSE.md | ||
| prompt.txt | ||
| README.md | ||
| requirements.txt | ||
| run.py | ||
| scheduler.py | ||
Bill Tracker
A modern, containerized web application for tracking recurring bills, utilities, subscriptions, and insurances with email reminders and calendar arithmetic.
Features
- Multi-user with Role Isolation:
- The first registered user automatically becomes the administrator.
- Strict privacy: users can only see their own bills; admins cannot view other users' bills directly.
- Alphanumeric usernames up to 48 characters, passwords up to 1024 characters.
- Passwords hashed securely with Argon2.
- Two-Factor Authentication (2FA): Time-based One-Time Passwords (TOTP) with scannable QR code generated offline.
- Account self-deletion: users can permanently delete their account from Account Settings after re-authenticating with their password; all their bills, payment logs, and verification records are removed (audit logs are retained). The last remaining administrator cannot be deleted, so the site is never left unmanaged.
- Persistent sessions: logins last 7 days and are automatically renewed on every site visit (sliding expiration), so users stay logged in across browser restarts.
- Flexible Bill Tracking:
- Track rent, utilities, internet, online subscriptions, car insurances, etc.
- Details: name, description, integer amount, payment method, payment link, recurrence.
- Smart Calendar Arithmetic: Recur monthly, every n months, or every n days. Month-end dates (e.g. January 31st) are clamped automatically to the last day of subsequent months (February 28th/29th) without losing original recurrence target days.
- Early Payments & Mark as Paid: Mark payments as paid early or on time. Next due date advances, reminders are suppressed, and an explicit payment log is maintained so accidentally clicked payments can be undone with one click.
- Automated Email Reminders:
- Dedicated background scheduler worker loop service in
docker-compose.yml. - Configurable multiple reminder thresholds per bill (e.g. on due date, 1 day before, 7 days before, 14 days before, or custom N days).
- Strict idempotency: database unique constraints guarantee no reminder is ever sent twice.
- All outgoing emails carry RFC 5322
Message-ID(domain derived from the sender address) andDateheaders for proper mail-flow handling and deliverability.
- Dedicated background scheduler worker loop service in
- Email Address Verification (Anti Open-Relay):
- Every new or changed contact email address must be verified by clicking a link with a high-entropy token (
secrets.token_urlsafe(32)). - No emails (including bill reminders) are ever sent to an unverified address.
- Verification links expire after a configurable TTL (default: 1 hour).
- Every sent verification link is recorded in the
email_verificationstable with a flag stating whether it was confirmed. - Anti-abuse rate limit: if a verification email to an address stays unconfirmed, the next one to the same address cannot be sent sooner than a configurable cooldown (default: 48 hours) after it — preventing the app from acting as an open SMTP relay.
- Every new or changed contact email address must be verified by clicking a link with a high-entropy token (
- Complete Audit Trail:
- Stores all site events (who did what) in the database indefinitely.
- Every sent email is recorded in the audit log.
- Viewable and searchable by administrators directly in the web UI.
- In-App Site Configuration:
- Configure SMTP host, port, credentials, security (TLS/SSL/none), application base URL, currency (default: CZK), and source link directly in the Admin UI.
- Configuration persists in
config.jsoninside the mounted data volume. - Includes SMTP test email utility.
- Clean UI & Modern Design:
- Vanilla JavaScript frontend with zero JavaScript dependencies.
- Responsive layout: desktop navbar collapsing to a mobile hamburger menu on narrow screens.
- Dark mode and Light mode with instant theme detection and persistence.
- Social media and link preview HTML meta tags on every page.
- Favicon served at
/favicon.ico. - Footer stating "vibecoded with gemini flash and kimi k3" with a link to source code.
Persistence & Volume Architecture
A single volume ./data is mounted to /app/data in the container.
What Persists in ./data:
app.db- SQLite database storing users, bills, payment logs, sent reminders, sent email verification links, and audit logs.config.json- In-app system configuration (SMTP settings, app URL, currency, source code URL, reminder dispatch hour, email verification TTL and resend cooldown).secret_key- Flask secret key, generated atomically usingsecrets.token_bytes(32)on initial deployment.
Everything else in the container is ephemeral and stateless.
Getting Started with Docker Compose
Prerequisites
- Docker (with Docker Compose v2)
Running the Application
-
Start the web app and dedicated reminder scheduler:
docker compose up -d --build -
Access the application in your browser:
http://localhost:5000(Or custom port via
PORT=5002 docker compose up -d) -
Register the first account to become the administrator.
-
Go to Site Settings (
/admin/settings) to configure your SMTP settings and application URL.
Email Verification & Anti Open-Relay Protection
To prevent the application from being abused as an open SMTP relay, no email is ever sent to an address that has not been verified by its owner:
- When a user provides an email address during registration, or sets/changes it
later in Account Settings, a verification email containing a link with a
high-entropy token (
secrets.token_urlsafe(32)) is dispatched immediately. - Clicking the link (no login required) proves ownership of the address. The verification record is marked as confirmed and bill reminders (as well as any other future emails) become deliverable to it.
- Every sent verification link is stored in the
email_verificationstable with aconfirmedcolumn stating whether it was confirmed. - Link validity: verification links expire after a configurable time (default: 1 hour).
- Resend cooldown: if a verification email to an address wasn't confirmed, the next verification email to that same address cannot be sent sooner than a configurable cooldown (default: 48 hours) after it.
- All parameters are configurable by the admin directly on the Site Settings
page (
/admin/settings) under Email Verification & Anti-Abuse, together with the Application Base URL used to build the verification links. - Users see their verification status in Account Settings, can re-send the verification email from there (subject to the cooldown), and see a dashboard warning while their address is unverified.
Production Database Migration (sqlite3, Debian, v3.46.1)
Note
Read this if you updated from commit
9c23dd7fd2or earlier
The new email_verifications table is created automatically on application
startup. The new email_verified column on the existing users table must be
added manually — run this on the production host when deploying (before or
right after restarting the containers with the new image):
sqlite3 data/app.db "ALTER TABLE users ADD COLUMN email_verified BOOLEAN NOT NULL DEFAULT 0;"
After the migration, existing users must verify their email address once
(reminders to them pause until they do). If you prefer to grandfather already
configured addresses as verified, run this optional statement instead right
after the ALTER TABLE:
# OPTIONAL: mark all existing non-empty addresses as already verified
sqlite3 data/app.db "UPDATE users SET email_verified = 1 WHERE email IS NOT NULL AND email != '';"
You can inspect the registry of sent verification links at any time:
sqlite3 data/app.db ".headers on" ".mode column" \
"SELECT id, email, created_at, expires_at, confirmed, confirmed_at FROM email_verifications ORDER BY id DESC LIMIT 20;"