@retiregolden/planner-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +181 -0
  3. package/package.json +77 -0
  4. package/src/App.tsx +246 -0
  5. package/src/RouteErrorBoundary.tsx +45 -0
  6. package/src/assets/hero.png +0 -0
  7. package/src/assets/react.svg +1 -0
  8. package/src/assets/vite.svg +1 -0
  9. package/src/data/fedInvestClient.ts +113 -0
  10. package/src/data/localStore.ts +42 -0
  11. package/src/data/planOrigin.ts +24 -0
  12. package/src/data/planStore.ts +165 -0
  13. package/src/data/v2Backup.ts +101 -0
  14. package/src/import/ImportPage.tsx +347 -0
  15. package/src/import/ReviewChecklistView.tsx +38 -0
  16. package/src/import/brokerCsv.ts +395 -0
  17. package/src/import/csv.ts +133 -0
  18. package/src/import/genericCsv.ts +224 -0
  19. package/src/import/projectionLab.ts +350 -0
  20. package/src/import/reviewChecklist.ts +33 -0
  21. package/src/import/tenForty.ts +275 -0
  22. package/src/index.css +630 -0
  23. package/src/index.ts +16 -0
  24. package/src/learn/ArticleBody.tsx +78 -0
  25. package/src/learn/ArticlePage.tsx +57 -0
  26. package/src/learn/GlossaryPage.tsx +33 -0
  27. package/src/learn/LearnAboutScreen.tsx +41 -0
  28. package/src/learn/LearnCards.tsx +41 -0
  29. package/src/learn/LearnLink.tsx +91 -0
  30. package/src/learn/LearningCenterPage.tsx +114 -0
  31. package/src/learn/SourcesPage.tsx +98 -0
  32. package/src/learn/components/ArticleFigure.tsx +34 -0
  33. package/src/learn/components/ArticleShell.tsx +86 -0
  34. package/src/learn/components/ComparisonTable.tsx +42 -0
  35. package/src/learn/components/FormulaBlock.tsx +34 -0
  36. package/src/learn/components/PurchasingPowerChart.tsx +41 -0
  37. package/src/learn/components/RelatedArticles.tsx +27 -0
  38. package/src/learn/components/ScenarioCard.tsx +24 -0
  39. package/src/learn/components/SourceList.tsx +23 -0
  40. package/src/learn/components/charts.tsx +21 -0
  41. package/src/learn/content/about-retiregolden.ts +100 -0
  42. package/src/learn/content/aca-premium-tax-credits-and-magi.ts +103 -0
  43. package/src/learn/content/account-types-overview.ts +106 -0
  44. package/src/learn/content/after-tax-estate.ts +111 -0
  45. package/src/learn/content/agi-magi-and-taxable-income.ts +112 -0
  46. package/src/learn/content/appealing-irmaa-ssa-44.ts +95 -0
  47. package/src/learn/content/assumption-general-inflation.ts +82 -0
  48. package/src/learn/content/assumption-healthcare-inflation.ts +85 -0
  49. package/src/learn/content/assumption-heir-tax-rate.ts +79 -0
  50. package/src/learn/content/assumption-investment-returns.ts +90 -0
  51. package/src/learn/content/assumption-longevity-planning-age.ts +78 -0
  52. package/src/learn/content/assumption-recent-magi.ts +83 -0
  53. package/src/learn/content/assumption-social-security-cola.ts +89 -0
  54. package/src/learn/content/assumption-social-security-trust-fund.ts +83 -0
  55. package/src/learn/content/assumption-state-tax-override.ts +79 -0
  56. package/src/learn/content/beneficiaries-and-account-titling.ts +99 -0
  57. package/src/learn/content/break-even-useful-lens.ts +94 -0
  58. package/src/learn/content/building-a-retirement-spending-budget.ts +100 -0
  59. package/src/learn/content/cola-and-inflation-protection.ts +102 -0
  60. package/src/learn/content/divorced-spousal-and-survivor-records.ts +104 -0
  61. package/src/learn/content/dynamic-spending-guardrails.ts +90 -0
  62. package/src/learn/content/earnings-test-before-fra.ts +100 -0
  63. package/src/learn/content/employer-match-and-contribution-order.ts +104 -0
  64. package/src/learn/content/examplePlanArticles.ts +525 -0
  65. package/src/learn/content/fees-expense-ratios-and-compounding-drag.ts +98 -0
  66. package/src/learn/content/fi-number-and-four-percent-rule.ts +64 -0
  67. package/src/learn/content/filling-a-tax-bracket-with-roth-conversions.ts +98 -0
  68. package/src/learn/content/funded-ratio.ts +70 -0
  69. package/src/learn/content/healthcare-after-65.ts +103 -0
  70. package/src/learn/content/healthcare-before-65.ts +104 -0
  71. package/src/learn/content/historical-vs-random-return-models.ts +101 -0
  72. package/src/learn/content/how-assumptions-change-the-answer.ts +105 -0
  73. package/src/learn/content/how-much-can-i-spend.ts +105 -0
  74. package/src/learn/content/how-social-security-is-taxed.ts +95 -0
  75. package/src/learn/content/how-the-optimizer-thinks.ts +102 -0
  76. package/src/learn/content/how-the-optimizer-values-after-tax-estate.ts +97 -0
  77. package/src/learn/content/how-to-model-accumulation.ts +67 -0
  78. package/src/learn/content/how-to-read-a-retirement-projection.ts +115 -0
  79. package/src/learn/content/hsas-and-qualified-medical-expenses.ts +108 -0
  80. package/src/learn/content/hsas-as-retirement-accounts.ts +101 -0
  81. package/src/learn/content/inflation-risk.ts +98 -0
  82. package/src/learn/content/inherited-ira-10-year-rule.ts +105 -0
  83. package/src/learn/content/insurance-in-your-retirement-plan.ts +103 -0
  84. package/src/learn/content/irmaa-two-year-lookback.ts +99 -0
  85. package/src/learn/content/long-term-care-costs-and-insurance.ts +103 -0
  86. package/src/learn/content/long-term-care-insurance-as-risk-transfer.ts +98 -0
  87. package/src/learn/content/longevity-risk.ts +99 -0
  88. package/src/learn/content/marginal-vs-effective-tax-rate.ts +98 -0
  89. package/src/learn/content/medicare-part-b-vs-part-d-irmaa.ts +102 -0
  90. package/src/learn/content/mortality-weighted-social-security.ts +113 -0
  91. package/src/learn/content/moving-to-retiregolden.ts +86 -0
  92. package/src/learn/content/niit-high-income-investment-tax.ts +98 -0
  93. package/src/learn/content/ordinary-income-vs-capital-gains.ts +103 -0
  94. package/src/learn/content/paying-conversion-taxes-taxable-vs-ira.ts +102 -0
  95. package/src/learn/content/pensions-and-annuities.ts +101 -0
  96. package/src/learn/content/permanent-life-insurance-in-a-plan.ts +106 -0
  97. package/src/learn/content/pia-aime-and-bend-points.ts +103 -0
  98. package/src/learn/content/planner-overview.ts +106 -0
  99. package/src/learn/content/planning-for-couples-and-survivor-years.ts +108 -0
  100. package/src/learn/content/privacy-what-stays-in-your-browser.ts +99 -0
  101. package/src/learn/content/qcds-qualified-charitable-distributions.ts +101 -0
  102. package/src/learn/content/reading-the-results-page.ts +96 -0
  103. package/src/learn/content/reading-the-social-security-analysis-page.ts +106 -0
  104. package/src/learn/content/real-estate-home-equity-and-debt.ts +100 -0
  105. package/src/learn/content/reports-csv-exports-and-sharing.ts +101 -0
  106. package/src/learn/content/risk-based-guardrails.ts +100 -0
  107. package/src/learn/content/rmds-required-minimum-distributions.ts +100 -0
  108. package/src/learn/content/roth-conversion-basics.ts +104 -0
  109. package/src/learn/content/rsus-and-espp.ts +101 -0
  110. package/src/learn/content/rule-of-55-and-72t.ts +107 -0
  111. package/src/learn/content/savings-rate-biggest-lever.ts +66 -0
  112. package/src/learn/content/seed-your-plan-from-your-tax-return.ts +93 -0
  113. package/src/learn/content/sensitivity-testing-what-changes-the-answer.ts +104 -0
  114. package/src/learn/content/sequence-of-returns-risk.ts +98 -0
  115. package/src/learn/content/social-security-bridge.ts +67 -0
  116. package/src/learn/content/social-security-claiming-age-basics.ts +113 -0
  117. package/src/learn/content/social-security-taxes-vs-benefits.ts +76 -0
  118. package/src/learn/content/spending-profiles-and-the-retirement-smile.ts +92 -0
  119. package/src/learn/content/spousal-and-survivor-benefits.ts +120 -0
  120. package/src/learn/content/ssdi-and-retirement-planning.ts +72 -0
  121. package/src/learn/content/standard-deduction-senior-deduction-and-itemizing.ts +97 -0
  122. package/src/learn/content/state-income-taxes-in-retirement.ts +97 -0
  123. package/src/learn/content/step-up-in-basis.ts +102 -0
  124. package/src/learn/content/survivor-planning-for-couples.ts +110 -0
  125. package/src/learn/content/survivor-spending-in-couple-plans.ts +98 -0
  126. package/src/learn/content/tax-cliffs-and-bracket-edges.ts +105 -0
  127. package/src/learn/content/tax-loss-and-gain-harvesting.ts +99 -0
  128. package/src/learn/content/taxable-brokerage-basis-and-capital-gains.ts +99 -0
  129. package/src/learn/content/three-big-questions-spending-time-risk.ts +103 -0
  130. package/src/learn/content/tips-ladders.ts +92 -0
  131. package/src/learn/content/todays-dollars-vs-future-dollars.ts +107 -0
  132. package/src/learn/content/traditional-vs-roth-contributions.ts +113 -0
  133. package/src/learn/content/troubleshooting-surprising-results.ts +105 -0
  134. package/src/learn/content/trust-fund-haircut-scenarios.ts +101 -0
  135. package/src/learn/content/understanding-monte-carlo-success-rate.ts +118 -0
  136. package/src/learn/content/understanding-your-plan-assumptions.ts +134 -0
  137. package/src/learn/content/using-assumptions-and-provenance.ts +98 -0
  138. package/src/learn/content/using-scenarios-to-compare-choices.ts +99 -0
  139. package/src/learn/content/what-changes-when-you-move-states.ts +141 -0
  140. package/src/learn/content/what-is-fire.ts +65 -0
  141. package/src/learn/content/what-monte-carlo-proves.ts +98 -0
  142. package/src/learn/content/what-retiregolden-models.ts +103 -0
  143. package/src/learn/content/what-retirement-healthcare-really-costs.ts +117 -0
  144. package/src/learn/content/why-95-percent-is-not-a-guarantee.ts +98 -0
  145. package/src/learn/content/why-roth-conversions-raise-other-costs.ts +106 -0
  146. package/src/learn/content/why-small-tax-cliffs-can-matter.ts +109 -0
  147. package/src/learn/content/widows-penalty-and-survivor-brackets.ts +106 -0
  148. package/src/learn/content/withdrawal-order-basics.ts +105 -0
  149. package/src/learn/glossary.ts +191 -0
  150. package/src/learn/inlineMarkdown.tsx +54 -0
  151. package/src/learn/learn.css +537 -0
  152. package/src/learn/learningRegistry.ts +502 -0
  153. package/src/longevity/LongevityResults.tsx +85 -0
  154. package/src/longevity/LongevityWizard.tsx +305 -0
  155. package/src/longevity/constants.ts +15 -0
  156. package/src/longevity/factors.ts +125 -0
  157. package/src/longevity/model.ts +31 -0
  158. package/src/longevity/persistedGuard.ts +129 -0
  159. package/src/longevity/storage.ts +40 -0
  160. package/src/mc/messages.ts +118 -0
  161. package/src/mc/monteCarlo.worker.ts +44 -0
  162. package/src/mc/pool.ts +267 -0
  163. package/src/mc/runRequest.ts +125 -0
  164. package/src/optimize/messages.ts +84 -0
  165. package/src/optimize/optimize.worker.ts +29 -0
  166. package/src/optimize/runOptimize.ts +92 -0
  167. package/src/optimize/runSpendingSolve.ts +47 -0
  168. package/src/optimize/runner.ts +21 -0
  169. package/src/optimize/spendingMessages.ts +44 -0
  170. package/src/optimize/spendingRunner.ts +21 -0
  171. package/src/optimize/spendingSolve.worker.ts +18 -0
  172. package/src/planner/AssumptionsCardPage.tsx +136 -0
  173. package/src/planner/BucketLensCard.tsx +114 -0
  174. package/src/planner/ComparePlansPage.tsx +219 -0
  175. package/src/planner/DisclaimerPage.tsx +88 -0
  176. package/src/planner/HowTestedPage.tsx +159 -0
  177. package/src/planner/LiveStatus.tsx +15 -0
  178. package/src/planner/LongevityModal.tsx +55 -0
  179. package/src/planner/Modal.tsx +97 -0
  180. package/src/planner/MonteCarloPage.tsx +907 -0
  181. package/src/planner/OptimizePage.tsx +611 -0
  182. package/src/planner/PlanContext.tsx +198 -0
  183. package/src/planner/PlanPickerPage.tsx +124 -0
  184. package/src/planner/PlanWorkspace.tsx +290 -0
  185. package/src/planner/ProvenancePanel.tsx +45 -0
  186. package/src/planner/RelocationComparePage.tsx +485 -0
  187. package/src/planner/ReportPage.tsx +375 -0
  188. package/src/planner/ResultsPage.tsx +817 -0
  189. package/src/planner/ScenariosPage.tsx +285 -0
  190. package/src/planner/SocialSecuritySection.tsx +556 -0
  191. package/src/planner/SpendingSolverPage.tsx +512 -0
  192. package/src/planner/SsAnalysisPage.tsx +1134 -0
  193. package/src/planner/SurvivalPercentileModal.tsx +161 -0
  194. package/src/planner/SurvivorTransitionPage.tsx +286 -0
  195. package/src/planner/assumptionsExport.ts +371 -0
  196. package/src/planner/bucketLens.ts +89 -0
  197. package/src/planner/chartFrame.ts +8 -0
  198. package/src/planner/chartStyle.ts +11 -0
  199. package/src/planner/dialogViews.tsx +184 -0
  200. package/src/planner/dialogs.tsx +133 -0
  201. package/src/planner/examples/ExampleLibrary.tsx +189 -0
  202. package/src/planner/examples/ExamplePreviewBanner.tsx +55 -0
  203. package/src/planner/examples/ExamplesPage.tsx +25 -0
  204. package/src/planner/examples/OpenExampleButton.tsx +61 -0
  205. package/src/planner/examples/buildAggressiveSaver.ts +102 -0
  206. package/src/planner/examples/buildAnnuityEstate.ts +137 -0
  207. package/src/planner/examples/buildBaristaFire.ts +115 -0
  208. package/src/planner/examples/buildBracketFillRoth.ts +65 -0
  209. package/src/planner/examples/buildBridgeEarlyRetirement.ts +94 -0
  210. package/src/planner/examples/buildBrokerageNoHsa.ts +109 -0
  211. package/src/planner/examples/buildCoastFire.ts +88 -0
  212. package/src/planner/examples/buildContext.ts +20 -0
  213. package/src/planner/examples/buildEarlyCareerMatch.ts +93 -0
  214. package/src/planner/examples/buildEarlyRetireeAca.ts +61 -0
  215. package/src/planner/examples/buildExampleCouple.ts +103 -0
  216. package/src/planner/examples/buildFixedTargetSpending.ts +74 -0
  217. package/src/planner/examples/buildGlidepathAllocation.ts +131 -0
  218. package/src/planner/examples/buildGuardrailsFlex.ts +120 -0
  219. package/src/planner/examples/buildHsaPropertyDepth.ts +109 -0
  220. package/src/planner/examples/buildHsaStealthRetirement.ts +97 -0
  221. package/src/planner/examples/buildLeanFatFire.ts +109 -0
  222. package/src/planner/examples/buildLtcShock.ts +62 -0
  223. package/src/planner/examples/buildMovingStateTax.ts +53 -0
  224. package/src/planner/examples/buildNoAnnuityBrokerage.ts +92 -0
  225. package/src/planner/examples/buildRmdIrmaa.ts +55 -0
  226. package/src/planner/examples/buildSalaryGrowthEscalation.ts +96 -0
  227. package/src/planner/examples/buildStaticAllocationControl.ts +96 -0
  228. package/src/planner/examples/buildSurvivorYears.ts +62 -0
  229. package/src/planner/examples/buildUnderSavedSingle.ts +51 -0
  230. package/src/planner/examples/exampleCopy.ts +23 -0
  231. package/src/planner/examples/loadExample.ts +90 -0
  232. package/src/planner/examples/registry.ts +313 -0
  233. package/src/planner/explainPanels.tsx +233 -0
  234. package/src/planner/fields.tsx +381 -0
  235. package/src/planner/format.ts +33 -0
  236. package/src/planner/home/DataAndPrivacyCard.tsx +56 -0
  237. package/src/planner/home/GettingStartedPaths.tsx +46 -0
  238. package/src/planner/home/GettingStartedReopener.tsx +32 -0
  239. package/src/planner/home/StartHereLinks.tsx +22 -0
  240. package/src/planner/home/WelcomeHero.tsx +39 -0
  241. package/src/planner/home/YourPlans.tsx +72 -0
  242. package/src/planner/home/importErrorMessage.ts +22 -0
  243. package/src/planner/home/startHereSlugs.ts +7 -0
  244. package/src/planner/home/useHomeData.ts +190 -0
  245. package/src/planner/home/useHomeMode.ts +47 -0
  246. package/src/planner/householdActions.ts +22 -0
  247. package/src/planner/insights/InsightCardView.tsx +340 -0
  248. package/src/planner/insights/InsightsPage.tsx +204 -0
  249. package/src/planner/insights/categoryLabels.ts +11 -0
  250. package/src/planner/learnLinks.ts +85 -0
  251. package/src/planner/marketModelPicker.ts +172 -0
  252. package/src/planner/optimizePageChart.ts +40 -0
  253. package/src/planner/optimizePageClaim.ts +64 -0
  254. package/src/planner/planCompleteness.ts +27 -0
  255. package/src/planner/planContextCore.ts +26 -0
  256. package/src/planner/planner.css +2304 -0
  257. package/src/planner/provenanceLinks.ts +25 -0
  258. package/src/planner/sections/AccountFields.tsx +872 -0
  259. package/src/planner/sections/AccountsSection.tsx +89 -0
  260. package/src/planner/sections/AllocationPanel.tsx +261 -0
  261. package/src/planner/sections/AssumptionsSection.tsx +256 -0
  262. package/src/planner/sections/HouseholdSection.tsx +243 -0
  263. package/src/planner/sections/IncomeFloorSection.tsx +418 -0
  264. package/src/planner/sections/IncomeSection.tsx +170 -0
  265. package/src/planner/sections/InsuranceSection.tsx +362 -0
  266. package/src/planner/sections/SpendingSection.tsx +904 -0
  267. package/src/planner/sections/StrategySection.tsx +349 -0
  268. package/src/planner/sections/UpdateBalancesPanel.tsx +182 -0
  269. package/src/planner/sections/sectionHelpers.ts +48 -0
  270. package/src/planner/sections/shared.tsx +15 -0
  271. package/src/planner/sections.tsx +15 -0
  272. package/src/planner/ssAnalysis.ts +325 -0
  273. package/src/planner/successBand.ts +20 -0
  274. package/src/planner/survivorAnalysis.ts +277 -0
  275. package/src/planner/usStates.ts +19 -0
  276. package/src/planner/useMcSuccessRate.ts +77 -0
  277. package/src/planner/useProjection.ts +63 -0
  278. package/src/relocation/messages.ts +21 -0
  279. package/src/relocation/relocation.worker.ts +18 -0
  280. package/src/relocation/runRelocation.ts +17 -0
  281. package/src/relocation/runner.ts +22 -0
  282. package/src/report/brandingContext.ts +15 -0
  283. package/src/report/downloadReport.ts +34 -0
  284. package/src/report/reportHtml.ts +547 -0
  285. package/src/routes/LearnRoutes.tsx +46 -0
  286. package/src/routes/PlanRoutes.tsx +55 -0
  287. package/src/routes/RouteFallback.tsx +9 -0
  288. package/src/socialSecurity/breakEven.ts +107 -0
  289. package/src/socialSecurity/expectedPv.ts +164 -0
  290. package/src/socialSecurity/explain.ts +92 -0
  291. package/src/socialSecurity/ficaReturn.ts +81 -0
  292. package/src/socialSecurity/persistedSsGuard.ts +138 -0
  293. package/src/socialSecurity/ssFormUtils.ts +48 -0
  294. package/src/socialSecurity/ssaStatementXml.ts +156 -0
  295. package/src/socialSecurity/storage.ts +69 -0
  296. package/src/socialSecurity/survivorSwitching.ts +153 -0
  297. package/src/testSupport/samplePlan.ts +2 -0
  298. package/src/workers/run.ts +45 -0
@@ -0,0 +1,525 @@
1
+ import type { LearningArticle, LearningCategoryId, ArticleBlock, ScenarioAssumption } from '../learningRegistry'
2
+
3
+ function exampleArticle(
4
+ slug: string,
5
+ title: string,
6
+ description: string,
7
+ exampleId: string,
8
+ teaches: string,
9
+ lookFor: string,
10
+ relatedArticles: string[],
11
+ relatedPlannerRoutes: string[],
12
+ category: LearningCategoryId = 'example-plans',
13
+ scenario?: { name: string; assumptions: ScenarioAssumption[]; summary?: string },
14
+ ): LearningArticle {
15
+ const blocks: ArticleBlock[] = [
16
+ { type: 'heading', text: 'Quick Takeaways' },
17
+ {
18
+ type: 'list',
19
+ items: [
20
+ 'Open the linked example in the planner to explore with live numbers.',
21
+ 'Edit freely — the demo stays out of Your plans until you save it.',
22
+ lookFor,
23
+ ],
24
+ },
25
+ ]
26
+
27
+ if (scenario) {
28
+ blocks.push(
29
+ { type: 'heading', text: 'The Household' },
30
+ {
31
+ type: 'scenario',
32
+ name: scenario.name,
33
+ assumptions: scenario.assumptions,
34
+ summary: scenario.summary,
35
+ }
36
+ )
37
+ }
38
+
39
+ blocks.push(
40
+ { type: 'heading', text: 'The Basic Idea' },
41
+ {
42
+ type: 'prose',
43
+ md: teaches,
44
+ },
45
+ { type: 'heading', text: 'Why It Matters In RetireGolden' },
46
+ {
47
+ type: 'prose',
48
+ md: `This example highlights specific modeling capabilities added in recent enhancements. Use it to see how the feature changes outcomes in Results, Monte Carlo, or the optimizer.`,
49
+ },
50
+ { type: 'heading', text: 'What to Look For' },
51
+ {
52
+ type: 'prose',
53
+ md: `Use **Results** for the year-by-year ledger, then **Scenarios**, **Monte Carlo**, or **Optimize** to stress-test the story. The example is a teaching household, not a recommendation for your situation.`,
54
+ },
55
+ { type: 'heading', text: 'Common Mistakes' },
56
+ {
57
+ type: 'list',
58
+ items: [
59
+ 'Do not copy the household numbers directly; use the example to learn which inputs matter.',
60
+ 'Check assumptions before comparing outcomes, especially returns, inflation, healthcare, and tax settings.',
61
+ 'Treat the scenario as an educational model, not as personal tax, investment, or insurance advice.',
62
+ ],
63
+ }
64
+ )
65
+
66
+ return {
67
+ slug,
68
+ title,
69
+ description,
70
+ category,
71
+ tags: ['example-plan', 'worked example', 'planner', 'fire'],
72
+ audience: 'beginner',
73
+ status: 'ready',
74
+ lastReviewed: '2026-07-07',
75
+ reviewCadence: 'stable',
76
+ sourceUrls: [],
77
+ relatedArticles,
78
+ relatedPlannerRoutes,
79
+ currentYearSensitive: false,
80
+ priority: 'P1',
81
+ exampleId,
82
+ blocks,
83
+ }
84
+ }
85
+
86
+ export const exampleCoupleArticle = exampleArticle(
87
+ 'example-couple',
88
+ 'Example couple: the full retirement picture',
89
+ 'A married household two years from retirement — accounts, Social Security, Roth strategy, insurance, and scenarios.',
90
+ 'example-couple',
91
+ 'This is RetireGolden\'s flagship teaching household: diversified accounts, pre-retirement wages, a fill-to-bracket Roth strategy, LTC policies, and side scenarios for a Social Security haircut and higher spending.',
92
+ 'Watch Roth conversions in Strategy, then trace RMDs, taxes, and ending balances in Results.',
93
+ ['planner-overview', 'roth-conversion-basics', 'long-term-care-insurance-as-risk-transfer'],
94
+ ['/plan/:planId/results', '/plan/:planId/strategy', '/plan/:planId/scenarios'],
95
+ )
96
+
97
+ export const exampleUnderSavedSingleArticle = exampleArticle(
98
+ 'example-under-saved-single',
99
+ 'Under-saved single retiree',
100
+ 'When modest savings meet steady spending — depletion year and shortfall warnings.',
101
+ 'under-saved-single',
102
+ 'Jordan is a single retiree with consulting income, Social Security at 67, and spending that outpaces investable assets over time. The lesson is not pessimism — it is seeing *when* the plan runs out and what still funds cash flow.',
103
+ 'Find the depletion year on Results and compare withdrawals from cash, taxable, and traditional accounts.',
104
+ ['how-to-read-a-retirement-projection', 'reading-the-results-page', 'three-big-questions-spending-time-risk'],
105
+ ['/plan/:planId/results', '/plan/:planId/spending'],
106
+ )
107
+
108
+ export const exampleBracketFillRothArticle = exampleArticle(
109
+ 'example-bracket-fill-roth',
110
+ 'Bracket-fill Roth conversions',
111
+ 'Converting up to a tax bracket top while RMDs and QCDs interact.',
112
+ 'bracket-fill-roth',
113
+ 'Morgan and Riley are retired with large traditional IRAs, Social Security, and a strategy to fill the 22% bracket with Roth conversions. QCDs offset part of the RMD tax bite.',
114
+ 'Compare lifetime tax vs ending Roth balance — and watch conversion amounts year by year.',
115
+ ['filling-a-tax-bracket-with-roth-conversions', 'rmds-required-minimum-distributions', 'qcds-qualified-charitable-distributions'],
116
+ ['/plan/:planId/strategy', '/plan/:planId/results'],
117
+ )
118
+
119
+ export const exampleEarlyRetireeAcaArticle = exampleArticle(
120
+ 'example-early-retiree-aca',
121
+ 'Early retiree and the ACA cliff',
122
+ 'Pre-65 healthcare premiums driven by MAGI — and why conversions have a hidden cost.',
123
+ 'early-retiree-aca',
124
+ 'Casey retired before Medicare with marketplace coverage and ACA credits. Consulting income and Roth conversions both flow into MAGI, which can push premiums over the subsidy cliff.',
125
+ 'Read healthcare expense lines before 65 and any ACA cliff warnings on Results.',
126
+ ['aca-premium-tax-credits-and-magi', 'healthcare-before-65', 'why-roth-conversions-raise-other-costs'],
127
+ ['/plan/:planId/spending', '/plan/:planId/results', '/plan/:planId/strategy'],
128
+ )
129
+
130
+ export const exampleRmdIrmaaArticle = exampleArticle(
131
+ 'example-rmd-irmaa',
132
+ 'High balances: RMDs and IRMAA',
133
+ 'Large traditional balances, required distributions, and Medicare surcharges.',
134
+ 'rmd-irmaa',
135
+ 'Dana has a very large IRA entering RMD years. Required withdrawals boost MAGI, which can interact with IRMAA tiers on Medicare premiums. QCDs provide partial relief.',
136
+ 'Trace RMD and QCD columns, then Medicare-related healthcare costs after 65.',
137
+ ['rmds-required-minimum-distributions', 'irmaa-two-year-lookback', 'qcds-qualified-charitable-distributions'],
138
+ ['/plan/:planId/results', '/plan/:planId/accounts'],
139
+ )
140
+
141
+ export const exampleSurvivorYearsArticle = exampleArticle(
142
+ 'example-survivor-years',
143
+ 'Survivor years and the widow\'s penalty',
144
+ 'Unequal Social Security, a pension with survivor benefits, and higher taxes after the first death.',
145
+ 'survivor-years',
146
+ 'Lee and Chris have unequal Social Security and a pension that pays a survivor benefit. When Chris\'s planning age ends first, Lee steps into survivor benefits and single tax brackets — taxes can rise even as total income falls.',
147
+ 'Compare tax and Social Security in the last joint year vs the first survivor year.',
148
+ ['widows-penalty-and-survivor-brackets', 'spousal-and-survivor-benefits', 'planning-for-couples-and-survivor-years'],
149
+ ['/plan/:planId/household', '/plan/:planId/results', '/plan/:planId/social-security-analysis'],
150
+ )
151
+
152
+ export const exampleMovingStateTaxArticle = exampleArticle(
153
+ 'example-moving-state-tax',
154
+ 'Moving in retirement (state tax)',
155
+ 'Mid-plan relocation from Florida to Kentucky changes lifetime tax.',
156
+ 'moving-state-tax',
157
+ 'Avery earns consulting income while living in Florida, then relocates to Kentucky. Federal tax is unchanged, but modeled state tax adds a new layer — compare the base plan to the built-in scenarios.',
158
+ 'Open Scenarios and compare lifetime tax when the move happens sooner vs later.',
159
+ ['state-income-taxes-in-retirement', 'using-scenarios-to-compare-choices'],
160
+ ['/plan/:planId/household', '/plan/:planId/scenarios'],
161
+ )
162
+
163
+ export const exampleLtcShockArticle = exampleArticle(
164
+ 'example-ltc-shock',
165
+ 'Long-term-care shock',
166
+ 'A multi-year care episode and how LTC insurance offsets the hit.',
167
+ 'ltc-shock',
168
+ 'Quinn faces a care episode in late life. Without insurance, the shock drains cash quickly; with an LTC policy, benefits and premiums change the ending estate picture.',
169
+ 'Inspect care-event years on Results and Insurance for premium vs benefit flow.',
170
+ ['long-term-care-insurance-as-risk-transfer', 'long-term-care-costs-and-insurance', 'permanent-life-insurance-in-a-plan'],
171
+ ['/plan/:planId/insurance', '/plan/:planId/results'],
172
+ )
173
+
174
+ export const exampleEarlyCareerMatchArticle = exampleArticle(
175
+ 'example-early-career-match',
176
+ 'Just getting started (Alex)',
177
+ 'Young professional capturing employer match and building basic tax-diversified savings.',
178
+ 'early-career-match',
179
+ 'Alex is starting their career with $65,000 in wages growing at 3% real annually. By contributing $6,000 to their employer 401(k) and capturing the 4% match, plus contributing $3,000 to a Roth IRA, they compound early momentum.',
180
+ 'Verify the employerMatch amount on the Results page and watch wages increase by the raise rate.',
181
+ ['what-is-fire', 'savings-rate-biggest-lever'],
182
+ ['/plan/:planId/income', '/plan/:planId/accounts', '/plan/:planId/results'],
183
+ 'early-investing-fire',
184
+ )
185
+
186
+ export const exampleAggressiveSaverArticle = exampleArticle(
187
+ 'example-aggressive-saver',
188
+ 'Aggressive saver to early retirement (Taylor)',
189
+ 'A high savings rate and time-phased contribution schedules support retirement in 15 years.',
190
+ 'aggressive-saver',
191
+ 'Taylor saves 50% of their gross wages. By maxing out pre-tax and Roth options and scheduling aggressive taxable contributions, they build a portfolio to support their retirement expenses.',
192
+ 'Open Results to inspect the savings rate, FI Target, and the year they cross the FI threshold.',
193
+ ['what-is-fire', 'savings-rate-biggest-lever', 'fi-number-and-four-percent-rule'],
194
+ ['/plan/:planId/results', '/plan/:planId/accounts'],
195
+ 'early-investing-fire',
196
+ )
197
+
198
+ export const exampleCoastFireArticle = exampleArticle(
199
+ 'example-coast-fire',
200
+ 'Coast FIRE (Morgan)',
201
+ 'Morgan front-loads contributions during their 30s and coasts without saving until retirement.',
202
+ 'coast-fire',
203
+ 'Morgan contributes heavily until age 40, then completely stops active savings. Compounding growth carries their portfolio the rest of the way to a full retirement at age 60.',
204
+ 'Open Accounts to check the contribution schedule, and Results to see when traditional IRA coasts to goal.',
205
+ ['what-is-fire', 'fi-number-and-four-percent-rule'],
206
+ ['/plan/:planId/accounts', '/plan/:planId/results'],
207
+ 'early-investing-fire',
208
+ )
209
+
210
+ export const exampleBaristaFireArticle = exampleArticle(
211
+ 'example-barista-fire',
212
+ 'Barista FIRE (Robin)',
213
+ 'Robin leaves their primary career at age 40 and uses part-time income and ACA credits to bridge to age 65.',
214
+ 'barista-fire',
215
+ 'Robin transitions from a high-paying job to a $35,000 part-time barista job at age 40 and trims baseline spending. The part-time work covers much of the gap so the portfolio can keep compounding instead of carrying the whole bridge alone.',
216
+ 'Open Income to see the barista stream, and Results to track the ACA premium tax credits.',
217
+ ['what-is-fire', 'aca-premium-tax-credits-and-magi'],
218
+ ['/plan/:planId/income', '/plan/:planId/results'],
219
+ 'early-investing-fire',
220
+ )
221
+
222
+ export const exampleBridgeEarlyRetirementArticle = exampleArticle(
223
+ 'example-bridge-early-retirement',
224
+ 'Bridge to 59½ (Jordan\'s SEPP)',
225
+ 'Jordan retires at 45 and accesses traditional retirement balances penalty-free using 72(t) payments.',
226
+ 'bridge-early-retirement',
227
+ 'Jordan retires early and sets up a Substantially Equal Periodic Payment (SEPP) series from their traditional IRA. This unlocks early cash flow without the 10% penalty.',
228
+ 'Check the SEPP column in Results and traditional account balance drawdown starting at age 45.',
229
+ ['rule-of-55-and-72t', 'withdrawal-order-basics'],
230
+ ['/plan/:planId/results', '/plan/:planId/accounts'],
231
+ 'early-investing-fire',
232
+ )
233
+
234
+ export const exampleLeanFatFireArticle = exampleArticle(
235
+ 'example-lean-fat-fire',
236
+ 'Lean vs. Fat FIRE (Jessie)',
237
+ 'Comparing minimalist early retirement against a higher-spending lifestyle side-by-side.',
238
+ 'lean-fat-fire',
239
+ 'Jessie compares a baseline $45,000 early retirement budget against a $80,000 Fat FIRE lifestyle scenario, modeling the impact on assets and FI date.',
240
+ 'Open Scenarios to compare the base plan against the Fat FIRE scenario side-by-side.',
241
+ ['what-is-fire', 'fi-number-and-four-percent-rule'],
242
+ ['/plan/:planId/scenarios', '/plan/:planId/results'],
243
+ 'early-investing-fire',
244
+ )
245
+
246
+ export const exampleHsaStealthRetirementArticle = exampleArticle(
247
+ 'example-hsa-stealth-retirement',
248
+ 'Stealth HSA Retirement (Chris)',
249
+ ' Chris maxes out and invests HSA contributions to form a powerful healthcare bridge.',
250
+ 'hsa-stealth-retirement',
251
+ 'Chris uses a triple-tax-advantaged HSA to build health savings. By maxing out contributions and keeping the balance invested, the HSA serves as a key bridge asset.',
252
+ 'Check the HSA contributions and final balance on the Accounts page.',
253
+ ['hsas-as-retirement-accounts', 'hsas-and-qualified-medical-expenses'],
254
+ ['/plan/:planId/accounts', '/plan/:planId/results'],
255
+ 'early-investing-fire',
256
+ )
257
+
258
+ export const exampleSalaryGrowthEscalationArticle = exampleArticle(
259
+ 'example-salary-growth-escalation',
260
+ 'Salary growth and escalation (Dana)',
261
+ 'Dana uses wage growth raises and auto-escalating savings schedules to accelerate FI.',
262
+ 'salary-growth-escalation',
263
+ 'Dana combines a 3% real wage raise rate with an annual 3% escalation on her 401(k) and brokerage contributions to reach FI much earlier.',
264
+ 'Trace wage raises in Income and watch the annual escalation of savings in Results.',
265
+ ['how-to-model-accumulation', 'savings-rate-biggest-lever'],
266
+ ['/plan/:planId/income', '/plan/:planId/accounts', '/plan/:planId/results'],
267
+ 'early-investing-fire',
268
+ )
269
+
270
+ export const exampleGuardrailsFlexArticle = exampleArticle(
271
+ 'example-guardrails-flex-goals',
272
+ 'Guardrails and flexible goals (Riley)',
273
+ 'Riley uses spending guardrails to protect a required floor while allowing adaptive flexible goals and discretionary layers.',
274
+ 'guardrails-flex-goals',
275
+ `Riley plans on $58,000 of annual spending in today's dollars.
276
+
277
+ She sets a required floor of $34,000 that must be protected no matter what the markets do. The remaining spending is discretionary and can be cut or increased.
278
+
279
+ When markets are poor, the guardrails automatically reduce flexible spending to protect the floor. In strong markets, spending can recover.
280
+
281
+ One-time goals can be marked required, target, ideal, or excess, and some are allowed to move or be skipped.`,
282
+ 'Watch guardrailAction and guardrailFactor columns in Results, the split between requiredShortfall and targetShortfall, and the layered success rates in Monte Carlo.',
283
+ ['dynamic-spending-guardrails', 'how-much-can-i-spend'],
284
+ ['/plan/:planId/spending', '/plan/:planId/results', '/plan/:planId/monte-carlo'],
285
+ 'example-plans',
286
+ {
287
+ name: 'The Riley household',
288
+ assumptions: [
289
+ { label: 'Filing status', value: 'Single' },
290
+ { label: 'Retirement age', value: '62' },
291
+ { label: 'Base spending', value: '$58,000 (today\'s dollars)' },
292
+ { label: 'Required floor', value: '$34,000' },
293
+ { label: 'Spending policy', value: 'Withdrawal-rate guardrails (125% upper)' },
294
+ { label: 'Key goals', value: 'Roof (required), trip (movable target), gift (skippable ideal)' },
295
+ { label: 'Investable starting balance', value: '~$505,000' },
296
+ ],
297
+ summary: 'Shows how guardrails protect the must-fund layer while allowing flexible spending and goals to adjust.',
298
+ }
299
+ )
300
+
301
+ export const exampleAnnuityEstateArticle = exampleArticle(
302
+ 'example-annuity-purchases-estate',
303
+ 'Annuity purchases and estate beneficiaries (Jordan & Taylor)',
304
+ 'Couple buys SPIA and QLAC contracts and designates per-account estate beneficiaries to optimize survivor and charitable outcomes.',
305
+ 'annuity-purchases-estate',
306
+ `Jordan and Taylor have substantial traditional IRA balances and want more guaranteed lifetime income.
307
+
308
+ They use part of their savings to purchase a SPIA (non-qualified, cash-funded) that begins payments at 66 and a QLAC (qualified, traditional-funded) that starts at 80.
309
+
310
+ The QLAC premium is excluded from future RMD calculations up to the limit.
311
+
312
+ Each account has its own beneficiary designation: some go to the surviving spouse (rollover treatment), others to charity (untaxed), and some to non-spouse heirs (with tax).`,
313
+ 'Look at the annuity income streams and purchase cash flows in Results, the reduced RMDs from the QLAC, and how the after-tax estate changes based on the beneficiary choices.',
314
+ ['after-tax-estate', 'account-types-overview'],
315
+ ['/plan/:planId/accounts', '/plan/:planId/results', '/plan/:planId/optimize'],
316
+ 'example-plans',
317
+ {
318
+ name: 'The Jordan & Taylor household',
319
+ assumptions: [
320
+ { label: 'Filing status', value: 'Married Filing Jointly' },
321
+ { label: 'SPIA purchase', value: '$220,000 at age 66 (non-qualified)' },
322
+ { label: 'QLAC purchase', value: '$135,000 at age 65 (qualified, deferred)' },
323
+ { label: 'Beneficiary setup', value: 'Mixed: spouse rollover, charity, non-spouse' },
324
+ { label: 'Key goal', value: 'Secure lifetime income + control estate tax treatment' },
325
+ ],
326
+ summary: 'Illustrates trading liquidity for guaranteed income and using per-account beneficiaries to shape the after-tax estate.',
327
+ }
328
+ )
329
+
330
+ export const exampleGlidepathAllocationArticle = exampleArticle(
331
+ 'example-glidepath-allocation',
332
+ 'Glidepath allocation and rebalancing (Morgan)',
333
+ 'Morgan runs a 4-class glidepath allocation across accounts with rebalancing and class-level taxable drag.',
334
+ 'glidepath-allocation',
335
+ `Morgan holds accounts in taxable, traditional, and Roth wrappers.
336
+
337
+ Instead of a single expected return on each account, he assigns target weights to four asset classes: US stocks, international stocks, bonds, and cash.
338
+
339
+ A linear glidepath gradually shifts the taxable account from aggressive (70% stocks) to conservative (30% stocks) over 12 years. Rebalancing happens annually.
340
+
341
+ In the taxable account, bonds generate more interest (taxed every year) while stocks generate qualified dividends and growth. Monte Carlo now applies correlated shocks to the classes rather than a single return.`,
342
+ 'Edit the allocation policy on each account and watch the target weights change over time. Run Monte Carlo with and without the allocation to compare downside percentiles and frontiers.',
343
+ ['assumption-investment-returns', 'reading-the-results-page'],
344
+ ['/plan/:planId/accounts', '/plan/:planId/assumptions', '/plan/:planId/monte-carlo', '/plan/:planId/insights'],
345
+ 'example-plans',
346
+ {
347
+ name: 'The Morgan household',
348
+ assumptions: [
349
+ { label: 'Filing status', value: 'Single' },
350
+ { label: 'Taxable allocation', value: 'Linear glide 70/30 stocks → 30/70 over 12 years, annual rebalance' },
351
+ { label: 'Traditional 401(k)', value: 'Staged allocation, starts aggressive' },
352
+ { label: 'Roth', value: 'Static 50/50 stocks/bonds' },
353
+ { label: 'Starting investable', value: '~$1.465M across accounts' },
354
+ ],
355
+ summary: 'Demonstrates moving from single-return assumptions to class-based allocation, glidepaths, rebalancing, and class-aware Monte Carlo.',
356
+ }
357
+ )
358
+
359
+ export const exampleHsaPropertyDepthArticle = exampleArticle(
360
+ 'example-hsa-property-depth',
361
+ 'HSA medical sub-ledger and home sale (Harper)',
362
+ 'Harper uses an HSA with explicit medical cap + reimburse-later plus a primary residence sale with basis, selling costs, and §121 treatment.',
363
+ 'hsa-property-depth',
364
+ `Harper contributes the maximum to an HSA and invests it for growth.
365
+
366
+ She sets the HSA to cap qualified medical withdrawals by actual modeled healthcare costs plus any accumulated "reimburse later" balance.
367
+
368
+ A primary residence with a low cost basis is scheduled for sale in 7 years. The plan tracks the §121 exclusion, selling costs, and a small amount of depreciation recapture.
369
+
370
+ A traditional IRA holds nondeductible basis that will affect the taxable portion of any conversions or withdrawals.`,
371
+ 'Look at the HSA withdrawal treatment fields, the qualified vs taxable split on HSA distributions, the exact gain calculation on the home sale, and the pro-rata impact on IRA conversions.',
372
+ ['hsas-as-retirement-accounts', 'hsas-and-qualified-medical-expenses', 'account-types-overview'],
373
+ ['/plan/:planId/accounts', '/plan/:planId/results'],
374
+ 'example-plans',
375
+ {
376
+ name: 'The Harper household',
377
+ assumptions: [
378
+ { label: 'Filing status', value: 'Single' },
379
+ { label: 'HSA balance + contribs', value: '$48,000 initial + $4,150/year, invested' },
380
+ { label: 'HSA treatment', value: 'Cap by medical expenses + reimburse-later enabled' },
381
+ { label: 'Home sale', value: '$385k value, $172k basis, 6% costs, primary residence + recapture' },
382
+ { label: 'Traditional IRA basis', value: '$68,000 nondeductible' },
383
+ ],
384
+ summary: 'Shows precise HSA qualified withdrawal limits and accurate tax treatment on a primary residence sale.',
385
+ }
386
+ )
387
+
388
+ export const exampleFixedTargetSpendingArticle = exampleArticle(
389
+ 'example-fixed-target-spending',
390
+ 'Fixed target spending control (Riley)',
391
+ 'Classic fixed spending control — identical balances and lifestyle target to the guardrails example but without any required floor or dynamic policy.',
392
+ 'fixed-target-spending',
393
+ `This is the identical Riley household and spending target as the guardrails version, but with no required floor and no guardrail policy.
394
+
395
+ All spending is treated as a single target. In bad markets the full amount is at risk.
396
+
397
+ Compare this plan directly with the guardrails version using the Compare feature to isolate the effect of the spending policy.`,
398
+ 'Open both examples, then use Compare Plans and look at Monte Carlo success rates (overall vs any required floor distinction) and when each version depletes.',
399
+ ['dynamic-spending-guardrails'],
400
+ ['/plan/:planId/spending', '/plan/:planId/results', '/plan/:planId/monte-carlo'],
401
+ 'example-plans',
402
+ {
403
+ name: 'The Riley household (fixed target version)',
404
+ assumptions: [
405
+ { label: 'Filing status', value: 'Single' },
406
+ { label: 'Retirement age', value: '62' },
407
+ { label: 'Base spending', value: '$58,000 (today\'s dollars)' },
408
+ { label: 'Spending policy', value: 'Fixed target (no guardrails)' },
409
+ { label: 'Key difference', value: 'No required floor; full spending at risk' },
410
+ ],
411
+ summary: 'Control case for the guardrails example. Same starting point, classic all-or-nothing spending target.',
412
+ }
413
+ )
414
+
415
+ export const exampleNoAnnuityBrokerageArticle = exampleArticle(
416
+ 'example-no-annuity-brokerage',
417
+ 'Brokerage only control (Jordan & Taylor)',
418
+ 'Same household and capital as the annuity example, except the money stays in cash/traditional instead of purchasing SPIA and QLAC.',
419
+ 'no-annuity-brokerage',
420
+ `This is the identical Jordan & Taylor household, but the $355,000 that would have purchased the SPIA and QLAC remains invested in cash and traditional accounts.
421
+
422
+ They keep full liquidity and control over the capital, but have no guaranteed lifetime income streams from the annuities.
423
+
424
+ Compare this version side-by-side with the annuity-purchases example to see the trade-off between liquidity and income security plus estate effects.`,
425
+ 'Compare the two plans in Results (income streams and RMDs) and in the estate metric. Note the higher early balances but lack of annuity income.',
426
+ ['after-tax-estate'],
427
+ ['/plan/:planId/accounts', '/plan/:planId/results'],
428
+ 'example-plans',
429
+ {
430
+ name: 'The Jordan & Taylor household (no annuity version)',
431
+ assumptions: [
432
+ { label: 'Filing status', value: 'Married Filing Jointly' },
433
+ { label: 'Key difference', value: 'Annuity premium money kept in cash + traditional' },
434
+ { label: 'Cash balance', value: 'Higher by $220k vs annuity version' },
435
+ { label: 'Traditional balance', value: 'Higher by $135k vs annuity version' },
436
+ { label: 'Guaranteed income', value: 'None from purchased annuities' },
437
+ ],
438
+ summary: 'Control case showing the pre-purchase capital position for direct comparison with the annuity version.',
439
+ }
440
+ )
441
+
442
+ export const exampleStaticAllocationControlArticle = exampleArticle(
443
+ 'example-static-allocation-control',
444
+ 'Static allocation control (Morgan)',
445
+ 'Identical starting balances to the glidepath example, but using a single default return with no class allocation or rebalancing.',
446
+ 'static-allocation-control',
447
+ `This is the identical Morgan household and account balances as the glidepath version.
448
+
449
+ Every account uses a single flat expected return instead of class weights, glidepaths, and rebalancing.
450
+
451
+ Monte Carlo applies a single-factor shock rather than correlated class shocks.
452
+
453
+ Load both this plan and the glidepath version, then use Compare or run Monte Carlo on each to see the impact of the allocation model on risk metrics.`,
454
+ 'Compare Monte Carlo outcomes (especially 10th-percentile estate, depletion probability, and frontiers) between this flat-return version and the allocated glidepath version.',
455
+ ['assumption-investment-returns', 'reading-the-results-page'],
456
+ ['/plan/:planId/accounts', '/plan/:planId/monte-carlo'],
457
+ 'example-plans',
458
+ {
459
+ name: 'The Morgan household (static allocation version)',
460
+ assumptions: [
461
+ { label: 'Filing status', value: 'Single' },
462
+ { label: 'Key difference', value: 'No allocation policies; single 5% return per account' },
463
+ { label: 'Starting investable', value: 'Same as glidepath version (~$1.465M)' },
464
+ { label: 'Rebalancing', value: 'None' },
465
+ { label: 'MC model', value: 'Single-factor returns (no class correlation)' },
466
+ ],
467
+ summary: 'Control case with identical dollars but classic single-return assumptions for fair comparison.',
468
+ }
469
+ )
470
+
471
+ export const exampleBrokerageNoHsaArticle = exampleArticle(
472
+ 'example-brokerage-no-hsa',
473
+ 'Brokerage instead of HSA control (Harper)',
474
+ 'The money that would be in the HSA (initial balance + contribution rate) is held in taxable brokerage instead. Other elements (property, traditional IRA) kept for fair comparison.',
475
+ 'brokerage-no-hsa',
476
+ `This is the identical Harper household and other accounts (including the home sale and traditional IRA with basis).
477
+
478
+ The $48,000 initial balance plus the $4,150 annual contribution capacity that went into the HSA is instead held in a taxable brokerage account.
479
+
480
+ There is no medical-expense cap or triple-tax treatment. Withdrawals are subject to ordinary tax (and potential penalty before 65).
481
+
482
+ Compare this version directly with the HSA version to see the difference in tax drag and qualified medical access.`,
483
+ 'Compare the tax on account withdrawals and the final balances between this brokerage version and the HSA version. Note the lack of medical-qualified treatment.',
484
+ ['hsas-as-retirement-accounts'],
485
+ ['/plan/:planId/accounts', '/plan/:planId/results'],
486
+ 'example-plans',
487
+ {
488
+ name: 'The Harper household (brokerage version)',
489
+ assumptions: [
490
+ { label: 'Filing status', value: 'Single' },
491
+ { label: 'Key difference', value: 'HSA dollars moved to taxable brokerage' },
492
+ { label: 'Brokerage balance', value: 'Higher by ~$48k + ongoing contribs' },
493
+ { label: 'Tax treatment', value: 'Ordinary income on growth and withdrawals' },
494
+ { label: 'Medical cap', value: 'None' },
495
+ ],
496
+ summary: 'Control case placing the same dollars in a taxable account instead of the HSA.',
497
+ }
498
+ )
499
+
500
+ export const EXAMPLE_PLAN_ARTICLES = [
501
+ exampleCoupleArticle,
502
+ exampleUnderSavedSingleArticle,
503
+ exampleBracketFillRothArticle,
504
+ exampleEarlyRetireeAcaArticle,
505
+ exampleRmdIrmaaArticle,
506
+ exampleSurvivorYearsArticle,
507
+ exampleMovingStateTaxArticle,
508
+ exampleLtcShockArticle,
509
+ exampleEarlyCareerMatchArticle,
510
+ exampleAggressiveSaverArticle,
511
+ exampleCoastFireArticle,
512
+ exampleBaristaFireArticle,
513
+ exampleBridgeEarlyRetirementArticle,
514
+ exampleLeanFatFireArticle,
515
+ exampleHsaStealthRetirementArticle,
516
+ exampleSalaryGrowthEscalationArticle,
517
+ exampleGuardrailsFlexArticle,
518
+ exampleAnnuityEstateArticle,
519
+ exampleGlidepathAllocationArticle,
520
+ exampleHsaPropertyDepthArticle,
521
+ exampleFixedTargetSpendingArticle,
522
+ exampleNoAnnuityBrokerageArticle,
523
+ exampleStaticAllocationControlArticle,
524
+ exampleBrokerageNoHsaArticle,
525
+ ]
@@ -0,0 +1,98 @@
1
+ /**
2
+ * "Fees, expense ratios, and compounding drag" - an Accounts and Saving P2 article.
3
+ */
4
+
5
+ import type { LearningArticle } from '../learningRegistry'
6
+
7
+ export const feesExpenseRatiosCompoundingDragArticle: LearningArticle = {
8
+ slug: 'fees-expense-ratios-and-compounding-drag',
9
+ title: 'Fees, expense ratios, and compounding drag',
10
+ description: 'Why a small annual fee can quietly cost a large share of growth.',
11
+ category: 'accounts-saving',
12
+ tags: ['fees', 'expense ratio', 'returns', 'compounding', 'investment costs', 'assumptions'],
13
+ audience: 'beginner',
14
+ status: 'ready',
15
+ lastReviewed: '2026-06-20',
16
+ reviewCadence: 'stable',
17
+ sourceUrls: [
18
+ 'https://www.investor.gov/introduction-investing/getting-started/fees-and-expenses',
19
+ 'https://www.investor.gov/introduction-investing/investing-basics/glossary/expense-ratio',
20
+ ],
21
+ relatedArticles: [
22
+ 'account-types-overview',
23
+ 'historical-vs-random-return-models',
24
+ 'how-assumptions-change-the-answer',
25
+ 'sensitivity-testing-what-changes-the-answer',
26
+ ],
27
+ relatedPlannerRoutes: ['/plan/:planId/accounts', '/plan/:planId/assumptions', '/plan/:planId/scenarios'],
28
+ currentYearSensitive: false,
29
+ priority: 'P2',
30
+ blocks: [
31
+ {
32
+ type: 'prose',
33
+ md: 'Investment fees can feel small because they are often quoted as annual percentages. In a retirement plan, the problem is not only this year\'s fee. It is the growth that never happens because the fee was removed before it could compound.',
34
+ },
35
+ { type: 'heading', text: 'Quick takeaways' },
36
+ {
37
+ type: 'list',
38
+ items: [
39
+ 'Fees reduce the return you actually keep, even when the market return is unchanged.',
40
+ 'A small expense ratio can become meaningful over decades because the lost dollars also stop compounding.',
41
+ 'RetireGolden does not have a separate fee field today, so the planning input is usually a net-of-fee return assumption.',
42
+ ],
43
+ },
44
+ { type: 'heading', text: 'The basic idea' },
45
+ {
46
+ type: 'prose',
47
+ md: 'If two investments earn the same gross return but one costs more to own, the lower-cost investment leaves more return in the account. That difference compounds. Over a short period, the gap may look modest. Over a full retirement horizon, it can change ending assets, withdrawal room, and estate value.',
48
+ },
49
+ {
50
+ type: 'figure',
51
+ image: { src: '/learn/images/fees-compounding-drag.webp' },
52
+ caption:
53
+ 'Fees act like a steady leak from the growth path, reducing both current balance and future compounding.',
54
+ alt: 'Two investment growth paths climb across a timeline, while one path loses small droplets through a fee valve and ends lower than the low-fee path.',
55
+ },
56
+ {
57
+ type: 'formula',
58
+ expression: 'net return = gross return - investment costs',
59
+ where: [
60
+ { symbol: 'gross return', meaning: 'the return before fund expenses, advisory fees, or other recurring costs' },
61
+ { symbol: 'investment costs', meaning: 'recurring costs that reduce what the investor keeps' },
62
+ ],
63
+ note: 'Real investments have taxes, trading costs, changing allocations, and timing risk. Use this as a planning lens, not a performance promise.',
64
+ },
65
+ { type: 'heading', text: 'A worked example' },
66
+ {
67
+ type: 'scenario',
68
+ name: 'The Allen household',
69
+ assumptions: [
70
+ { label: 'Portfolio assumption', value: '6% expected return before recurring costs' },
71
+ { label: 'Cost drag test', value: 'Compare a 5.8% net return with a 5.0% net return' },
72
+ { label: 'Question', value: 'Does the plan still work after lower net growth?' },
73
+ ],
74
+ summary:
75
+ 'The fee is not modeled as a separate bill. It is reflected by lowering the return assumption to what the household expects to keep after costs.',
76
+ },
77
+ { type: 'heading', text: 'Why it matters in RetireGolden' },
78
+ {
79
+ type: 'prose',
80
+ md: 'RetireGolden return fields are planning assumptions. If your investments carry meaningful fund expenses, advisory fees, or platform costs, enter expected returns after those recurring costs. Use **Scenarios** or **Sensitivity** to compare a low-cost version and a high-cost version of the same plan.',
81
+ },
82
+ { type: 'heading', text: 'Common mistakes' },
83
+ {
84
+ type: 'list',
85
+ items: [
86
+ 'Using a gross market return as if every investor keeps all of it.',
87
+ 'Focusing only on one-year fee dollars instead of the compounding drag.',
88
+ 'Comparing funds by return without checking whether the return is before or after expenses.',
89
+ 'Assuming lower cost automatically means lower risk. Fees and risk are separate questions.',
90
+ ],
91
+ },
92
+ { type: 'heading', text: 'Where to use this in the app' },
93
+ {
94
+ type: 'prose',
95
+ md: 'Use **Accounts** and **Assumptions** to set expected returns that already reflect recurring costs. Use **Scenarios** to test how sensitive the plan is to lower net returns.',
96
+ },
97
+ ],
98
+ }