← Back to All Projects

Expense Tracker Web Application

A full-stack, persistent financial logging application built with Python, Flask, and JSON storage engineered to process multi-byte local currency symbols across platforms.

What I Built

I built a full-stack personal finance web application using Python 3.12, Flask, Jinja2 templating, and CSS3. The application provides an interactive dashboard where users can submit and track income and expense transactions in real time with dynamic financial balance updates. All data persists locally in structured JSON format with full support for regional currency formatting, such as the Nigerian Naira (₦).

Problem

Many beginner-friendly personal finance tools operate solely as temporary command-line interface (CLI) tools, losing all transaction history once the terminal session closes. Additionally, standard file I/O operations on default Windows environments (cp1252 encoding) frequently crash when attempting to process non-ASCII Unicode currency symbols like the Naira (₦), rendering simple file persistence fragile and unreliable.

Solution

To solve this, I decoupled the CLI engine into a web application using Flask to handle HTTP routes and form submissions (/add). I implemented a persistent storage mechanism using Python’s json module, explicitly enforcing UTF-8 character encoding (encoding="utf-8") and ensure_ascii=False across all read and write file streams. This guarantees cross-session data retention and crash-free handling of multi-byte Unicode currency characters on any operating system.

Design Decisions

Tradeoffs

Challenges

When running the application on Windows, calling json.load() failed with a UnicodeDecodeError: 'charmap' codec can't decode byte 0x8f error as soon as transaction records contained the Naira (₦) symbol. The root cause was Python defaulting to the legacy Windows cp1252 character map. I resolved this by auditing all open() functions to pass encoding="utf-8" explicitly and passing ensure_ascii=False into json.dump(), ensuring characters are preserved as readable Unicode text rather than escaped binary sequences.

What I’d Improve

Demo

Live Demo Link

Source Code

GitHub Repository