Skip to content

Latest commit

Β 

History

34 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation


Typing SVG



> INDEX.NAVIGATION β€” TABLE OF CONTENTS

# SECTION LINK
01 About the Project PROJECT.ABOUT
02 Feature Overview FEATURES.DECK
03 Technology Stack STACK.LOAD
04 Repository Layout PROJECT.STRUCTURE
05 Quickstart QUICKSTART.SETUP
06 Development Guide DEV.WORKFLOW
07 API Surface ROUTES.MAP
08 Security & Data SECURITY.MODEL
09 Roadmap ROADMAP
10 Contribution Guide CONTRIBUTION.PROTOCOL
11 Visual Identity DESIGN.AESTHETIC
12 License & Support SUPPORT.LICENSE

> PROJECT.ABOUT β€” WHAT IS SPENDLY?

Spendly is a personal expense tracking web application built with Flask. It helps you log expenses, spot spending patterns, and stay on budget β€” without the spreadsheet headache.

Users can register, sign in, add expenses with category, amount, date, and description, then visualise their spending through category breakdowns, monthly summaries, and date-range filters on a personal profile dashboard.

Built with Flask + Jinja2 for server-side rendering, SQLite for zero-config storage, and custom CSS with design tokens for a warm editorial aesthetic. Features automatic dark/light theme detection with a manual toggle, CSRF-protected forms, and Werkzeug password hashing.

Why Spendly?

PROBLEM SOLUTION
Spreadsheets are tedious and error-prone One-click expense logging with structured fields
No insight into spending habits Category breakdowns, recent transactions, and date filtering
Complex finance apps are overkill A clean, focused, personal tracker

> FEATURES.DECK β€” KEY CAPABILITIES

FEATURE DESCRIPTION STATUS
πŸ” User Accounts Register, sign in, sign out with Werkzeug-hashed passwords βœ… LIVE
πŸ’° Log Expenses Add any expense in seconds with all details βœ… LIVE
✏️ Edit Expenses Update any field of an existing expense βœ… LIVE
πŸ—‘οΈ Delete Expenses Remove expenses with CSRF-protected POST βœ… LIVE
οΏ½ Category Breakdown Per-category totals and share of spending βœ… LIVE
πŸ“ˆ Profile Dashboard Summary stats, recent transactions, category cards βœ… LIVE
πŸ—“οΈ Date Filtering Preset ranges (this month, 3 months, 6 months) + custom range βœ… LIVE
πŸ“Š Analytics Page Dedicated analytics view βœ… LIVE
πŸ›‘οΈ CSRF Protection Token-based form protection on every state-changing request βœ… LIVE
πŸŒ“ Theme Support Automatic dark/light detection + manual toggle βœ… LIVE
πŸ“± Responsive Design Works on desktop and mobile devices βœ… LIVE
πŸ§ͺ Test Suite pytest + pytest-flask covering every shipped feature βœ… LIVE

> STACK.LOAD β€” TECHNOLOGIES

LAYER TECHNOLOGY PURPOSE
Backend Flask 3.1.3 / Werkzeug 3.1.6 Routing, sessions, password hashing
Language Python 3.13 Core application logic
Storage SQLite (stdlib sqlite3) Local, zero-config database
Templating Jinja2 Dynamic HTML generation
Forms CSRF tokens + flask.session Cross-site request forgery protection
Frontend CSS3 + vanilla JS Design tokens, theme toggle
Testing pytest 8.3.5 + pytest-flask 1.3.0 Feature-level integration tests
Tooling uv Dependency + environment management

> PROJECT.STRUCTURE β€” REPO LAYOUT

expense-tracker/
β”œβ”€β”€ app.py                          ← Flask app, all routes, CSRF middleware
β”œβ”€β”€ pyproject.toml                  ← Project metadata + dependencies
β”œβ”€β”€ uv.lock                         ← uv lockfile for reproducible installs
β”œβ”€β”€ .python-version                 ← Python version pin (3.13)
β”œβ”€β”€ opencode.json                   ← OpenCode agent/command config
β”‚
β”œβ”€β”€ database/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ db.py                       ← init_db, seed_db, CATEGORIES, get_db
β”‚   └── queries.py                  ← CRUD + analytics SQL helpers
β”‚
β”œβ”€β”€ static/
β”‚   β”œβ”€β”€ css/
β”‚   β”‚   β”œβ”€β”€ style.css               ← Global styles + design tokens
β”‚   β”‚   └── landing.css             ← Landing page styles
β”‚   └── js/
β”‚       └── main.js                 ← Theme toggle + shared JS
β”‚
β”œβ”€β”€ templates/
β”‚   β”œβ”€β”€ base.html                   ← Shared navbar + footer
β”‚   β”œβ”€β”€ landing.html                ← Marketing landing page
β”‚   β”œβ”€β”€ register.html               ← Registration form
β”‚   β”œβ”€β”€ login.html                  ← Sign-in form
β”‚   β”œβ”€β”€ profile.html                ← User dashboard (stats, transactions, categories)
β”‚   β”œβ”€β”€ analytics.html              ← Analytics view
β”‚   β”œβ”€β”€ add_expense.html            ← Create-expense form (CSRF)
β”‚   β”œβ”€β”€ edit_expense.html           ← Edit-expense form (CSRF)
β”‚   β”œβ”€β”€ terms.html                  ← Terms and Conditions
β”‚   └── privacy.html                ← Privacy Policy
β”‚
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_backend_connection.py  ← Smoke tests for the app boot
β”‚   β”œβ”€β”€ test_date_filter.py         ← Profile date-filter helpers
β”‚   β”œβ”€β”€ test_06-date-filter-profile.py
β”‚   β”œβ”€β”€ test_07-add-expense.py      ← Add-expense flow (validation, CSRF, DB)
β”‚   β”œβ”€β”€ test_08-edit-expense.py     ← Edit-expense flow (ownership, validation)
β”‚   └── test_09-delete-expense.py   ← Delete-expense flow (CSRF, ownership)
β”‚
β”œβ”€β”€ seed_user.py                    ← Seed a demo user
β”œβ”€β”€ seed_expenses.py                ← Seed demo expenses
└── expense_tracker.db              ← Local SQLite database (gitignored)

> QUICKSTART.SETUP β€” GET RUNNING IN 5 MINUTES

Prerequisites

  • Python 3.13 β€” pinned via .python-version
  • uv β€” fast dependency manager (recommended)

Option A β€” With uv (recommended)

# 1. Clone the repo
git clone https://github.com/SalikAhmad702/expense-tracker.git
cd expense-tracker

# 2. Create venv and install dependencies
uv sync

# 3. Start the development server
python app.py

The database is initialised and seeded automatically on app boot β€” no manual step required.

Option B β€” With pip

# 1. Clone the repo
git clone https://github.com/SalikAhmad702/expense-tracker.git
cd expense-tracker

# 2. Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate        # On Windows: .venv\Scripts\activate

# 3. Install dependencies
pip install -e .

# 4. Start the development server
python app.py

Open http://localhost:5001 in your browser πŸŽ‰


> DEV.WORKFLOW β€” TESTS & COMMANDS

TASK COMMAND
Run the app python app.py
Run the full test suite pytest
Run a single test file pytest tests/test_07-add-expense.py
Initialise the database only python -c "from database.db import init_db; init_db()"
Seed the database only python -c "from database.db import seed_db; seed_db()"
Seed a demo user python seed_user.py
Seed demo expenses python seed_expenses.py
Sync dependencies uv sync
Lint / format (via opencode) configured in opencode.json

πŸ’‘ app.py calls init_db() and seed_db() on startup, so the database is ready the first time you boot the server.


> ROUTES.MAP β€” AVAILABLE ENDPOINTS

ROUTE METHOD DESCRIPTION STATUS
/ GET Landing page βœ… ACTIVE
/register GET, POST Create an account βœ… ACTIVE
/login GET, POST Sign in βœ… ACTIVE
/logout GET Sign out and clear session βœ… ACTIVE
/profile GET User dashboard (stats, transactions, categories, filters) βœ… ACTIVE
/analytics GET Analytics view βœ… ACTIVE
/expenses/add GET, POST Add a new expense (CSRF) βœ… ACTIVE
/expenses/<int:id>/edit GET, POST Edit an existing expense (CSRF) βœ… ACTIVE
/expenses/<int:id>/delete POST Delete an expense (CSRF) βœ… ACTIVE
/terms GET Terms and Conditions βœ… ACTIVE
/privacy GET Privacy Policy βœ… ACTIVE

All mutating endpoints are gated by @app.before_request CSRF middleware and require a signed-in user (except /register and /login). Expense endpoints enforce ownership β€” a user can only see and mutate their own rows.


> SECURITY.MODEL β€” SESSIONS, CSRF & DATA

Spendly takes a pragmatic, dependency-light approach to security:

CONCERN MITIGATION
Password storage werkzeug.security.generate_password_hash (PBKDF2 by default)
Password verification Constant-time check_password_hash on login
Session integrity Flask's signed session cookie; SECRET_KEY read from SPENDLY_SECRET_KEY env var
CSRF Per-session token generated by @app.before_request; validated on every POST
Cookie scope SESSION_COOKIE_SAMESITE = "Lax"
Authorisation Expense routes check expense.user_id == session["user_id"] and 404 otherwise
Input validation Server-side checks on amount (> 0, finite), date (YYYY-MM-DD), category (allow-list), description (≀ 200 chars)

πŸ” In production, set SPENDLY_SECRET_KEY to a long random value and run behind HTTPS.


> ROADMAP β€” FUTURE WORK

Shipped in v0.1 βœ…

  • User registration, login, logout with password hashing
  • Personal profile dashboard (stats, transactions, categories)
  • Add / edit / delete expenses with CSRF protection
  • Date filtering with presets + custom range
  • Analytics view
  • Dark / light theme with manual toggle
  • pytest + pytest-flask test suite per feature

Next up

  • CSV / Excel export of expenses
  • Search across expense descriptions
  • Monthly budget caps with progress bars
  • Chart.js visualisations on the analytics page
  • Password reset flow
  • Email verification on registration

Quality of life

  • Pagination on the transactions list
  • Bulk delete
  • Receipt attachments
  • Recurring-expense templates

> CONTRIBUTION.PROTOCOL β€” HOW TO HELP

Quick workflow

# Fork β†’ Branch β†’ Commit β†’ Push β†’ PR
git checkout -b feature/your-improvement
git add .
git commit -m "feat: describe your change"
git push origin feature/your-improvement

Guidelines

  • βœ… Follow the existing code style
  • βœ… Describe what your PR changes and why
  • βœ… Keep commits focused and atomic
  • πŸ§ͺ Run pytest before opening a PR β€” every shipped feature has a matching test file

> DESIGN.AESTHETIC β€” VISUAL IDENTITY

Spendly uses a warm editorial aesthetic with:

ELEMENT DETAILS
🎨 Color Palette Deep green accent (#1a472a), warm paper tones (#f7f6f3)
✍️ Typography DM Serif Display for headings, DM Sans for body text
πŸŒ— Theme Support Automatic dark/light mode detection + manual override
πŸ”· Icons Custom CSS icons with geometric shapes

> SUPPORT.LICENSE β€” STAR Β· REPORT Β· FOLLOW

License: This project is currently unlicensed β€” no formal license file yet. Please reach out before using it commercially.

Found a bug? Have a feature idea? Open an Issue on GitHub β€” every report makes Spendly better.

If this project helped you with expense tracking or Flask development, consider giving it a ⭐ β€” it keeps the development going!



Footer Typing





Β  Β  Β 



Β  Β 



⭐ Star this repo if it helped you with expense tracking and Flask development.

About

An expense tracking application built to manage and track personal expenses. Through this project, I learned how to effectively use AI-powered coding tools such as OpenCode and to improve my development workflow, understand codebases, implement features, and debug issues.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages