FinSchool — Project Story
Inspiration
Personal finance is one of the most universally important subjects a person can learn, and it's almost completely absent from formal education. Most people graduate high school — or even college — without ever being taught how compound interest works, what an expense ratio is, or why keeping all your savings in cash is a slow-motion financial mistake.
The inspiration for FinSchool was simple: what if learning this stuff felt less like reading a textbook and more like actually using the concepts? The moment you drag a slider and watch a $5,000 investment compound into $19,348 over 20 years, the formula $A = P\left(1 + \frac{r}{n}\right)^{nt}$ stops being abstract. It becomes visceral. That's the experience I wanted to build.
What I Learned
Building FinSchool taught me as much about financial literacy as it did about front-end development.
On the finance side, I had to distill concepts like compound interest, ETF expense ratios, and credit score weightings into language that's genuinely accurate but doesn't require a finance degree to parse. That process of simplification forced a deeper understanding — you can't explain something clearly if you don't fully understand it yourself.
On the technical side, I got hands-on with:
- Structuring a multi-section single-page application with zero dependencies beyond an icon font
- Implementing financial calculators correctly in JavaScript (floating point is not your friend —
0.1 + 0.2does not equal0.3, and that matters when you're displaying dollar amounts) - Designing a UX that guides users through a progression — lessons → quiz → XP reward — without feeling gamified to the point of being patronizing
The mortgage calculator, for example, uses the standard amortization formula:
$$M = P \cdot \frac{r(1+r)^n}{(1+r)^n - 1}$$
where $P$ is the loan principal, $r$ is the monthly interest rate, and $n$ is the total number of payments. Getting this right and displaying it cleanly required careful rounding and edge-case handling.
How I Built It
FinSchool is a fully self-contained single HTML file — no frameworks, no build tools, no backend. The entire app is vanilla HTML, CSS, and JavaScript, with one external dependency: the Tabler Icons webfont for iconography.
The architecture is straightforward:
- Lesson data is stored as a JavaScript array of objects, each containing the lesson body, a key highlight, and a quiz with the correct answer and explanation. Adding a new lesson is a matter of pushing one object to the array.
- Tab navigation swaps CSS classes rather than re-rendering anything, keeping the UI snappy.
- Calculators recompute on every slider input event, so results update in real time with no button press required.
- XP and progress state live in JS variables and persist for the session — intentionally kept simple, since this is a learning tool, not a platform.
The styling uses CSS custom properties for theming, making the color system easy to adjust, and the layout uses CSS Grid with auto-fit / minmax columns so the lesson cards reflow naturally on any screen width.
Challenges
Writing accurate, approachable content is hard. Financial topics are riddled with caveats, and there's a real tension between being technically precise and being actually readable. The credit score section, for instance, involves five weighted factors — oversimplify it and you mislead people, over-explain it and nobody reads it. Finding that balance took multiple passes.
Floating point arithmetic. JavaScript's number representation means that naive financial calculations produce results like $19347.999999998 instead of $19,348. Every computed value in the app goes through Math.round() or .toFixed() before it touches the DOM — a small discipline that matters a lot when you're teaching people about money.
Scope creep. The original concept was "a few lessons and a calculator." It grew to include six lessons, three calculators, a 15-term glossary, and a progress tracker before I locked scope. The constraint of keeping everything in a single file was actually a useful forcing function — it kept the feature set honest.
Log in or sign up for Devpost to join the conversation.