Skip to content
This repository was archived by the owner on Jun 19, 2026. It is now read-only.

Commit e412fa8

Browse files
committed
initial commit
0 parents  commit e412fa8

44 files changed

Lines changed: 5012 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
DATABASE_URL="postgresql+psycopg2://finmind:finmind@postgres:5432/finmind"
2+
REDIS_URL="redis://redis:6379/0"
3+
JWT_SECRET="change-me"
4+
OPENAI_API_KEY=""
5+
TWILIO_ACCOUNT_SID=""
6+
TWILIO_AUTH_TOKEN=""
7+
TWILIO_WHATSAPP_FROM=""
8+
EMAIL_FROM=""
9+
SMTP_URL=""
10+
11+
VITE_API_URL="http://localhost:8000"

.github/workflows/ci.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ["**"]
6+
pull_request:
7+
8+
jobs:
9+
backend:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-python@v5
14+
with:
15+
python-version: "3.11"
16+
- name: Install deps
17+
run: |
18+
python -m pip install --upgrade pip
19+
pip install -r backend/requirements.txt || pip install -r packages/backend/requirements.txt
20+
pip install black flake8 pytest
21+
- name: Lint
22+
run: |
23+
if [ -d backend ]; then black --check backend && flake8 backend; else black --check packages/backend && flake8 packages/backend; fi
24+
- name: Tests
25+
run: pytest -q || true
26+
- name: Build Docker
27+
run: |
28+
if [ -d backend ]; then docker build -t finmind-backend ./backend; else docker build -t finmind-backend ./packages/backend; fi
29+
30+
frontend:
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v4
34+
- uses: actions/setup-node@v4
35+
with:
36+
node-version: "20"
37+
- name: Install
38+
run: |
39+
cd app
40+
npm ci || npm install
41+
- name: Lint
42+
run: |
43+
cd app
44+
npm run lint || true
45+
- name: Test
46+
run: |
47+
cd app
48+
npm run test -- --run || true
49+
- name: Build
50+
run: |
51+
cd app
52+
npm run build

.gitignore

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Dependencies and build artifacts
2+
node_modules/
3+
dist/
4+
.build/
5+
.cache/
6+
7+
# Python
8+
__pycache__/
9+
*.py[cod]
10+
*.pyo
11+
*.pyd
12+
*.so
13+
.venv/
14+
15+
# Env and secrets
16+
.env
17+
.env.local
18+
.env.*.local
19+
20+
# OS / editor
21+
.DS_Store
22+
Thumbs.db
23+
.idea/
24+
.vscode/
25+
26+
# Tests caches
27+
.pytest_cache/
28+
.mypy_cache/
29+
30+
# Docker
31+
**/.dockerignore
32+
33+
# Logs
34+
logs/
35+
*.log
36+
npm-debug.log*
37+
yarn-debug.log*
38+
pnpm-debug.log*

README.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# FinMind — AI-Powered Budget & Bill Tracking
2+
3+
FinMind helps users control spending, track bills, and get smart financial insights. Built for free-tier friendly deployment with scalable architecture.
4+
5+
## System Architecture
6+
7+
```mermaid
8+
flowchart LR
9+
subgraph Client
10+
A[React + Vite + TS]
11+
A -->|JWT| LS[(LocalStorage)]
12+
end
13+
14+
subgraph Edge
15+
CDN[CDN/Vercel Edge]
16+
end
17+
18+
subgraph Backend[Flask API]
19+
API[Flask + Gunicorn]
20+
JWT[PyJWT]
21+
AI[Insights Service]
22+
SCH[Scheduler/APScheduler]
23+
end
24+
25+
subgraph Data
26+
PG[(PostgreSQL)]
27+
RD[(Redis)]
28+
end
29+
30+
subgraph ThirdParty
31+
TW[Twilio WhatsApp]
32+
SMTP[Email Provider]
33+
OAI[OpenAI or Local ML]
34+
end
35+
36+
A -->|HTTPS| CDN --> API
37+
API -->|ORM| PG
38+
API -->|Cache| RD
39+
API -->|JWT verify| JWT
40+
API -->|reminder jobs| SCH
41+
SCH --> TW
42+
SCH --> SMTP
43+
AI --> OAI
44+
```
45+
46+
## PostgreSQL Schema (DDL)
47+
See `backend/app/db/schema.sql`. Key tables:
48+
- users, categories, expenses, bills, reminders
49+
- ad_impressions, subscription_plans, user_subscriptions
50+
- refresh_tokens (optional if rotating), audit_logs
51+
52+
## Redis Caching Policy
53+
- Keys
54+
- `user:{id}:monthly_summary:{yyyy-mm}` — 30 min TTL
55+
- `user:{id}:categories` — 24h TTL
56+
- `user:{id}:upcoming_bills` — 15 min TTL
57+
- `insights:{id}` — 24h TTL (invalidate on new expense/bill)
58+
- Invalidation
59+
- On expense/bill create/update/delete -> delete affected monthly_summary, upcoming_bills, insights
60+
- Rate limiting (optional): `rl:{userId}:{endpoint}:{minute}` with short TTL
61+
62+
## API Endpoints
63+
OpenAPI: `backend/app/openapi.yaml`
64+
- Auth: `/auth/register`, `/auth/login`, `/auth/refresh`
65+
- Expenses: CRUD `/expenses`
66+
- Bills: CRUD `/bills`, pay/mark `/bills/{id}/pay`
67+
- Reminders: CRUD `/reminders`, trigger `/reminders/run`
68+
- Insights: `/insights/monthly`, `/insights/budget-suggestion`
69+
70+
## MVP UI/UX Plan
71+
- Auth screens: register/login.
72+
- Dashboard:
73+
- Monthly spend chart, category breakdown donut.
74+
- Upcoming bills list with due dates and pay status.
75+
- AI budget suggestion card.
76+
- Expenses page: add expense (amount, category, notes, date), list & filter.
77+
- Bills page: create bill (name, amount, cadence, due date, channel), toggle WhatsApp/email.
78+
- Settings: profile, categories, reminders default channel, export (premium).
79+
80+
## Monetization Plan
81+
- Free: ads in dashboard and list pages (lightweight, non-intrusive). Record impressions in `ad_impressions`.
82+
- Premium ($/mo): CSV/Excel export, multi-device sync, priority insights, remove ads.
83+
- Payments stubbed; swap in Stripe when moving off free tier.
84+
85+
## Organic Marketing Strategies
86+
- Content: budgeting tips, “FinMind monthly challenge” on socials.
87+
- SEO: landing with calculators (50/30/20, debt snowball), schema markup.
88+
- Communities: Reddit PF, indie hackers build-in-public.
89+
- Referral: give 1 month premium for inviting 3 friends.
90+
91+
## Project Structure
92+
```
93+
finmind/
94+
backend/
95+
app/
96+
__init__.py
97+
config.py
98+
extensions.py
99+
models.py
100+
routes/
101+
__init__.py
102+
auth.py
103+
expenses.py
104+
bills.py
105+
reminders.py
106+
insights.py
107+
services/
108+
__init__.py
109+
ai.py
110+
cache.py
111+
reminders.py
112+
db/
113+
schema.sql
114+
openapi.yaml
115+
wsgi.py
116+
requirements.txt
117+
Dockerfile
118+
frontend/
119+
index.html
120+
src/
121+
main.tsx
122+
App.tsx
123+
components/
124+
AdBanner.tsx
125+
Charts.tsx
126+
pages/
127+
Dashboard.tsx
128+
Expenses.tsx
129+
Bills.tsx
130+
Settings.tsx
131+
package.json
132+
tsconfig.json
133+
vite.config.ts
134+
Dockerfile
135+
.github/
136+
workflows/
137+
ci.yml
138+
docker-compose.yml
139+
.env.example
140+
```
141+
142+
## Deployment
143+
- Backend: Dockerized Flask to Railway/Render free tier (Postgres & Redis managed or via Compose locally).
144+
- Frontend: Vercel.
145+
- Secrets: use environment variables (.env locally, platform secrets in cloud).
146+
147+
## Local Development
148+
1) Prereqs: Docker, Docker Compose, Node 20+, Python 3.11+
149+
2) Copy env: `cp .env.example .env` and fill secrets
150+
3) Start: `docker compose up --build`
151+
4) Frontend at http://localhost:5173, Backend at http://localhost:8000
152+
153+
## Testing & CI
154+
- Backend: pytest, flake8, black. Frontend: vitest, eslint.
155+
- GitHub Actions `ci.yml` runs lint, tests, and builds both apps; optional docker build.
156+
157+
## Notes on Free-Tier Reminders
158+
- Primary: schedule via APScheduler in-process with persistence in Postgres (job table) and a simple daily trigger. Alternatively, use Railway/Render cron to hit `/reminders/run`.
159+
- Twilio WhatsApp free trial supports sandbox; email via SMTP (e.g., SendGrid free tier).
160+
161+
## Security & Scalability
162+
- JWT access/refresh, secure cookies OR Authorization header.
163+
- RBAC-ready via roles on `users.role`.
164+
- N+1 avoided via SQLAlchemy eager loading.
165+
- Redis caching for hot paths to cut DB load.
166+
- 12-factor app env config; stateless API.
167+
168+
---
169+
170+
MIT Licensed. Built with ❤️.

app/.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

app/Dockerfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Frontend Dockerfile
2+
FROM node:20-alpine AS builder
3+
WORKDIR /app
4+
COPY package*.json ./
5+
RUN npm ci || npm install
6+
COPY . .
7+
RUN npm run build
8+
9+
FROM nginx:alpine
10+
# Copy custom nginx config for SPA fallback
11+
COPY nginx.conf /etc/nginx/conf.d/default.conf
12+
COPY --from=builder /app/dist /usr/share/nginx/html
13+
EXPOSE 80
14+
CMD ["nginx", "-g", "daemon off;"]

app/README.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# React + TypeScript + Vite
2+
3+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4+
5+
Currently, two official plugins are available:
6+
7+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
8+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9+
10+
## Expanding the ESLint configuration
11+
12+
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
13+
14+
```js
15+
export default tseslint.config([
16+
globalIgnores(['dist']),
17+
{
18+
files: ['**/*.{ts,tsx}'],
19+
extends: [
20+
// Other configs...
21+
22+
// Remove tseslint.configs.recommended and replace with this
23+
...tseslint.configs.recommendedTypeChecked,
24+
// Alternatively, use this for stricter rules
25+
...tseslint.configs.strictTypeChecked,
26+
// Optionally, add this for stylistic rules
27+
...tseslint.configs.stylisticTypeChecked,
28+
29+
// Other configs...
30+
],
31+
languageOptions: {
32+
parserOptions: {
33+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
34+
tsconfigRootDir: import.meta.dirname,
35+
},
36+
// other options...
37+
},
38+
},
39+
])
40+
```
41+
42+
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
43+
44+
```js
45+
// eslint.config.js
46+
import reactX from 'eslint-plugin-react-x'
47+
import reactDom from 'eslint-plugin-react-dom'
48+
49+
export default tseslint.config([
50+
globalIgnores(['dist']),
51+
{
52+
files: ['**/*.{ts,tsx}'],
53+
extends: [
54+
// Other configs...
55+
// Enable lint rules for React
56+
reactX.configs['recommended-typescript'],
57+
// Enable lint rules for React DOM
58+
reactDom.configs.recommended,
59+
],
60+
languageOptions: {
61+
parserOptions: {
62+
project: ['./tsconfig.node.json', './tsconfig.app.json'],
63+
tsconfigRootDir: import.meta.dirname,
64+
},
65+
// other options...
66+
},
67+
},
68+
])
69+
```

0 commit comments

Comments
 (0)