Skip to content
Horalis
Theme

Kept only in this tab.

HoralisAll the Horalis tools

Tools

Theme

Kept only in this tab.

Study: Horalis Growth without a framework

All the research sheets

Translated from the Spanish original. Where they differ, the Spanish one holds.

  • App: Horalis Growth (projects/wealth-lens/) · Date: 15 October 2026 · Phase: E1 of the Horalis plan
  • Status: a study only. It changes no code, methods or assumptions. It gathers measured facts and options. The decision is Marek's.

Question

Should Horalis Growth leave Next.js and React and be made like the other tools (Cost of Living, Inflation): static pages that Node generates from TypeScript, with seed-kit and no framework? What would it gain, what would it cost and what is at risk?

The criterion is that of docs/direction.md: tools that work for years untouched, light and private, with minimal dependencies. The ten-year test (docs/prueba-diez-anos.md, phase E2) gives the measure.

Measured facts (15 October 2026, on phase D2)

Horalis GrowthCost of Living / Inflation
Runtime dependenciesnext 16.3.7, react and react-dom 19.2.8, lucide-react: 55 production packages in package-lock.json (17 required; the rest, optional binaries per system)none (only seed-kit, in the same repository)
Development dependenciesTailwind 4, eslint-config-next, Vitest 5, fast-check, Playwright: 495 packages in all in package-lock.jsonESLint, TypeScript
Calculation code (src/lib, without tests)5,228 lines, with no React import at allcalc.ts, view.ts…
Interface (src/components, .tsx)46 files, 5,179 lines; 39 with "use client" and 28 with React hooksview.ts and app.ts: seed-kit templates and about 100 lines of script
More interface with Reactsrc/hooks: 292 lines; seed-kit src/react (header and footer, trend): 319 lines—
Words (src/i18n)3,594 lines: texts in three languages, plus Next metadata and routes (metadata.ts, route.ts)each tool's src/i18n/
Next pages (src/app)262 linespages.ts
Tests670 with Vitest (54 files, 44 of src/lib), 43 in the browser46–47 with node --test each
Outputout/: 2.9 MB, 34 JS files (1.2 MB; 389 KB compressed with gzip -9)18.5 MB and 56.8 MB, almost all pages for search engines (D1) and images for sharing (D2)
First visit208–237 KB per page according to its README (its test). With gzip -9 of the HTML and of all the JS and CSS the page names: 262–280 KB on index, es and how-it-works32.4 KB (Cost of Living) and 49.7 KB (Inflation) on the front page, measured by their build

How the new figures were measured:

  • wc -l on the files;
  • grep -l '"use client"' and grep -lE '\buse(State|Effect|Reducer|SyncExternalStore|Memo|Callback|Ref|Id|Context)\b' in src/components;
  • the packages, counted in package-lock.json: all of them, those that are not dev (production) and, among them, those that are not optional;
  • a script that compresses with gzip -9 the HTML of out/index.html, out/es.html and out/how-it-works.html, and each /_next/static/… they name.

The two weight figures do not measure the same thing: the README's is its own test's. Neither is a figure of real use.

What no longer depends on the framework

  • All the calculation (src/lib): the growth formula, the withdrawal rate, the goals, the "What if…?", the bad decade and the check. It is pure TypeScript and can be carried over as it is.
  • The data and the sources: they come from seed-kit (official/, asset-history.ts, cost-of-living.ts).
  • Offline and the download (B4): the service worker is seed-kit's (writeOffline). The .zip already treats Next as a separate case (nextAppOnDisk).

What does depend on React and Next

  • The page's state: the plan, the goals and the questions, in hooks and in app-store.ts (useSyncExternalStore). Without a framework, a state of its own and redrawing by hand would be needed, as app.ts does in the other tools, but with many more pieces.
  • The charts: growth-chart.tsx, futures-view.tsx and history-charts.tsx draw SVG with JSX. Inflation draws its timeline as SVG text in view.ts: it can be done the same way.
  • Lazy loading (next/dynamic, 5 files): parts that are not downloaded until used. Without a framework, import(), like the sharing code since D2 (seed-kit browser.ts, lazy modules).
  • The pages per language (app/(en), app/[lang]) and Next's metadata: seed-kit's build would make them, as in the other tools.
  • Tailwind: the classes are in the JSX. They would have to move to their own CSS or to seed-kit's classes.
  • The icons (lucide-react, 14 uses): inline SVG, as in the hub.

Options

  1. Keep Next and React (as today).
    • For: nothing has to be rewritten, and it works and is tested.
    • Against:
      • 55 production packages that change major version every year or two (Next 13, October 2022 → Next 16, October 2025);
      • a first visit 4–9 times heavier than the other tools;
      • the tool cannot be built with Forja's mould.
  2. Rewrite the interface without a framework, with seed-kit, like the other tools.
    • For:
      • zero runtime dependencies;
      • a single way of making tools;
      • foreseeably a first visit close to the others (estimate: 40–80 KB; unmeasured until it exists);
      • the build on Node 22 with nothing else (the browser tests would still need Playwright and npm).
    • Against:
      • rewriting some 5,500–6,000 lines of interface (components, hooks, seed-kit's React part) and its state;
      • redoing what Next gives today: metadata, canonicals, hreflang and the pages per language, the hidden Dutch one too;
      • changing how it is prepared for the download (hub/scripts/release.ts, nextAppOnDisk);
      • porting 43 browser tests;
      • the risk of breaking the accessibility achieved in C1;
      • weeks of work, not days.
  3. A small framework (Preact, Lit…) instead of React.
    • For: less weight and a partial rewrite.
    • Against: there is still a runtime dependency, and another way of making tools.
  4. React without Next (Vite and a static SPA).
    • For: removes Next.
    • Against:
      • React stays, and Vite comes in as a development dependency;
      • the already built HTML of each page is lost (Next gives it today);
      • little is gained.
  5. Keep what is needed to build it, without rewriting anything.
    • Keep beside the .zip the exact packages of package-lock.json (npm pack or a local npm cache) and the Node it is built with. Or treat out/, already built, as what lasts.
    • For: almost no work; it answers the risk of not being able to build it in ten years.
    • Against: it removes neither the weight nor the different way of making this tool. Maintaining that copy is one more task, and a change to the tool still needs that Next.

What is debatable

  • The cost of doing nothing. Next and React do not stop working overnight. But "years untouched" asks to be able to build the tool in ten years with whatever there is:
    • an abandoned package or a failing npm install breaks the build;
    • a Node build with native TypeScript, on the other hand, depends only on Node (the ten-year test, E2).
  • The risk of rewriting. The calculation is separate and has 670 tests, so the risk is in the interface, not in the figures. But the interface is what was audited in C1 (WCAG 2.2) and what people use.
  • The weight. 200–280 KB is well below the principles' 350 KB limit. The gain in weight is real, but it is not the main reason: the reason is to depend on less.

If a rewrite is decided: a possible order

  1. Freeze the current interface: screenshots of each view and a list of behaviours (the 43 browser tests already are one).
  2. Build with seed-kit the pages without interaction: How it works, About, Your data and Terms. Compare the HTML.
  3. Move the front page to seed-kit templates with the same src/lib. The state lives in a module of its own, without React. The charts are drawn as SVG in text.
  4. Port the 43 browser tests and the accessibility audit; the src/lib tests do not change.
  5. Publish both versions in parallel and switch when the new one passes everything. The choices people have saved (importing and exporting their data) must keep opening.

Each step has its PR and its review, like the rest of the plan.

To check by hand (Marek)

  • Whether the priority of "years untouched" justifies weeks of rewriting now, or after launch.
  • Whether people's saved state (the data file of "Download my data") must stay compatible, and for how long.

History

  • 15 October 2026: initial study (phase E1). No code changes.