{"id":50359240,"url":"https://github.com/breezinstein/future-sight","last_synced_at":"2026-05-30T00:03:15.798Z","repository":{"id":359078601,"uuid":"1244242581","full_name":"breezinstein/future-sight","owner":"breezinstein","description":"Self-hosted, household-shared investment \u0026 wealth scenario planner — project net worth, model what-if events, compare scenarios. React 19 + Express 5 + SQLite, single Docker container.","archived":false,"fork":false,"pushed_at":"2026-05-20T10:08:21.000Z","size":216,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-20T12:47:27.459Z","etag":null,"topics":["docker","finance","homelab","household","personal-finance","react","scenario-planning","self-hosted","sqlite","typescript","wealth-planner"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/breezinstein.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-20T05:02:33.000Z","updated_at":"2026-05-20T10:08:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/breezinstein/future-sight","commit_stats":null,"previous_names":["breezinstein/future-sight"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/breezinstein/future-sight","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breezinstein%2Ffuture-sight","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breezinstein%2Ffuture-sight/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breezinstein%2Ffuture-sight/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breezinstein%2Ffuture-sight/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/breezinstein","download_url":"https://codeload.github.com/breezinstein/future-sight/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/breezinstein%2Ffuture-sight/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33675019,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","finance","homelab","household","personal-finance","react","scenario-planning","self-hosted","sqlite","typescript","wealth-planner"],"created_at":"2026-05-30T00:03:15.712Z","updated_at":"2026-05-30T00:03:15.781Z","avatar_url":"https://github.com/breezinstein.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🔭 Future Sight\n\nA self-hosted, household-shared **investment and wealth scenario planner**. Project net worth over time, model \"what-if\" events (lump sums, withdrawals, rate changes), and compare alternative scenarios side-by-side. Built for couples and families who've outgrown spreadsheets.\n\n\u003e Inspired by the [`homedash`](https://github.com/breezinstein/homedash) project for self-hosted homelab UX.\n\n---\n\n## ✨ Features\n\n### 🏠 Household collaboration\n- Multi-user with role-based access (**owner**, **editor**, **viewer**)\n- Shared plans, activity log of who changed what\n- Lightweight email + password auth, sessions stored in SQLite\n\n### 📊 Scenario planning\n- One **base** scenario per household + unlimited \"what-if\" clones\n- Clone any scenario to fork your future\n- Side-by-side **comparison view** with overlay charts and diff tables at 5/10/20-year horizons\n\n### 💰 Buckets \u0026 contributions\n- Investment \"pots\" with configurable expected return, currency, target amount, and target date\n- Variable contribution schedules over time (monthly / quarterly / annual)\n- 16 Lucide icons for visual identification\n\n### 📅 Event-driven modelling\n- **Cash-flow events**: one-off deposits, withdrawals, contribution changes\n- **Rate-change events**: override a bucket's return from a date forward\n- **Recurring events** with cadence + end date\n- Toggle events on/off for sensitivity testing without deleting\n\n### 📈 Historical tracking\n- Record actual balances per bucket over time\n- Compare projected vs. actual on the dashboard with drift indicator\n- CSV import of historical actuals\n\n### 🌍 Multi-currency\n- Each bucket has its own currency\n- Live FX conversion to the plan's base currency via **[frankfurter.app](https://frankfurter.app)** (ECB-backed, no API key)\n- Local cache with 6-hour TTL on latest rates; historical rates cached forever\n\n### 🎨 Design\n- Dark-first, Linear-inspired aesthetic\n- Inter typography with tabular figures throughout\n- Generated UI from a Stitch design brief; tokens locked in `src/index.css`\n\n---\n\n## 🚀 Quick start\n\n### Option 1: Pre-built image from GitHub Container Registry (recommended)\n\n```bash\ndocker run -d \\\n  --name future-sight \\\n  -p 3002:3002 \\\n  -v future-sight-data:/app/data \\\n  -e SESSION_SECRET=\"$(openssl rand -hex 32)\" \\\n  --restart unless-stopped \\\n  ghcr.io/breezinstein/future-sight:latest\n```\n\nOr with Docker Compose:\n\n```yaml\nservices:\n  future-sight:\n    image: ghcr.io/breezinstein/future-sight:latest\n    container_name: future-sight\n    restart: unless-stopped\n    ports:\n      - \"3002:3002\"\n    volumes:\n      - future-sight-data:/app/data\n    environment:\n      - NODE_ENV=production\n      - SESSION_SECRET=change-me-to-a-random-string\n      - ALLOW_REGISTRATION=true\nvolumes:\n  future-sight-data:\n    driver: local\n```\n\nOpen \u003chttp://localhost:3002\u003e and create your first account.\n\nImages are published for **linux/amd64** and **linux/arm64** (Raspberry Pi 4+, Apple Silicon, etc.).\n\n### Option 2: Build from source\n\n```bash\ngit clone https://github.com/breezinstein/future-sight.git\ncd future-sight\ndocker compose up -d --build\n```\n\n### Option 3: Local development\n\n```bash\nnpm install\nnpm run dev\n```\n\nThis starts both:\n- Backend API on http://localhost:3002\n- Vite dev server on http://localhost:5174 (with proxy to the API)\n\nOpen \u003chttp://localhost:5174\u003e.\n\n### Option 4: Production build (no Docker)\n\n```bash\nnpm install\nnpm run build\nNODE_ENV=production PORT=3002 SESSION_SECRET=\u003crandom\u003e npm start\n```\n\nOpen \u003chttp://localhost:3002\u003e.\n\n---\n\n## 🛠 Tech stack\n\n| Layer | Choice |\n|---|---|\n| Frontend | React 19, TypeScript, Tailwind CSS 4, Vite |\n| Charts | Recharts |\n| Forms | react-hook-form + zod |\n| Icons | lucide-react |\n| Dates | date-fns |\n| Backend | Node 20, Express 5 (ESM) |\n| Database | SQLite via `better-sqlite3` (WAL mode) |\n| Auth | bcrypt + express-session + connect-sqlite3 |\n| FX | [frankfurter.app](https://frankfurter.app) (ECB-backed) |\n| Testing | Vitest |\n| Deploy | Single Docker container, multi-stage build |\n\n---\n\n## 🗄️ Data model\n\n```\nusers\nplans (created_by) ──┬── plan_members (role)\n                     └── scenarios (is_base, cloned_from)\n                          ├── buckets (currency, return, target)\n                          │    ├── contribution_schedules\n                          │    └── actuals\n                          └── events (cash-flow \u0026 rate-change)\nfx_cache    audit_log\n```\n\nAll updates to plan / scenario data bump a `version` counter on the plan for cheap polling-based sync between household members (homedash-style).\n\n---\n\n## 🔐 Security notes\n\n- Passwords hashed with **bcrypt** (cost 12).\n- Sessions stored server-side in `data/sessions.db`. The cookie holds only an opaque session ID.\n- Set `TRUST_PROXY=true` when running behind a TLS-terminating reverse proxy so secure cookies are issued.\n- Lock down new account registration with `ALLOW_REGISTRATION=false` (the bootstrap user can still be created when the user table is empty).\n- The frankfurter.app API is the only external dependency. Disable network egress if you don't need multi-currency.\n\n---\n\n## 🧪 Tests\n\n```bash\nnpm test                # run the projection engine tests\nnpm run test:watch      # watch mode\n```\n\nThe projection engine has 11 tests covering compounding, contributions, deposits, withdrawals, rate changes, and milestone detection.\n\n---\n\n## 📜 API reference (selected)\n\n```\nPOST   /api/auth/signup            # create user + default plan + base scenario\nPOST   /api/auth/login\nPOST   /api/auth/logout\nGET    /api/auth/me\n\nGET    /api/plans                  # list my plans\nPOST   /api/plans                  # create plan\nGET    /api/plans/:id              # plan + members + scenarios\nGET    /api/plans/:id/activity     # audit log\nGET    /api/plans/:id/members\nPOST   /api/plans/:id/members\nPOST   /api/plans/:id/compare      # multi-scenario comparison\n\nGET    /api/plans/:id/scenarios\nPOST   /api/plans/:id/scenarios\nGET    /api/scenarios/:id\nPATCH  /api/scenarios/:id\nDELETE /api/scenarios/:id\nPOST   /api/scenarios/:id/clone\nGET    /api/scenarios/:id/projection\nGET    /api/scenarios/:id/export?type=actuals|events|contributions\n\nPOST   /api/scenarios/:id/buckets\nGET    /api/buckets/:id\nPATCH  /api/buckets/:id\nDELETE /api/buckets/:id\nPOST   /api/buckets/:id/contributions\nPOST   /api/buckets/:id/actuals\nPOST   /api/buckets/:id/actuals/import\n\nPOST   /api/scenarios/:id/events\nPATCH  /api/events/:id\nDELETE /api/events/:id\n\nGET    /api/fx/currencies\nGET    /api/fx/rate?base=USD\u0026quote=EUR\n```\n\n---\n\n## 📁 Project layout\n\n```\nfuture-sight/\n├── server/\n│   ├── index.js              # Express entry\n│   ├── db/\n│   │   ├── database.js       # better-sqlite3 setup + WAL\n│   │   └── schema.sql        # tables, indexes, triggers\n│   ├── lib/\n│   │   ├── auth.js           # bcrypt, session middleware\n│   │   ├── audit.js          # audit log writer\n│   │   ├── projection.js     # projection engine\n│   │   ├── fx.js             # frankfurter.app + cache\n│   │   └── csv.js            # tiny CSV parser/emitter\n│   └── routes/               # auth, plans, scenarios, buckets, events, ...\n├── src/\n│   ├── App.tsx               # router\n│   ├── main.tsx              # ReactDOM + providers\n│   ├── index.css             # Tailwind 4 @theme tokens\n│   ├── api/                  # typed fetch client\n│   ├── components/           # AppLayout, Sidebar, BucketEditor, EventEditor, ...\n│   ├── context/              # AuthContext, ToastContext\n│   ├── hooks/\n│   ├── lib/format.ts         # currency/date helpers\n│   ├── pages/                # Dashboard, ScenarioDetail, ScenarioCompare, ...\n│   └── types.ts              # shared types\n├── tests/\n│   └── projection.test.js    # projection engine tests\n├── data/                     # SQLite DB + sessions DB (mounted volume in Docker)\n├── Dockerfile\n├── docker-compose.yml\n└── entrypoint.sh\n```\n\n---\n\n## 🗺️ Roadmap / nice-to-haves\n\nThese are intentionally out of scope for v1 but would be useful next steps:\n\n- [ ] Email-based household invites (vs. requiring the member to sign up first)\n- [ ] CSV column-mapping wizard (currently expects fixed column names)\n- [ ] Server-Sent Events for live sync between concurrent editors\n- [ ] Daily-snapshot backups with retention policy\n- [ ] Inflation toggle (real vs. nominal projections)\n- [ ] Tax modelling\n- [ ] Bank/brokerage account sync (explicitly out of scope per design)\n\n---\n\n## 📄 License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbreezinstein%2Ffuture-sight","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbreezinstein%2Ffuture-sight","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbreezinstein%2Ffuture-sight/lists"}