Skip to main content

Overview

Running SpendWisely George locally enables all features including bank sync, mutual fund tracking, and settings persistence. This setup runs both the FastAPI backend and serves the frontend.
All features work locally: Bank sync, mutual funds, settings, and manual expense tracking.

Prerequisites

Python 3.8+

Required for FastAPI server

Unfold CLI

Pre-built binary included in unfold/ directory

Fold Account

Invite-only banking aggregator service

Google Sheet

Optional, for manual expense tracking

Installation

1

Clone Repository

git clone https://github.com/georgejohnsonoff-business/spendwiselygeorge.git
cd spendwiselygeorge
2

Install Python Dependencies

pip install fastapi uvicorn pyyaml requests
Required packages:
  • fastapi - Web framework
  • uvicorn - ASGI server
  • pyyaml - Config file handling
  • requests - HTTP client for API calls
3

Verify Unfold Binary

The repository includes a pre-built Unfold CLI binary:
ls -lh unfold/unfold
# Should show: -rwxr-xr-x ... unfold/unfold (18MB)
If missing, build from source:
cd unfold
make build  # Requires Go 1.19+
4

Create Holdings File

Create an empty file for mutual fund holdings:
echo '[]' > holdings.json

Configuration

Server Configuration

The server (server.py:16-20) uses these default paths:
UNFOLD_BINARY = "./unfold/unfold"        # Unfold CLI binary
UNFOLD_CONFIG = "./unfold_config.yaml"   # Auth tokens
DB_PATH = "./unfold/db.sqlite"           # Transaction database
HOLDINGS_FILE = "./holdings.json"        # Mutual fund holdings

Environment Variables

All configuration is file-based. The only environment variable is:
PORT=8000  # Optional, defaults to 8000

Running the Server

1

Start the Server

python server.py
Expected output:
INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000
2

Access the Application

Open your browser:
http://localhost:8000
The frontend (index.html) is served via FastAPI’s StaticFiles (server.py:237).
3

Verify API Endpoints

Test the health check:
curl http://localhost:8000/api/fold/status
# Returns: {"logged_in": false}

Unfold CLI Setup

Important: Using Unfold CLI will log you out of the Fold mobile app. Fold does not support multiple concurrent sessions.

Login via Web Interface

The easiest method is through the app UI:
1

Open Settings

In the web app, navigate to SettingsBank Sync
2

Enter Phone Number

Click “Login to Fold” and enter your registered phone number (automatically prefixed with +91).
3

Verify OTP

Enter the 6-digit OTP sent via SMS.
4

Confirm Login

The server saves credentials to unfold_config.yaml (server.py:44-56):
token:
  access: "eyJhbGc..."
  refresh: "refresh_token..."
fold_user:
  uuid: "user-uuid-here"
device_hash: "python-client-a3f2"

Manual Login via CLI

Alternatively, use the Unfold CLI directly:
cd unfold
./unfold login --config ../unfold_config.yaml

# Follow prompts:
# Enter phone number: +919876543210
# Enter OTP: 123456

Syncing Transactions

Click the Sync button in the Transactions section.This calls /api/sync (server.py:190-198), which runs:
./unfold/unfold transactions --db --config ./unfold_config.yaml

Mutual Fund Portfolio

The portfolio feature fetches NAV data from the public MFAPI service.
1

Add Holdings

In the web app, go to PortfolioAdd Holding:
  • Scheme Code: AMFI scheme code (e.g., 120503 for HDFC Top 100)
  • Units: Number of units you own
2

Data Storage

Holdings are saved to holdings.json (server.py:40-42):
[
  {"scheme_code": "120503", "units": 150.5},
  {"scheme_code": "118989", "units": 200.0}
]
3

NAV Fetching

The server fetches current NAV from https://api.mfapi.in/mf/{code} (server.py:213).No API key required - this is a free public service.

API Endpoints Reference

Authentication

# Send OTP
POST /api/fold/login
{"phone": "9876543210"}

# Verify OTP
POST /api/fold/verify
{"phone": "9876543210", "otp": "123456"}

# Check login status
GET /api/fold/status

Transactions

# Get recent transactions (last 50)
GET /api/transactions

# Sync with Fold
POST /api/sync

Portfolio

# Get all holdings with current values
GET /api/portfolio

# Update holdings
POST /api/holdings
[{"scheme_code": "120503", "units": 150}]

Troubleshooting

Cause: Missing pyyaml dependencySolution:
pip install pyyaml
Cause: Binary missing or not executableSolution:
chmod +x unfold/unfold
./unfold/unfold --help  # Should show usage
If still failing, rebuild:
cd unfold && make build
Cause: Unfold CLI requires --db flagSolution:
./unfold transactions --db --config ../unfold_config.yaml
#                     ^^^^ Required to write to SQLite
Cause: Frontend served from different originSolution: The server allows all origins (server.py:23-28). If still blocked, ensure you’re using http://localhost:8000 directly, not a different port.
Cause: Invalid scheme code or API downtimeSolution:

File Structure

After setup, your directory should look like:
spendwiselygeorge/
├── server.py                # FastAPI backend
├── index.html              # Frontend
├── manifest.json           # PWA manifest
├── sw.js                   # Service worker
├── google_script.js        # Google Script reference
├── holdings.json           # Mutual fund data
├── unfold_config.yaml      # Unfold auth tokens (created after login)
└── unfold/
    ├── unfold              # CLI binary (18MB)
    ├── db.sqlite           # Transaction database (created after sync)
    ├── main.go
    ├── Makefile
    └── readme.md

Next Steps

Google Sheets Integration

Add manual expense tracking

Cloud Deployment

Deploy to production on cloud platforms

Build docs developers (and LLMs) love