Pennywise is a finance app that simplifies budgeting, builds financial literacy, and helps you make better money decisions with personalized, source-backed guidance.
The goal is to feel in control of your money — not overwhelmed by it.
- Personalized guidance: Understand your financial situation through an onboarding flow and tailored recommendations instead of generic advice.
- Education-first experience: Learn the why behind each suggestion, with explanations and links to credible sources.
- Practical budgeting help: Get suggestions for how to allocate income, manage recurring expenses, and plan toward goals.
- Assistant-style interactions: Ask questions in natural language and get structured, source-backed answers (powered by AI).
- Frontend: Next.js (React + TypeScript)
- Backend: FastAPI (Python)
- Database & Auth: Supabase
- AI: Gemini (for recommendations and explanations)
- Monorepo: pnpm / npm workspaces-style layout
You do not need to know any of this to simply run the app locally, but it’s helpful context if you’re technical or considering contributing.
apps/web– Web app (Next.js)apps/api– API service (FastAPI)packages/shared– Shared types/utilitiesdocs/– Architecture, API contract, data model, and design docs
This section is intended for anyone who wants to try Pennywise on their own machine (no prior contribution required).
- Node.js (LTS version recommended, e.g. 20.x)
- npm or pnpm (npm works out of the box)
- Python 3.10+
- A Supabase project (free tier is fine)
- A Gemini API key (for AI features; optional but recommended)
-
Navigate to the API app
cd apps/api -
Create and activate a virtual environment
python -m venv .venv # macOS/Linux source .venv/bin/activate # Windows (PowerShell) .venv\Scripts\Activate.ps1
-
Install dependencies
pip install -r requirements.txt
-
Create the API environment file
In
apps/api, create a file named.env(this file is gitignored) and add:SUPABASE_URL=your_supabase_project_url SUPABASE_ANON_KEY=your_supabase_anon_key SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key GEMINI_API_KEY=your_gemini_api_key # required for AI features
-
Run the API locally
uvicorn app.main:app --reload --port 8000
-
Check that the API is healthy
Open in your browser:
http://localhost:8000/health
-
Open a new terminal window (keep the API running), then from the repo root:
cd apps/web -
Install dependencies
npm install
-
Create the web environment file
In
apps/web, create.env.localwith:NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
apps/web/.env.localis gitignored and should not be committed. -
Run the web app
npm run dev
-
Open the app
Visit:
http://localhost:3000
You should now be able to go through onboarding, see your dashboard, and interact with guidance powered by the running API.
If you prefer using PowerShell or a terminal, here are sample calls to exercise the profile endpoints once your API is running on http://localhost:8000.
# Health check
Invoke-RestMethod -Method Get -Uri "http://localhost:8000/health"
# Get current profile
Invoke-RestMethod -Method Get -Uri "http://localhost:8000/me"
# Update profile
Invoke-RestMethod -Method Put -Uri "http://localhost:8000/me" `
-ContentType "application/json" `
-Body '{"job_type":"w2","state":"CA","pay_frequency":"biweekly","net_income_range":"1500_2500","rent_status":"rent","debt_status":"none","credit_card_status":"use_sometimes","emergency_buffer_range":"lt_500","priority":"save"}'- Supabase stores user profiles (for example, your job type, income range, rent status, and goals) in a
profilestable. - Secure credentials for Supabase live only in
apps/api/.env, which is never committed. - The backend is designed to use authenticated Supabase tokens to derive a
user_idso that each user’s data is kept separate.
From the app’s perspective:
- The web app sends authenticated requests like
PUT /meto update your profile. - The API writes this information to Supabase.
- You can verify what’s stored by calling
GET /me.
- Non-technical feedback: If you’re just trying out Pennywise, feedback on clarity, tone, and usefulness of recommendations is extremely valuable.
- Technical contributions: If you’re a developer and want to contribute, you can:
- Open an issue describing a bug, idea, or improvement.
- Submit a pull request (ideally with a short description and screenshots where applicable).
Pennywise is early-stage and evolving quickly; your feedback helps shape what it becomes.
finance app that simplifies budgeting, financial literacy, and decision-making with personalized guidance
Pennywise is a finance education + guidance app focused on helping users understand core money topics through personalized recommendations and a source-backed assistant.
apps/web— Frontend (React/Next + TypeScript)apps/api— Backend (FastAPI)packages/shared— Shared types/utilities across appsdocs/— Architecture, API contract, and data model.github/workflows/— CI pipelines (WIP)
- Create your local env file:
cp .env.example .env
2) Run the API:
```bash
cd apps/api
python -m venv .venv
# macOS/Linux: source .venv/bin/activate
# Windows: .\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000
Health check:
http://localhost:8000/health
3)Run the Web app
cd apps/web
## Run locally
```bash
cd apps/web
npm install
npm run dev
Web env (required):
Create apps/web/.env.local with the following content:
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
.env.local is gitignored. Do not commit it.
```md
API env (required for Supabase-backed endpoints):
Create `apps/api/.env` (gitignored) with:
- `SUPABASE_URL`
- `SUPABASE_ANON_KEY`
- `SUPABASE_SERVICE_ROLE_KEY`
- `GEMINI_API_KEY` (for AI recommendations)
### API quick test (PowerShell)
Health:
```powershell
Invoke-RestMethod -Method Get -Uri "http://localhost:8000/health"
1st method: Get profile
Invoke-RestMethod -Method Get -Uri "http://localhost:8000/me"
2nd method: Update profile
Invoke-RestMethod -Method Put -Uri "http://localhost:8000/me" `
-ContentType "application/json" `
-Body '{"job_type":"w2","state":"CA","pay_frequency":"biweekly","net_income_range":"1500_2500","rent_status":"rent","debt_status":"none","credit_card_status":"use_sometimes","emergency_buffer_range":"lt_500","priority":"save"}'
### How user data is stored
Supabase connection credentials are stored in `apps/api/.env` (gitignored).
The backend now requires proper authentication to extract the user's `user_id`.
When the frontend sends a `PUT /me` request with proper authentication, the API updates the profile for that user in the `profiles` table in Supabase.
You can then confirm it was saved by calling `GET /me`.
> Note: Authentication middleware needs to be implemented to extract `user_id` from Supabase Auth tokens.