Retirement Simulator That Shows Its Work
A privacy-first, Monte Carlo simulation-based retirement planning tool that helps individuals determine if their retirement plan will work. Built with transparency and statistical accuracy in mind, this tool honestly discloses its limitations rather than creating false confidence.
๐ Try the live demo โ no install, runs entirely in your browser
"Tell me what you'll have AT retirement, and I'll tell you if it will last."
This tool focuses exclusively on the retirement phaseโno pre-retirement accumulation modeling. Users input their projected retirement balances, and the simulator models whether those assets will sustain them through retirement.
- ๐ฒ Monte Carlo Simulation โ 10,000 runs with randomized market returns
- ๐ Probabilistic Results โ success rate and outcome distribution (10th/50th/90th percentiles)
- ๐ฐ HSA Integration โ tax-free healthcare coverage, with age-65+ flexibility
- ๐ฅ Phase-Based Spending โ Go-Go, Slow-Go, and No-Go years
- ๐ณ Multiple Income Sources โ Social Security (with earnings test), pensions, part-time work, rental
- ๐ Privacy-First โ no server, no accounts, no tracking; everything runs in your browser
- ๐พ Scenario Management โ save and compare scenarios in browser
localStorage
Early retirees, the FIRE community, and DIY planners who want transparent, statistically honest projections.
Read this before trusting a number. The app's Disclosures tab shows the same list with your own figures filled in โ none of it is buried in a footnote.
What it models โ US federal taxes for single and married filing jointly filers ยท state income tax for 13 states (the nine with no individual income tax, plus Georgia's age-tiered retirement exclusion, Virginia's means-tested age deduction, California's brackets-by-status, credit-based exemption, and surtax, and New York's source-dependent retirement benefit and benefit-recapture brackets) ยท Social Security (claiming age, COLA, earnings test, provisional-income taxability) ยท RMDs from age 75 ยท Medicare premiums and IRMAA ยท pre-Medicare healthcare ยท HSA (incl. age-65+ flexibility) ยท pensions, part-time work, and rental income ยท phase-based spending (Go-Go / Slow-Go / No-Go) ยท two active withdrawal strategies โ standard priority order and tax-smart deduction-floor filling (a third, gap-year Roth conversions, is scaffolded but disabled).
What it deliberately does not model โ pre-retirement accumulation ยท state income tax for the other 38 states (fold your rate into the marginal rate yourself) ยท ACA subsidies for pre-Medicare coverage ยท long-term care (often the largest single retirement risk) ยท the survivor's penalty for couples ยท per-spouse accounts (couples' balances are pooled) ยท variable inflation ยท dynamic spending guardrails ยท fat-tail crashes ยท fees and transaction costs ยท home equity and mortgages ยท non-income state and local taxes (sales, property, excise) โ a no-income-tax state is not necessarily a low-tax state.
Key simplifications โ one marginal rate above the standard deduction rather than the full 10โ37% brackets ยท long-term capital gains taxed at that same flat rate (no 0/15/20% brackets) ยท fixed life expectancy, not a mortality distribution ยท all accounts share one market shock per year (perfectly correlated) ยท annual returns capped at ยฑ50% ยท IRMAA estimated by you rather than derived from MAGI.
Several of these gaps are open, well-scoped contribution opportunities โ see CONTRIBUTING.md.
- React 19 + TypeScript 5 โ UI and type-safe logic
- Vite 8 โ build tool and dev server (Rolldown bundler)
- React Router 7 โ client-side routing (Landing โ Wizard โ Results โ Scenarios/Compare)
- Tailwind CSS 3 + shadcn/ui (Radix UI primitives) โ styling and components
- Recharts 3 โ charts ยท Lucide โ icons
- React Context API โ global state (no Redux)
- Web Workers โ Monte Carlo runs off the main thread
- localStorage โ scenario persistence (inputs only, not results)
- Vitest 4 โ unit tests for the calculation engine ยท ESLint 9 (flat config) โ linting
Just want to try it? Use the live demo โ no setup required. The steps below are only for running it locally.
- Node.js 20.19+ or 22.12+ (required by Vite 8) and npm v10+
- A current evergreen browser with Web Worker support. Vite 8 builds to
baseline-widely-availablerather than a fixed target, so there is no pinned minimum version
git clone https://github.com/tuangatech/retirement-planner.git
cd retirement-planner
npm install
npm run devThen open http://localhost:5175.
npm run dev # Start Vite dev server (hot reload) on port 5175
npm run build # Type-check + production build to ./dist
npm run preview # Serve the production build locally
npm test # Run the Vitest unit-test suite once
npm run test:watch # Vitest in watch mode (re-runs on change)
npm run lint # ESLint (flat config); errors block, style nits are warnings
npm run type-check # TypeScript check, no emitTesting: unit tests (Vitest) cover the pure calculation modules in
src/lib/calculations/โ taxes, RMDs, Social Security, HSA, withdrawals, the seeded RNG, and the depletion/success metric. They're the fast regression net; the JSON export +verify_plan.pyworkflow below is the end-to-end cross-check. Test files live next to the code they cover as*.test.ts.
Every simulation can be independently re-checked against a Python re-implementation of the expected-value formulas.
- Run a simulation, go to the Annual Breakdown tab, and click JSON to download
retirement-verification-<yyyymmdd-hhmm>.json(contains all inputs, settings, and the p10/p50/p90 year-by-year projections). - Move that file into the
scripts/folder. - Run the verifier (it auto-picks the newest bundle in
scripts/):
python3 scripts/verify_plan.py # newest bundle, median (p50)
python3 scripts/verify_plan.py --percentile p10 # check the worst-case run
python3 scripts/verify_plan.py --json path/to/file.json --tolerance 0.03It re-derives income, expenses, healthcare premiums/out-of-pocket, taxes, and the cash-flow identity from the inputs, and exits non-zero if any deterministic check fails. Downloaded bundles are git-ignored. See docs/7-technical-implementation.md ยง4.2 for details.
Comparing a scenario across states: the State Tax Comparison
page calls the real
calculateTotalTaxes/computeStateTaxDetailed functions directly for one household's income
profile and shows federal + all 13 modeled states' tax side by side, with an expandable breakdown
per state โ no simulation, no saved scenario. See
docs/scenario-tax-comparisons.md for worked examples.
retirement-planner/
โโโ .github/ # CI workflow, issue/PR templates, Dependabot
โโโ src/
โ โโโ components/ # UI: ui/ (shadcn), common/, wizard/, results/,
โ โ # scenarios/, comparison/
โ โโโ contexts/ # InputsContext (inputs), ResultsContext (worker + results)
โ โโโ lib/
โ โ โโโ calculations/ # Calculation engine (see below)
โ โ โโโ storage/ # localStorage scenario management
โ โ โโโ exportVerification.ts # JSON verification bundle
โ โ โโโ constants.ts # Default values, RMD table, SS factors
โ โ โโโ utils.ts, format.ts
โ โโโ workers/ # monte-carlo.worker.ts (simulation engine)
โ โโโ pages/ # LandingPage, WizardPage, ResultsPage,
โ โ # ScenariosPage, ComparisonPage, StateTaxComparisonPage
โ โโโ types/index.ts # All TypeScript interfaces
โ โโโ App.tsx, main.tsx, index.css
โโโ scripts/ # verify_plan.py + downloaded verification bundles
โโโ docs/ # requirements, system-design, technical-implementation, tax-model
โโโ public/ # Static assets
โโโ CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md, LICENSE
โโโ vite.config.ts, tsconfig.json, tailwind.config.js, components.json
โโโ package.json
Routes: / (landing) โ /wizard/:step (4-step wizard) โ /results (5 tabs: Summary, Monte Carlo, Cash Flow, Annual Breakdown, Disclosures); plus /scenarios, /compare, and /state-tax-comparison.
Located in src/lib/calculations/ โ independent, pure, unit-testable modules:
random.ts Seeded RNG (Mulberry32) + Box-Muller normal returns
rmd.ts Required Minimum Distributions (IRS Uniform Lifetime Table)
socialSecurity.ts Claiming-age adjustment, COLA, earnings test
income.ts Pensions, part-time work, rental income
expenses.ts Phase-based spending + healthcare (pre-Medicare & Medicare)
taxes.ts Federal model: provisional-income SS, deduction floor, gross-up
stateTax.ts State model: per-state formulas, also fed to the withdrawal gross-up
stateTaxRules.json Per-state constants w/ primary sources (also read by verify_plan.py)
withdrawals.ts Withdrawal sequencing, RMD enforcement, HSA-first
hsa.ts HSA tax-advantaged withdrawal logic
yearlyProjection.ts Orchestrates all modules for one year
The monte-carlo.worker.ts worker runs 10,000 full simulations and aggregates success rate, percentiles, and the p10/p50/p90 projections. A seeded PRNG makes results reproducible.
Performance: 10,000 runs complete in a few seconds.
The app is a static SPAโno backend or environment variables.
- Import the GitHub repo into Vercel once. Vercel auto-detects the Vite preset and runs the build for you (output
dist) โ you don't build locally. - Every push to
maintriggers a production deploy; other branches and PRs get preview deploys. That's the whole workflowโjust push.
A vercel.json at the repo root rewrites all paths to index.html, so deep links and page refreshes (e.g. /results) don't 404 under the app's client-side routing. It's already includedโno action needed.
Building locally is optional โ Vercel builds on its servers. If you want to sanity-check a production bundle before pushing,
npm run build(andnpm run preview) are available, but they aren't part of the deploy step.
All calculations run in your browserโno server, no accounts, no tracking, no cookies. Scenarios are saved to localStorage (inputs only; results are recalculated on load because they're too large to store).
Configuration lives in vite.config.ts, tsconfig.json, tailwind.config.js, and components.json; no .env is required.
- 1-requirements.md โ product requirements
- 2-federal-tax-model.md โ federal tax logic, constants/sources
- federal-tax-explained.html โ illustrated walkthrough of the federal model: the Social Security provisional-income formula and the resulting "tax torpedo" (open in a browser)
- 3-withdrawal-strategy.md โ withdrawal order and tax-efficiency suggestions
- 4-married-filing-jointly.md โ married-filing-jointly (couples) model and roadmap
- 5-state-tax-model.md โ per-state tax model (13 states live incl. GA, VA, CA, and NY), constants and sources
- state-tax-explained-georgia.html โ illustrated walkthrough of Georgia's retiree tax rules (open in a browser)
- state-tax-explained-virginia.html โ the same for Virginia, incl. the phase-out band that doubles the marginal rate
- state-tax-explained-california.html โ the same for California, incl. the credit-based exemption and the surtax
- state-tax-explained-new-york.html โ the same for New York, incl. the source-dependent retirement benefit and the benefit-recapture brackets
- scenario-tax-comparisons.md โ worked household scenarios compared across states, reproducible on the State Tax Comparison page
- 6-system-design.md โ architecture and design
- 7-technical-implementation.md โ implementation guide (incl. verification workflow)
For contributors: CONTRIBUTING.md ยท CODE_OF_CONDUCT.md ยท SECURITY.md
- No pre-retirement modeling โ focuses only on the retirement phase.
- Simplified tax model โ single effective rate rather than full brackets.
- Mandatory assumptions panel โ honest disclosure of limitations.
- localStorage only โ no cloud sync keeps it simple and private.
- Web Workers โ keep the UI responsive during 2โ10s simulations.
Contributions are welcome โ including from people who don't write code.
- Use it and report what's wrong. Run the live demo with a plausible plan and file anything confusing or incorrect.
- Check the math. Export the JSON bundle and run
python3 scripts/verify_plan.py. If it disagrees with the app, that's a great bug report. - Challenge an assumption. If you know the tax, Medicare, or Social Security rules better than the code does, cite the source and we'll fix it or document the simplification.
- Close a known gap. ACA subsidies, the survivor's penalty, and a state module for any of the
remaining 38 unmodeled states are all documented, unbuilt, and well-scoped โ see
docs/5-state-tax-model.mdfor the pattern the first four states followed.
Read CONTRIBUTING.md first โ the engine has hard invariants (seeded RNG,
exactly two rng() calls per simulated year, pure calculation modules) that are easy to break by
accident. Issues labeled good first issue are safe entry points.
๐ Never post your real financial data in an issue. Use rounded or synthetic numbers โ the exported JSON bundle contains every figure you entered.
By participating you agree to the Code of Conduct.
MIT โ see LICENSE.
Educational projections only; not financial, tax, legal, or investment advice. The software is provided "as is", without warranty of any kind. Consult a qualified professional before making retirement decisions.
Made for the FIRE community
