- JavaScript 75.9%
- Python 17.5%
- HTML 4%
- CSS 2%
- Dockerfile 0.6%
| .emergent | ||
| backend | ||
| frontend | ||
| memory | ||
| test_reports | ||
| tests | ||
| .env.example | ||
| .gitconfig | ||
| .gitignore | ||
| backend_test.py | ||
| design_guidelines.json | ||
| docker-compose.yaml | ||
| LICENSE | ||
| README.md | ||
| test_result.md | ||
Recurring Expenses Tracker
A secure, end-to-end encrypted web application for managing and tracking recurring expenses. Built with FastAPI, MongoDB, and React.
Features
- Zero-Knowledge Architecture: All sensitive data is encrypted on the client side before being sent to the server
- End-to-End Encryption (E2EE): AES-GCM encryption with user-derived keys ensures only you can decrypt your data
- Secure Authentication: JWT-based authentication with password hashing (bcrypt) and brute-force protection
- Multi-Currency Support: Track expenses in multiple currencies with real-time exchange rate conversions
- Recurring Expense Management: Configure expenses with flexible recurrence patterns (daily, weekly, monthly, yearly)
- Responsive UI: Modern, accessible React interface with Tailwind CSS and Radix UI components
- Password Reset: Secure password recovery with time-limited reset tokens
- Role-Based Access: Admin and user role management (extensible)
Architecture
Backend
- Framework: FastAPI (async Python)
- Database: MongoDB (NoSQL)
- Authentication: JWT with refresh tokens
- Security: BCRYPT password hashing, input validation, CORS protection
- API: RESTful endpoints with proper HTTP status codes
Frontend
- Framework: React 19
- Build Tool: Create React App with Craco
- Styling: Tailwind CSS with custom components
- UI Components: Radix UI + custom built components
- State Management: React Context API
- Encryption: TweetNaCl.js for client-side E2EE
Quick Start
Prerequisites
- Docker & Docker Compose (recommended)
- Node.js 18+ and Python 3.9+ (for local development)
- MongoDB 5.0+ (if running without Docker)
Using Docker Compose (Recommended)
-
Clone the repository
git clone https://github.com/kalvin0x8d0/recurring-expenses-tracker.git cd recurring-expenses-tracker -
Configure environment variables
cp .env.example .envEdit
.envand change sensitive values (especiallyJWT_SECRET,MONGODB_PASSWORD,ADMIN_PASSWORD) -
Start all services
docker-compose up -d -
Access the application
- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/docs (Swagger UI)
-
Default admin credentials
- Email:
admin@example.com(from.env) - Password:
admin123(from.env)
- Email:
Local Development Setup
Backend
cd backend
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
# Set up environment variables
cp ../.env.example ../.env
export $(cat ../.env | grep -v '#' | xargs)
# Start the backend server
uvicorn server:app --reload --host 0.0.0.0 --port 8000
Frontend
cd frontend
npm install # or yarn install
npm start # or yarn start
The frontend will open at http://localhost:3000
API Endpoints
Authentication
POST /api/auth/register- Create a new user accountPOST /api/auth/login- Login with email and passwordPOST /api/auth/logout- Logout (clear cookies)GET /api/auth/me- Get current user profilePOST /api/auth/refresh- Refresh access tokenPOST /api/auth/forgot-password- Request password resetPOST /api/auth/reset-password- Reset password with token
Expenses
GET /api/expenses- List user's expenses (with pagination)- Query params:
frequency,currency,limit,skip
- Query params:
POST /api/expenses- Create new expenseGET /api/expenses/{expense_id}- Get specific expensePUT /api/expenses/{expense_id}- Update expenseDELETE /api/expenses/{expense_id}- Delete expense
Currency
GET /api/currency/supported- List supported currenciesGET /api/currency/rates/{base_currency}- Get exchange ratesPOST /api/currency/convert- Convert between currencies
System
GET /api/health- Health check endpointGET /api/- API root with version info
Encryption Details
Client-Side Encryption
- Algorithm: AES-256-GCM
- Key Derivation: PBKDF2 (user password)
- IV: Randomly generated per encryption
Data Flow
- User enters expense details
- Encryption context derives encryption key from user's password
- Data is encrypted client-side before transmission
- Server stores encrypted data + IV (never sees plaintext)
- On retrieval, frontend decrypts using derived key
What's Encrypted vs Stored Plaintext
Encrypted on server:
- Expense name
- Amount
- Category
- Notes
Stored plaintext (for filtering):
- Frequency (daily, weekly, monthly, yearly)
- Currency code (MYR, USD, EUR, etc.)
- Next due timestamp (for sorting)
Security Considerations
Implemented Security Measures
✅ HTTPS/TLS support via COOKIE_SECURE env variable
✅ HTTPOnly cookies to prevent XSS token theft
✅ CSRF protection via SameSite cookies
✅ Brute-force attack protection (5 attempts = 15 min lockout)
✅ Password hashing with bcrypt
✅ JWT tokens with short expiration (15 min access, 7 day refresh)
✅ Input validation and sanitization
✅ MongoDB injection prevention via ORM
✅ CORS with configurable origins
✅ Rate limiting on list endpoints (max 500 items)
Deployment Security Recommendations
- 🔒 Set
COOKIE_SECURE=truein production - 🔒 Use strong
JWT_SECRET(minimum 32 characters) - 🔒 Enable HTTPS/TLS on your domain
- 🔒 Change
ADMIN_PASSWORDimmediately after first login - 🔒 Set
ENVIRONMENT=productionin production - 🔒 Restrict MongoDB access to internal networks only
- 🔒 Use environment variables, never commit
.envfiles - 🔒 Regularly update dependencies:
npm audit fix,pip list --outdated - 🔒 Enable MongoDB authentication and use strong credentials
- 🔒 Set up firewall rules to restrict port access
Environment Variables
All available environment variables are documented in .env.example. Key variables:
| Variable | Default | Description |
|---|---|---|
MONGO_URL |
(required) | MongoDB connection string |
DB_NAME |
recurring_expenses |
Database name |
JWT_SECRET |
(required) | Secret for signing JWT tokens |
ENVIRONMENT |
development |
Environment mode (development/production) |
COOKIE_SECURE |
false |
Enable secure cookies (set true for HTTPS) |
FRONTEND_URL |
http://localhost:3000 |
Frontend URL for CORS |
ADMIN_EMAIL |
admin@example.com |
Initial admin email |
ADMIN_PASSWORD |
admin123 |
Initial admin password |
EXCHANGERATE_API_KEY |
demo |
Exchange rate API key |
Development
Project Structure
.
├── backend/ # FastAPI backend
│ ├── server.py # Main API server
│ └── requirements.txt # Python dependencies
├── frontend/ # React frontend
│ ├── src/
│ │ ├── pages/ # Page components
│ │ ├── components/ # Reusable components
│ │ ├── contexts/ # Context providers (Auth, Encryption)
│ │ └── hooks/ # Custom React hooks
│ ├── package.json # Node dependencies
│ └── tailwind.config.js # Tailwind configuration
├── docker-compose.yaml # Docker Compose setup
├── .env.example # Environment template
└── README.md # This file
Running Tests
Backend
cd backend
pytest ../backend_test.py -v
Frontend
cd frontend
npm test
Code Style
- Python: Follow PEP 8 (checked with
flake8, formatted withblack) - JavaScript: ESLint + Prettier
- Git: Conventional commits recommended
Troubleshooting
MongoDB Connection Issues
Error: "connect ECONNREFUSED 127.0.0.1:27017"
- Ensure MongoDB is running:
docker-compose logs mongodb - Check connection string in
.env:MONGO_URL=mongodb://user:pass@host:port/db
Frontend Can't Connect to Backend
CORS Error or "Failed to fetch"
- Verify backend is running:
docker-compose logs backend - Check
FRONTEND_URLmatches your frontend's domain - Ensure firewall allows port 8000
Admin Login Fails
- Check admin credentials in
.env(default: admin@example.com / admin123) - View backend logs:
docker-compose logs backend
Docker Issues
# Rebuild containers
docker-compose down -v
docker-compose up --build
# View logs
docker-compose logs -f backend
docker-compose logs -f frontend
docker-compose logs -f mongodb
Production Deployment
Pre-Deployment Checklist
- Generate strong
JWT_SECRET(useopenssl rand -hex 32) - Change all default credentials
- Set
ENVIRONMENT=production - Set
COOKIE_SECURE=true - Configure proper
FRONTEND_URL - Enable HTTPS/TLS on your domain
- Set up MongoDB with authentication
- Review and update security settings
- Set up monitoring and logging
- Test email notifications (if configured)
Recommended Deployment Stacks
- Docker/Kubernetes: Use provided
docker-compose.yamlas base - Traditional VPS: Install Node, Python, MongoDB separately
- Serverless: Not recommended due to database requirements
- PaaS: Heroku, Railway, Render support easy deployment
Scaling Considerations
- MongoDB connection pooling (Motor is configured)
- Frontend: CDN for static assets
- Backend: Use load balancer with multiple instances
- Database: Consider read replicas for scaling queries
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is released under the CC0 1.0 Universal License. See the LICENSE file for details.
Support
For issues, questions, or suggestions:
- Open an GitHub Issue
- Check existing issues for similar problems
- Include error messages, logs, and reproduction steps
Acknowledgments
- FastAPI and Motor for async Python
- React and the community for UI building
- Radix UI for accessible components
- Tailwind CSS for utility-first styling
- Open Exchange Rates API for currency data
Last Updated: March 2026 Version: 1.0.0 Status: Actively Maintained