A full-stack personal finance management platform with an AI-powered financial assistant. Track income and expenses, set monthly budgets, visualize spending patterns, and ask natural-language questions about your finances — all backed by secure cookie-based authentication.
📌 Project Context: Built for learning as part of AlmaBetter's AlmaX Program Assignment.
# Clone the repository
git clone https://github.com/mdmunna84880/FinSmart.git
cd FinSmart
# Start the backend (Terminal 1)
cd backend && npm install && npm run dev
# Start the frontend (Terminal 2)
cd frontend && npm install && npm run devBackend → http://localhost:8000 | Frontend → http://localhost:5173
- Features
- Architecture
- Tech Stack
- Project Structure
- Prerequisites
- Getting Started
- Environment Variables
- API Reference
- Authentication
- AI Chat Assistant
- Design Decisions
- Build & Deployment
- Author
| Feature | Description |
|---|---|
| Dashboard | Net savings, income/expenses, 6-month cash flow chart, recent transactions, budget progress |
| Transactions | Full CRUD with search, pagination, and dynamic filters (year, month, category, type) |
| Budgets | Monthly spending limits with per-category caps, actual-vs-planned summaries |
| Analytics | Category spending donut chart, budget-vs-actual progress per category |
| Profile & Security | Password change form, budget configuration modal |
| Feature | Description |
|---|---|
| Contextual Answers | Gemini 2.5 Flash analyzes 12 months of real financial data |
| Persistent Sessions | Conversation history saved — pick up where you left off |
| Optimistic UI | Messages appear instantly before the server responds |
| Markdown Rendering | Bold text, lists, and code blocks rendered in brand styling |
| Quick Prompts | 8 predefined questions for first-time users |
| Feature | Description |
|---|---|
| Secure Auth | JWT via HTTP-only cookies — no localStorage exposure |
| Responsive Design | Mobile-first with collapsible sidebar, hamburger menu, overlay drawer |
| Route Guards | Protected/public routes with auto-redirect based on auth state |
| Toast Notifications | Success/error feedback on every operation |
| Dual Validation | React Hook Form + Joi schemas on both client and server |
FinSmart uses a modern, decoupled architecture:
- Frontend App: A React application providing a localized, seamless user experience.
- Backend API: An Express.js REST API that securely handles business logic and database operations.
- Database: MongoDB for storing user profiles, transaction records, budgets, and chat sessions.
- AI Assistant: Google Gemini for tailored financial insights.
| Category | Technology | Version |
|---|---|---|
| Framework | React | 19.2.4 |
| Build Tool | Vite | 8.0.1 |
| Routing | React Router | 7.13.2 |
| State Management | Redux Toolkit + React Redux | 2.8.2 / 9.2.0 |
| Styling | Tailwind CSS | 4.2.2 |
| Charts | Recharts | 3.8.0 |
| Forms | React Hook Form + @hookform/resolvers | 7.61.0 / 5.2.0 |
| Validation | Joi | 17.13.3 |
| HTTP Client | Axios | 1.10.0 |
| Markdown | react-markdown | 10.1.0 |
| Notifications | React Toastify | 11.0.5 |
| Icons | React Icons (Feather) | 5.6.0 |
| Category | Technology | Version |
|---|---|---|
| Runtime | Node.js (ES modules) | v18+ |
| Framework | Express | 5.2.1 |
| Database | MongoDB via Mongoose | 9.x |
| Auth | JWT in HTTP-only cookies | jsonwebtoken 9.x |
| Validation | Joi | 18.x |
| Password Hashing | bcryptjs | 3.x (10 salt rounds) |
| AI | Google Gemini (@google/generative-ai) |
0.24.x |
| Logging | Morgan | 1.10.x |
The repository is divided into two distinct applications:
backend/: The Express API and database modelsfrontend/: The React Single Page Application (SPA)
Each sub-project (
backend/,frontend/) has its ownREADME.mdwith in-depth documentation.
| Requirement | Version | Notes |
|---|---|---|
| Node.js | v18+ | Download |
| npm | v9+ | Bundled with Node.js |
| MongoDB | Any | Local instance or MongoDB Atlas |
| Gemini API Key | — | Get yours free from Google AI Studio |
git clone https://github.com/mdmunna84880/FinSmart.git
cd FinSmartcd backend
npm installCreate a .env file in backend/:
MONGODB_URI=mongodb://localhost:27017
JWT_SECRET=your-long-random-secret-key-here
JWT_EXPIRY=7d
GEMINI_API_KEY=your-google-gemini-api-key
NODE_ENV=development
PORT=8000
CLIENT_URL=http://localhost:5173cd ../frontend
npm installCreate a .env file in frontend/ (optional — defaults are provided):
VITE_API_URL=http://localhost:8000/apiTerminal 1 — Backend:
cd backend && npm run devServer running at http://localhost:8000
Terminal 2 — Frontend:
cd frontend && npm run devApp opens at http://localhost:5173
| Variable | Required | Default | Description |
|---|---|---|---|
MONGODB_URI |
Yes | — | MongoDB connection string (database name finsmart is appended by the app) |
JWT_SECRET |
Yes | — | Secret key for signing JWTs — use a long, random string |
GEMINI_API_KEY |
Yes | — | Google Gemini API key for the AI chat feature |
JWT_EXPIRY |
No | 7d |
JWT token expiry duration |
NODE_ENV |
No | development |
Controls error verbosity and cookie secure flag |
PORT |
No | 8000 |
HTTP server port |
CLIENT_URL |
No | http://localhost:5173 |
Frontend origin for CORS configuration |
| Variable | Default | Description |
|---|---|---|
VITE_API_URL |
http://localhost:8000/api |
Backend API base URL |
Base URL: http://localhost:8000/api
FinSmart uses cookie-based sessions instead of storing JWT tokens in localStorage. This eliminates the risk of XSS-based token theft.
FinSmart employs a seamless login process where users receive a secure session cookie directly upon authentication. This ensures that subsequent API requests are automatically authorized without exposing sensitive tokens to browser environments.
| Measure | Implementation |
|---|---|
| Token storage | HTTP-only cookie — inaccessible to JavaScript |
| CSRF protection | sameSite: "lax" (dev) / "none" + secure (prod) |
| CORS | credentials: true — only the configured CLIENT_URL can send cookies |
| Password hashing | bcrypt with 10 salt rounds |
| Input validation | Joi schemas on every write endpoint |
| Ownership enforcement | Every query scoped to req.user._id |
FinSmart's AI assistant is powered by Google Gemini 2.5 Flash and answers questions grounded in the user's actual financial data — not generic advice.
Whenever a user consults the AI assistant, FinSmart securely packages their recent financial transaction metrics (income, expenses, active budgets) into an anonymized request sent to the Gemini engine. As a result, the AI recognizes patterns and can generate precise, applicable advice on-the-fly.
On the first message of a session, the backend aggregates:
| Data | Source |
|---|---|
| Total income, expenses, net savings | Last 12 months of transactions |
| Monthly trends | Income/expense grouped by month |
| Top expense categories | Sorted by spending amount |
| Active budget configurations | Last 12 months of budget settings |
| Recent transactions | 20 most recent entries |
This snapshot is stored as contextSnapshot in the ChatSession document and sent to Gemini as part of the system prompt for every subsequent message in that session.
- Auto-generated titles — Parsed from the first message using pattern matching (no extra API call)
- Persistent history — All messages saved, accessible via the sidebar
- Optimistic UI — User messages appear instantly before the server responds
- Markdown rendering — Bold text, lists, and code blocks styled in brand colors
- Quick prompts — 8 predefined questions for users who don't know where to start
| Decision | Rationale |
|---|---|
| Cookie-based auth | HTTP-only cookies eliminate XSS token theft. Paired with CORS + sameSite, CSRF risk is mitigated for same-origin setups |
| Layered backend | Routes → Controllers → Services/Repositories → Models. Simple CRUD in controllers; complex queries delegated to services |
| Upsert for budgets | One endpoint (POST /budgets) handles both create and update via findOneAndUpdate with upsert: true |
| Dynamic filters | GET /transactions/filters runs a $facet aggregation — dropdowns reflect actual data, never stale options |
| Optimistic chat UI | Messages pushed to state immediately — users see instant feedback, AI response appends on fulfillment |
| Dual Joi validation | Client-side (RHF) for instant feedback, server-side for security — schemas mirror each other |
| Compound indexes | (userId, date), (userId, category), (userId, type) on transactions; unique (userId, year, month) on budgets |
# Frontend
cd frontend && npm run build # Output → dist/
npm run preview # Preview locally
# Backend
cd backend && npm start # Production mode (node)The project includes a vercel.json:
{
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
],
"headers": [
{
"source": "/assets/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }
]
}
]
}npx vercel- Push code to GitHub
- Connect repository to your hosting platform
- Set root directory to
backend/ - Add environment variables in the dashboard
- Deploy
- Deploy backend and note the production URL
- Set
CLIENT_URLon backend to the frontend's production URL - Set
VITE_API_URLon frontend to the backend's production URL - Set
GEMINI_API_KEYon backend - Point MongoDB Atlas to allow connections from backend IP
- Deploy frontend as a static SPA (Vercel, Netlify, Cloudflare Pages)
- Test registration, login, transaction CRUD, budget, and chat
|
Md Munna 📧 mdmunna19434@gmail.com 📍 Bihar, India |
Built for learning — AlmaBetter's AlmaX Program Assignment
Made in Bihar, India