A personal expense tracker for small households. Scan receipts with your phone camera, have AI extract the details, and save entries directly to Google Sheets — or enter expenses manually when there’s no receipt.
Built as a mobile-optimised web app accessible at cashflow.yourdomain.com.
cashflow.yourdomain.com| Layer | Technology |
|---|---|
| Frontend | Svelte + Vite, hosted on GitHub Pages |
| Backend | Google Apps Script (TypeScript via clasp) |
| OCR | Claude API — Haiku 4.5 model |
| Data | Google Sheets (one sheet per year) |
| Photos | Google Drive (receipts/ folder per year) |
| Domain | cashflow.yourdomain.com via CNAME |
cash-flow/
├── frontend/ ← Svelte app deployed to GitHub Pages
│ ├── src/
│ │ ├── routes/
│ │ │ ├── Home.svelte
│ │ │ ├── Scan.svelte
│ │ │ ├── Entry.svelte ← shared form (manual + scan fallback)
│ │ │ └── Audit.svelte
│ │ ├── lib/
│ │ │ ├── api.ts ← all Apps Script calls
│ │ │ ├── camera.ts ← file picker / photo capture
│ │ │ ├── auth.ts ← token storage / retrieval
│ │ │ └── store.ts ← Svelte app state
│ │ └── App.svelte
│ ├── public/
│ │ └── CNAME ← cashflow.yourdomain.com
│ ├── package.json
│ └── vite.config.ts
│
├── apps-script/ ← Google Apps Script backend (clasp)
│ ├── src/
│ │ ├── main.ts ← doPost router
│ │ ├── sheets.ts ← read/write Google Sheets
│ │ ├── drive.ts ← receipt photo storage
│ │ ├── claude.ts ← Claude Vision API
│ │ ├── dropdowns.ts ← category / payment / tag lists
│ │ └── config.ts ← auth, CORS, sheet ID discovery
│ ├── appsscript.json
│ └── tsconfig.json
│
├── .github/
│ └── workflows/
│ ├── deploy-frontend.yml ← triggers on frontend/** changes
│ └── deploy-apps-script.yml ← triggers on apps-script/** changes
│
├── README.md
├── ARCHITECTURE.md
├── CONTRIBUTING.md
└── PLAN.md
This project uses credentials across three locations: Google Apps Script Script Properties, GitHub Actions Secrets, and user devices (localStorage + 1Password).
Set these manually in the Apps Script editor under Project Settings → Script Properties.
| Property Key | Value | Set By | Notes |
|---|---|---|---|
AUTH_TOKEN |
Shared secret string | Manual (once) | Must match what users enter on first login |
CLAUDE_API_KEY |
Anthropic API key | Manual (once) | Never exposed to frontend |
CASHFLOW_FOLDER_ID |
Google Drive folder ID | Manual (once) | ID of the Cash flow parent folder — from its Drive URL |
sheetId_{year} |
Google Sheet ID | Auto-populated | Discovered on first request per year, persists forever. e.g. sheetId_2026 |
To get CASHFLOW_FOLDER_ID: open the Cash flow folder in Google Drive and copy the ID from the URL:
https://drive.google.com/drive/folders/[CASHFLOW_FOLDER_ID]
To get your Anthropic API key: visit console.anthropic.com
Set these under Repo Settings → Secrets and Variables → Actions.
| Secret Name | Value | Used By | Notes |
|---|---|---|---|
APPS_SCRIPT_URL |
https://script.google.com/macros/s/xxx/exec |
Frontend build | Baked into Svelte bundle at compile time |
CLASPRC_JSON |
Contents of ~/.clasprc.json |
Apps Script deploy | OAuth token for clasp push; see below for setup |
To generate CLASPRC_JSON:
npx @google/clasp login
cat ~/.clasprc.json | pbcopy # copies to clipboard
Paste the copied content as the value of the CLASPRC_JSON secret in GitHub.
If the CLASPRC_JSON token expires, the Apps Script deploy workflow will fail with clear instructions. To fix: re-run clasp login locally and update the secret.
| Item | Storage | Notes |
|---|---|---|
AUTH_TOKEN |
localStorage (per device) | Entered once on first visit, never re-asked |
AUTH_TOKEN |
1Password | Saved under URL cashflow.yourdomain.com for autofill |
1Password entry setup (both users):
Title: Cash Flow App
URL: cashflow.yourdomain.com
Username: (your name or leave blank)
Password: [AUTH_TOKEN value]
AUTH_TOKEN is never stored in the repository or baked into the build. It is entered by the user on first visit and saved to their device’s localStorage.
APPS_SCRIPT_URL in GitHub SecretsAPPS_SCRIPT_URL and CLASPRC_JSON to repository secretsmain — GitHub Actions handles the restType: CNAME
Host: cashflow
Value: [github-username].github.io
TTL: 3600
cashflow.yourdomain.comSee CONTRIBUTING.md for local dev setup and workflow. See ARCHITECTURE.md for system design details. See PLAN.md for full project plan and decision log.