Architecture Decision Record
Status
accepted
Context
FinReview needed a frontend to present portfolio analytics, charts, alerts, AI briefings, and market news. The natural default for a new project in 2024 would have been to reach for React or Vue. I chose vanilla HTML, Bootstrap 5, and plain JavaScript instead. This was a deliberate decision, not a shortcut.
Rationale
The frontend's role in FinReview is strictly presentational. All business logic lives in the FastAPI backend. A JavaScript framework adds a build pipeline, a Node dependency, bundle management, and component state complexity in exchange for a development model that is most valuable when the frontend carries significant application logic. Since the frontend in FinReview carries none, the trade was not worth making.
Trade-offs
No component model means more manual DOM management as the UI grows. There is no reactive state — updates require explicit DOM manipulation. For a project with a larger team or a more complex UI, a component framework would become necessary. For a single-developer project with a backend-first architecture and a well-defined scope, the static approach removed friction without meaningful loss.

Every developer building a new web project in 2024 faced the same default: choose your framework. React, Vue, Next.js, Nuxt, SvelteKit — the ecosystem offers more options than any project actually needs. I chose none of them, and the decision was intentional.

The question I asked before choosing was: what is the frontend actually responsible for in this application?

The answer was: displaying data that the backend computes, and sending user actions back to the backend. Nothing else.

Portfolio analytics are computed in the backend. XIRR, P&L, concentration scores, drift percentages — all deterministic calculations in Python, returned as JSON. The frontend receives the JSON and renders it. AI briefings are generated in the backend and returned as text. The frontend displays the text. Market news is fetched and categorised in the backend. The frontend shows the list.

When the frontend's only job is rendering backend responses and collecting user input, a component framework adds complexity without adding capability. React's virtual DOM, component lifecycle, and state management are genuinely powerful when the frontend manages significant application state. When the frontend's state is "what did the last API call return," they add indirection without benefit.

The practical consequences of the static approach were significant.

Deployment is a folder of files. The entire frontend can be uploaded to any static hosting provider — MilesWeb, Netlify, Cloudflare Pages, an S3 bucket — without a build step. There is no npm install, no webpack configuration, no bundle to optimise. A developer reviewing the project can open index.html in a browser directly without running any build tooling.

The dependency footprint is minimal. Bootstrap 5 and Chart.js are loaded from CDN. There is no package.json, no node_modules, no version conflict between transitive dependencies. The only runtime dependency is a browser.

The CI pipeline is simpler. Syntax checking JavaScript files requires only node --check. There is no TypeScript compilation, no ESLint configuration, no test framework for component rendering. The backend tests cover the business logic; the frontend tests cover syntax.

The trade-off I accepted was manual DOM management. When the portfolio table updates, the code rebuilds the table HTML and sets innerHTML. When the alert list changes, the code iterates the response and constructs list items. This is more verbose than a reactive component and more error-prone at scale. For a single-developer project with a well-understood set of views, it was manageable.

There is a temptation in software development to choose tools for their reputation rather than their fit. React is used by large engineering teams at scale because it solves problems that arise at scale. A portfolio project with one developer, a backend-first architecture, and a static deployment target does not have those problems. Using React would have solved problems I did not have while adding complexity I did not need.

The static frontend also serves a specific purpose in the context of this project's goals. FinReview is an engineering showcase for backend architecture, service design, and AI integration. The frontend is intentionally simple so that attention stays on the backend. A sophisticated React application would shift the review toward frontend engineering, which is not what the project is trying to demonstrate.

Choosing the right tool for the actual problem is a more useful skill than choosing the most sophisticated tool available. The static frontend is the right choice for what FinReview is, not a compromise of what it could have been.

← Back to FinReview - Portfolio intelligence platform for Indian investors
Building AI features without locking into a single… →