Why I'm Building Financial Calculators with a Minimal Technical Stack

I love Laravel.

I love Nuxt probably just as much.

And Vue.js ❤️.

And client-side apps in general.

And Serverless. And Containers. And Kubernetes!

And the list goes on.

...so why go back to basics? Really, do I need all of that, for calculators?

Some reasons for a minimal stack

Preventing dependency drift

Reinventing the wheel is a great learning exercise. However, it's better to leverage dependencies so we have more time to work on our core business problems.

Now, saying that, frameworks usually come with a tonne of dependencies that we may not even need. Now that was the case for my project. I just didn't need all these dependencies.

Maintaining dependencies isn't noticeable when you're continually working on a code base. Every 30 minutes here and there seems negligible. But it adds up.

Usually, with dependency heavy projects, when I come back to a code base after some time, I have to inevitably run a build or install the packages afresh, at which point, something is broken. Now there are ways to try and mitigate this but it doesn't always work, like using version locks, or Nix for the OS.

Focusing on logic

It's enjoyable. Learning and becoming proficient at a framework is truly one of life's joys as a developer. But when time is limited and a new feature needs to be created, I had to decide. What do I want to challenge myself with? The framework? Or the logic?

https://www.radicalsimpli.city/

💡
"If it takes an hour to figure out what’s going on, well, that’s an hour that wasn’t spent doing something else more useful and interesting. On top of that, tech deals a lot of time with itself instead of delivering business value.” - https://www.radicalsimpli.city/ (image)

So for this particular project, most files are just .mjs files, ran with the Bun runtime.

Why? Financial calculators are just that. Calculators.

I had to write tests. Also, using bun:test instead of the usual test library, minimising dependencies again. Although the outputs with Vitest or Jest are a lot prettier.

So whether I do FIFO, LIFO or weighted average cost methods for calculating realised gains and losses, all I had to create were blackboxes of logic. No framework required. Just pure functionality.

Building quickly

I love client side frameworks, especially as I started off a front end developer. But I found working with HTMX weirdly efficient as most of my logic lives on the server for this project. When I needed a tiny bit of interactivity and dynamic data, I didn't see any reason to reach for Vue.js or even React!

Now if I needed the power of a JavaScript framework, I would certainly have had fun building with those. Or if I was developing a project with mostly third-party APIs, then of course. But for this project, I had no reason for it.

Being a solo dev

Now there's a downside to being a solo dev. I can build something that only I will ever understand. And so using frameworks would give me a standard way for doing things. Without a framework, the onus is then on me to make sure I structure and document the code in a way that's easy for my future self to understand as well as other developers and that is extra time and thought.

So to get around building a confusing code base, my simple gotos were:

  1. Modularising the code into small replaceable/deletable chunks that use the Unix philosophy. And sorry about the swearing at the beginning of the video. This might even mean some duplication.

    %[youtube.com/watch?v=1FPsJ-if2RU]

  2. Documenting inputs and outputs that leveraged IntelliSense and type checks. That meant for me, writing code was super simple as IntelliSense would highlight what I'd need to write.

  3. Keeping app and infrastructure separate from core logic. This is a principle found in the hexagonal architecture, and the aim is to be able to replace the framework in future, which I've never had to do. But the main reason is it makes the core logic easy to test. If there's not much pure logic, there's no need to do this.

  4. Writing contextual code. My calculators are not pure mathematical calculators. They're contextual to order objects in my project. I also don't worry about input validation for every function because I believe the boundaries between user input and the core functions should validate what comes in.

Now am I against frameworks and dependencies?

No. I'm building another project using Laravel Inertia which makes use of Vue.js, because the ecosystem is so rich, and I didn't want to re-invent the wheel. I knew I'd need to integrate subscriptions, notifications, websockets or at least, server sent events, background queues, migrations – the list goes on.

I'd be crazy to recreate a bad version of a framework myself when I could just leverage something out there already, even if that means running into dependency issues.

The only thing I'd try to do, is limit the number of dependencies I add on top of Laravel to make it easier to maintain.

And what's the stack?

  • Node.js

  • HTMX

  • Alpine.js

Maybe some would say this more complicated. But given I didn't know HTMX and Alpine.js when I started the project,

So the financial calculators

So I've built a very basic free fifo calculator for stocks and options as well as using other accounting methods. And literally, I didn't have to fight a framework or any dependency.

So, frameworkless forever?

While modern frameworks and tools offer immense power and convenience, they can also introduce unnecessary complexity, especially for projects with straightforward requirements. By returning to a minimal stack, we can focus on the core logic and deliver value without getting bogged down by dependencies. This has been a liberating project for me, and I hope you get to enjoy a project with minimal dependencies too. But 100% frameworkless isn't realistic either for all projects.

Did you find this article valuable?

Support Gemma Black by becoming a sponsor. Any amount is appreciated!