A full-stack expense tracking application with glassmorphism UI, real-time analytics, and comprehensive testing. Built with FastAPI backend serving both the REST API and the vanilla JavaScript frontend as a single unified server.
- Glassmorphism UI β Modern frosted glass design with animated gradients
- Expense Management β Add, view, filter, and delete expenses with category tracking
- Analytics Dashboard β Visual category breakdown with date range analysis
- RESTful API β FastAPI backend with Pydantic validation
- MySQL Database β Persistent storage with parameterized queries
- Comprehensive Testing β 41+ test cases covering all functionality
- Logging β File and console logging for debugging
- Single Server β Frontend served as static files from the FastAPI backend
Live URL: http://<elastic-beanstalk-url>
GitHub Push
β
GitHub Actions (CI/CD)
β Deploy
Elastic Beanstalk (Python + Docker)
β connects
RDS MySQL (managed database)
β fetches credentials
AWS Secrets Manager (DB credentials)
| Service | Purpose |
|---|---|
| Elastic Beanstalk | Hosts the FastAPI application (auto-scaling, load balancing) |
| RDS MySQL | Managed relational database (automated backups, high availability) |
| Secrets Manager | Stores database credentials securely (no .env files on server) |
| IAM Role | Grants Beanstalk permission to access Secrets Manager |
| GitHub Actions | Auto-deploys on every push to main branch |
1. Create RDS MySQL instance
AWS Console β RDS β Create database β MySQL
- Template: Free tier
- DB identifier: expense-manager-db
- Username: admin
- Enable public access: No (private within VPC)
2. Store DB credentials in Secrets Manager
# AWS Console β Secrets Manager β Store a new secret
# Secret name: expense-manager/db-credentials
# Keys: DB_HOST, DB_USER, DB_PASSWORD, DB_NAME3. Create IAM Role for Elastic Beanstalk
IAM β Roles β Create role β EC2
Attach: SecretsManagerReadWrite
Name: expense-manager-eb-role
4. Create Elastic Beanstalk environment
Elastic Beanstalk β Create environment β Web server environment
- Platform: Python or Docker
- Upload your application code as a zip
- Attach IAM instance profile: expense-manager-eb-role
5. Set environment variables in Beanstalk
Configuration β Software β Environment properties
DB_HOST, DB_USER, DB_PASSWORD, DB_NAME
(pulled from Secrets Manager at startup)
6. GitHub Actions CI/CD
Add these secrets in GitHub β Settings β Secrets β Actions:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYEB_APP_NAME- Elastic Beanstalk application nameEB_ENV_NAME- Elastic Beanstalk environment name
Every push to main automatically packages and deploys the application.
# Pause: Beanstalk Console β Environment β Actions β Terminate environment
# Full cleanup: Terminate environment β Delete application β Delete RDS instance β Delete secret
expense-manager/
βββ backend/
β βββ server.py # FastAPI application (serves API + frontend)
β βββ db_helper.py # Database operations
βββ frontend/
β βββ index.html # Main HTML structure
β βββ style.css # Glassmorphism styling
β βββ app.js # JavaScript logic (uses relative API URLs)
βββ tests/
β βββ backend/
β βββ test_db_helper.py # Database tests
β βββ test_server.py # API endpoint tests
βββ logs/ # Application logs
βββ schema.sql # Database setup script
βββ Dockerfile # Container configuration
βββ requirements.txt
βββ pyproject.toml # Pytest configuration
- Python 3.8+
- MySQL 8.0+
The project includes a schema.sql file for easy database setup. Run it using:
mysql -u root -p < schema.sqlOr manually create the database:
CREATE DATABASE expense_manager;
USE expense_manager;
CREATE TABLE expenses (
id INT AUTO_INCREMENT PRIMARY KEY,
expense_date DATE NOT NULL,
category VARCHAR(100) NOT NULL,
notes TEXT,
amount DECIMAL(10, 2) NOT NULL CHECK (amount > 0),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_expense_date (expense_date),
INDEX idx_category (category)
);- Clone the repository
git clone <your-repo-url>
cd expense-manager- Set up MySQL database
mysql -u root -p < schema.sql- Install Python dependencies
pip install -r requirements.txt- Configure environment variables
cp .env.example .envEdit .env with your MySQL credentials:
DB_HOST=localhost
DB_USER=root
DB_PASSWORD=your_password_here
DB_NAME=expense_manager- Run the server (serves both API and frontend)
uvicorn backend.server:app --host 0.0.0.0 --port 8000Open http://localhost:8000 β the frontend loads automatically.
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
Serves the frontend UI |
GET |
/health |
Health check |
GET |
/expenses/{date} |
Get expenses for a date |
POST |
/expenses/{date} |
Add expenses for a date |
DELETE |
/expenses/{date} |
Delete expenses for a date |
GET |
/summary?start_date=X&end_date=Y |
Get expense summary |
Add Expense:
curl -X POST "http://localhost:8000/expenses/2025-12-07" \
-H "Content-Type: application/json" \
-d '[{"category": "Food", "notes": "Lunch", "amount": 250.50}]'Get Summary:
curl "http://localhost:8000/summary?start_date=2025-12-01&end_date=2025-12-07"
Expense-Manager Application Interface
Run all tests:
pytestRun with coverage:
pytest --cov=backend --cov-report=htmldocker build -t expense-manager .docker run -p 8000:8000 --env-file .env expense-managerError: "Access denied for user"
- Check your MySQL credentials in
.env - Ensure MySQL user has permissions:
GRANT ALL ON expense_manager.* TO 'root'@'localhost';
Error: "Can't connect to MySQL server"
- Verify MySQL is running:
sudo service mysql status(Linux) or check services (Windows) - Check
DB_HOSTin.envmatches your MySQL host
Error: "Unknown database 'expense_manager'"
- Run the schema script:
mysql -u root -p < schema.sql
If port 8000 is already in use:
uvicorn backend.server:app --host 0.0.0.0 --port 8001MIT License