The usefulness of in-house accounting has become evident only in recent years. On different occasions, my wife and I discussed a solution for keeping track of expenses and available budget for short- and long-term goals. Simply put: the bank statement was not enough any more.
In the past we relied on ledger, knowing too well the power of plain text. For a while we succeeded in our money management, because ledger is really that good. However, soon we started thinking about savings and goals, about a custom user interface to have a better understanding of our financial situation.
Naturally, I decided to use some of the experience I gained at work to develop our own application. I wanted a simple single-page application that would enable us to:
- track expenses
- query expenses to get reports
- track short- and long-term goals
boodle (a synonym of money, in case you are wondering) has the following architecture:
- client: re-frame
- server: ring on top of HTTP kit
- database: PostgreSQL
I have set up bidi for client-side routing, compojure for server-side routing and compojure-api to connect client and server via pleasant APIs.
Thanks to mount I have three main components that I can start and stop to make development and debugging easier: application configuration, database and HTTP server.
I decided to give dire a try, appreciating the separation between logic and error handling. I also took the chance to couple clojure.test with test.check, for some basic property-based testing, and lein-eftest to have fast and pretty test results.
The setup is completed by the continuous integration offered by Travis CI and Deps Versions to identify outdated dependencies. Everything is available on SourceHut, if you want to dig deeper into the details.
boodle is currently deployed on my home server, and in the last months it has proved to be a reliable tool. It also deepened my love for Clojure and ClojureScript. Long forgotten are the days where separation of concerns, both client- and server-side, seemed impossible and destined to fail.