Skip to content

Repository files navigation

Forecast Magic

Forecast Magic

Forecast Magic is a self-hosted cash-flow forecasting application. It integrates with the Lunch Money API v2 to project a selected account's available-to-spend balance, then applies locally configured Fund Allocations as reservations that do not create or modify Lunch Money transactions.

Forecast Magic is independent software and is not affiliated with, endorsed by, or officially connected with Lunch Money or its developers.

Features

  • Single-account cash-flow projection
  • Actual, pending, future-dated, and recurring Lunch Money activity
  • Recurring occurrence matching and missed-recurring protection
  • Available-to-spend chart and Key Events carousel
  • Account-scoped Fund Allocations with Operating, Reserved, and Sinking types
  • No, full, and capped rollover
  • Lunch Money category drawdown and per-transaction exclusions
  • Admin and read-only Household presentations
  • Admin-only review of likely manual/imported Lunch Money duplicates
  • Read-only financial health audits across Lunch Money, Capital One exports, n8n alerts, and Forecast Magic reservations
  • REST and MCP interfaces for conversational troubleshooting and automation
  • On-demand Admin or Household Daily Financial Highlight PDFs with share, download, and print actions
  • Persistent SQLite configuration for use across browsers and machines
  • Light and dark modes

Screenshots

Cash-Flow Projection and Upcoming Activity

Forecast Magic cash-flow projection and upcoming activity in dark mode

Fund Allocations

Forecast Magic Fund Allocations in dark mode

Requirements

  • Node.js 22 or later
  • npm
  • A Lunch Money API key

Install

git clone https://github.com/pvols79/forecast-magic.git
cd forecast-magic
npm install

Copy .env.example to .env and set at least an Admin password and session secret:

PORT=3000
DATABASE_PATH=./data/app.db
ADMIN_PASSWORD=choose-a-password
SESSION_SECRET=choose-a-long-random-value
REPORTING_API_TOKEN=choose-a-separate-long-random-value
AUDIT_READ_TOKEN=choose-another-long-random-value
AUDIT_INGEST_TOKEN=choose-another-long-random-value
LUNCH_MONEY_API_KEY=

LUNCH_MONEY_API_KEY is optional. If omitted, an Admin can enter the key in the application. The entered key is stored in the installation's local SQLite database. An environment-provided key takes precedence and cannot be cleared from the UI.

Production Run

npm run build
npm start

The application defaults to http://localhost:3000. The Node service serves both the built React application and its local REST API. It creates the SQLite database and runs pending migrations automatically.

Development

Run the backend and Vite in separate terminals:

npm run dev:server
npm run dev

Open http://localhost:5173. Vite proxies /api requests to the backend on port 3000.

Docker

For a standalone installation on the same machine:

cp .env.example .env
docker compose up --build -d

Open http://localhost:3000. By default, the published port is bound only to 127.0.0.1; set FORECAST_MAGIC_BIND_ADDRESS=0.0.0.0 only when direct LAN access is intentional.

For a dedicated Docker server with shared NGINX and Certbot services, use the supplied external-network Compose and NGINX examples. The app publishes no host port in that configuration. See Docker Deployment for both installation paths, HTTPS setup, updates, and backups.

SQLite is stored in the named forecast-magic-data volume at /data/app.db; no Postgres or separate SQLite container is used. HTTPS termination belongs in the optional external reverse proxy.

Back up the volume or database file before upgrades. Application startup applies versioned migrations without deleting existing data.

Admin And Household

When ADMIN_PASSWORD is configured, unauthenticated users receive the Household presentation. The Admin password creates a signed, HTTP-only session cookie. This is intentionally a small shared-password boundary for a trusted local network or VPN, not a multi-user identity system.

Admin sees the same available-to-spend chart and carousel as Household, plus:

  • Latest actual selected-account balance
  • Total currently reserved in Fund Allocations
  • Fund Allocation management
  • Category mappings and transaction exclusions
  • Timezone settings

Funds hidden from Household still reduce the Household available-to-spend value; only their names and details are hidden.

Fund Allocations

Fund Allocations are reservation policy, not transactions. They never create fake financial events and never appear in Upcoming.

Available to Spend = Projected Ledger Balance - Remaining Fund Allocations

Actual matching Lunch Money spending reduces both the account balance and the matching Fund. Real pending or future-dated Lunch Money spending does the same on its transaction date. This prevents reserved spending from reducing available-to-spend twice. A Fund stops at zero, and spending beyond zero reduces available-to-spend normally. Recurring projections reserve ledger cash but do not draw down Funds.

Transactions created manually or through an automation such as n8n and assigned to a Plaid account do not alter Lunch Money's bank-supplied balance. Tag a manually created placeholder LM Manual; tag an automation placeholder Forecast Magic Pending. Forecast Magic applies these tagged manual and api entries as opening adjustments when dated today or earlier. Native pending transactions and Lunch Money source recurring are also opening adjustments. Untagged past manual/API entries are treated as already included. When Plaid later imports the real transaction, Duplicate Review keeps the imported row and deletes the placeholder; the adjustment then disappears. An imported, settled row does not become an extra adjustment if it inherits these tags. Forecast Magic intentionally does not hide unresolved duplicate pairs because they represent the current Lunch Money data and require review.

Every future periodic boundary adds one flat allocation to the available-to-spend projection. For example, a $125 Weekly Fuel Fund adds another $125 commitment each week across the chart horizon. This is linear recurring commitment, not exponential growth. Rollover separately controls how much actually unused period balance remains available in the next period; it is not required for future allocations to appear in the forecast.

Only the current rollover checkpoint is persisted for each Fund. When a period advances, that row is overwritten. Ended Fund periods are not retained as reporting history and are not included in future projections. Actual transaction detail remains live in Lunch Money.

All period boundaries use a server-stored IANA timezone. Lunch Money's v2 user response does not expose a timezone, so the browser timezone is detected on first use and then shared by every browser using that installation.

Lunch Money API v2

The local Node service uses:

  • GET /v2/manual_accounts
  • GET /v2/plaid_accounts
  • GET /v2/categories?format=flattened&is_group=false
  • GET /v2/tags
  • GET /v2/recurring, with a compatibility fallback to /v2/recurring_items
  • GET /v2/transactions?include_pending=true

Automation-created placeholders on a synced account must carry a Lunch Money tag named Forecast Magic Pending. Older n8n_proc and N8N Pending tags do not trigger forecast deductions. Forecast Magic applies those tagged rows, and native Lunch Money pending rows, until Duplicate Review retains the imported transaction and removes the placeholder. An api transaction source by itself is not treated as pending, because that source remains on historical transactions after they have posted.

Lunch Money v2 transactions provide category IDs rather than hydrated category details. Fund Allocations store those category IDs, while category names are loaded separately for the Admin UI.

Fund types:

  • Operating reserves a configured amount each Weekly, Monthly, Quarterly, or Yearly period. Category transactions draw down the current period. Rollover can be disabled, full, or capped.
  • Reserved keeps an editable all-time amount set aside. Categories and a goal are optional.
  • Sinking carries its balance forward. It can receive automatic periodic allocations, and an optional goal caps those allocations. If category spending lowers the balance, automatic allocations resume at the next period boundary until the goal is restored.

The transaction detail button lists every qualifying transaction in the current period, including the transaction that exhausts an allocation and later transactions that are over budget. Shared Fund Allocations expose this read-only detail in Household view; only Admin can exclude or re-include a transaction.

Financial Analytics API

GET /api/analytics/overview?accountKey=plaid:123 exposes reusable structured cash-position, recurring-attention, spending-trend, unallocated-spending, and Household Fund card data. It always calculates a six-month projection independently of the UI horizon. See Reporting Readiness Audit for definitions and the metric matrix.

For automation, GET /api/reporting/daily-highlight?accountKey=plaid:123&view=admin exposes the same calculations as a versioned, consolidated JSON report, including the complete six-month daily projection series. It requires a dedicated REPORTING_API_TOKEN Bearer credential and never accepts the Lunch Money API key as an automation credential. Schema 1.2 includes report context, recurring urgency, six-month summary metrics, explicit Fund visibility, and role-aware filtering. See Reporting API for n8n configuration and the response contract.

The Daily Highlight also includes a read-only count and summary of High- and Medium-confidence duplicate candidates. Detection, review, metadata merging, and destructive resolution remain Admin-only. See Duplicate Review for the matching and safety boundaries.

Financial Health Audit

POST /api/financial-audit/runs creates an immutable, account-scoped health snapshot. It compares current Lunch Money data with optional Capital One CSV and n8n alert evidence, reports stale or missing imports, transaction changes, tag compliance, duplicate candidates, source totals, Fund reservations, missed-recurring adjustments, and any unexplained balance difference.

The audit is advisory and non-destructive. It does not connect directly to Plaid, change Lunch Money, hide unresolved transactions from the forecast, or automatically resolve findings. Missing bank transactions are asserted only when current Capital One evidence covers the date being checked.

The same read-only capabilities are available to compatible conversational clients through the Streamable HTTP MCP endpoint at /mcp. Use the dedicated AUDIT_READ_TOKEN; evidence uploads use a separate AUDIT_INGEST_TOKEN that should never be given to ChatGPT. See Financial Health Audit for setup, REST examples, n8n integration, MCP tools, security boundaries, and ChatGPT connectivity constraints.

The Share Report menu requests a fresh PDF for the selected account and active Admin or Household view. It can open the native file-share sheet, download the PDF, or open the browser print dialog. The PDF is streamed from memory and uses the same report model as the JSON API.

The adapter normalizes Lunch Money's transaction signs once:

  • Internal positive amount: money entering the selected account
  • Internal negative amount: money leaving the selected account

Manual and Plaid IDs remain separate namespaces through compound account keys such as manual:123 and plaid:123.

Testing

npm test
npm run lint
npm run build

Tests cover the ledger projection, sign normalization, Fund drawdown, overspending, period anchors, rollover, account isolation, exclusions, category conflicts, available-to-spend calculations, financial-audit normalization and matching, REST/MCP access boundaries, and SQLite persistence.

Privacy

Forecast Magic is self-hosted. Its Node server and SQLite database run on the computer or private server where the user installs it. The application does not send Fund Allocation configuration to a hosted Forecast Magic service. Financial API requests go from the self-hosted application to Lunch Money.

Do not commit .env, API keys, database files, or the persistent data directory.

Origins and Attribution

Forecast Magic began as a derivative of Wesley Ceraso's cashflow-app.

The original project and this derivative are distributed under the MIT License. The original copyright and permission notice are preserved in LICENSE.

Forecast Magic is independently maintained and is not affiliated with, endorsed by, or officially connected with Lunch Money or its developers. Lunch Money is referenced only to describe API compatibility.

License

Distributed under the MIT License. See LICENSE.

Releases

Packages

Contributors

Languages