Wherein I show you around one of my personal projects for logging smokes.
I know there’s been a dearth of Homelab posts and projects recently, and that’s because I’m currently learning the Go programming language and some web development. Today, I’d like to tell you why.
I’m a smoker, and have been for over 20 years now. About ten years back, I was feeling like I was getting close to lighting the next cigarette on the last glimmer of the previous one. I was in the habit of smoking inside my small flat during University. And I felt I was smoking too much.
I was also looking for a new side gig at the time, and one interesting opportunity was as a student assistant in a mobile networking project at my University. It involved writing simulations to test different scheduling algorithms. And it required C++. So I needed some pet project to get accustomed to the language, after going through the C++ primer book.
I ended up with implementing a tool I called “smoking”, to help me reduce the number of daily smokes. The basic idea was to have a timer: Every time I had a smoke, the time and date would be entered into a database, and then I could configure an interval which needs to pass before I could smoke the next one.
I decided to implement it as a CLI tool. Most of it was written in 2015, and I’m using it daily to this day. The basic features are pretty simple. The first one is a check to see whether I’m allowed to smoke again:
smoking when
Sat Dec 13 17:51:46 2025
(01h:06m:22s)
That’s the output right now, as I had a smoke right before I sat down to write this post. It tells me that I’ve got another about 1h before I could have the next. When I’m already allowed to have a new smoke right now, it would just say so:
smoking when
Now!
For registering a smoke, I would enter smoking smoked:
smoking smoked
Smoke Logged for Sat Dec 13 13:29:03 2025
Next Smoke in 01h:30m:00s
As you can see here, I’ve currently got an interval of 1.5h between smokes. That
has been the value for many years now.
But sometimes, I do want to have a smoke right now. Is it against the rules?
Yes. But I still want to. For those instances, the smoked command has a -f
flag:
smoking smoked -f
Interval has not passed.
Forced Event logged at Sat Dec 13 16:21:46 2025
Next Smoke in 01h:30m:00s
In addition to those commands, there’s also the stat command, to output some
basic statistics:
smoking stat weekly
Weekly statistics for Sat Dec 13 16:53:53 2025
Smoked: 58 (60)
Passed: 42 (40)
Smokes per Hour: 0.42 (0.44)
Average Interval: 2.38 (2.30)
Costs: 16.24 (16.80)
The “Smokes per Hour” and “Average Interval” values are a bit cheated, because I don’t account for the time I spend sleeping. 😉
There remains one more command, log:
smoking log today-06:30 1
Logged 1 cigarettes for Sat Dec 13 06:30:58 2025
It is intended for logging smokes I’ve had while away from my machine. At the
moment, I’m noting down the times where I’ve had smokes while away from my machine
in my phone. When I get back home, I run smoking log with all of those timestamps
to retroactively register the smokes.
And this is the trigger for me currently learning Go. I want to create a web app
where I can register smokes while I’m out and about without having to learn
Android app development. Then I will also add a new backend to the CLI app which
uses that new web app directly to register smokes.
When I wrote the original CLI program, I already designed it so that the backend can be replaced easily. The main point is going to be the implementation of a proper import function, so I don’t lose all of the historical data.
The web app
The plan with the web app is to write it in Go, which I’ve started to learn recently. And I honestly find it to be a very nice language. It feels a lot like C in its syntactic simplicity, but without a lot of the footguns C comes with. I started out with Jon Bodner’s Learning Go, which makes for a great introduction into the concepts and syntax of Go. As I’ve written before, I’m also making use of exercism.org for additional learning exercises.
Right now, I’m working through Alex Edwards’ Let’s Go, for an introduction to learning web dev with Go. And I have not had this much fun programming in a long time. It contains all the bits and pieces I need, from serving templated HTML to database usage to user handling and authentication. Even though I’m not through it yet, I already highly recommend it.
The UI idea for the app is pretty simple. I want to reproduce the functionality of the
CLI app, but on a website. The main page will be displaying the time and date of
the next allowed smoke, as well as a countdown to that time, a bit similar to the
output of the smoking when command.
In an example of how much I’m not a web developer, I’m struggling with one major issue: How to update the page? There are two parts to this question:
- How to actually do the countdown?
- How to update the page when a smoke is registered through other means, e.g. the API?
The answer to the first questions clearly seems to be: Use JavaScript. There’s no way to show a countdown with pure HTML/CSS. At least none that doesn’t look unnecessarily convoluted.
The second one seems to be a bit more complex. The base approach would be to show the time of the next cigarette, templating it into the page’s HTML before it’s delivered. But then, how to refresh the page when there’s another smoke registered, but via the API? The page would then need to be re-send, but with the new value for when the next smoke can be smoked. I’ve already found the http-equiv attribute, which can be used to automatically reload a page. But the docs for that also seem to state that it shouldn’t really be used, due to accessibility. And I can see that.
But what else to do? From my very limited understanding of web development, my only other option seems to be to code the page mostly in JavaScript, and then make API calls in the background on certain events, checking to see whether there’s a newer smoke and the time for the next allowed smoke shown on the page needs to be adapted?
I’m also still undecided whether to use one of the Go web app frameworks or not. The Let’s Go book mostly works with Go’s build-in tools and libraries. And I like that. But if I end up doing JavaScript, using a full web framework might not be amiss? It would also mean that I wouldn’t have to roll my own user/auth code. Finally, most web frameworks in Go come with some database management layer, and I would definitely like to have something that allows easy database schema migrations. But I could of course also just use the database framework those web frameworks use.
Decisions, decisions. 😁
But for now, I will stop here and continue working my way through Let’s Go. If you have any commentary, especially on my page refresh question, please hit me up on the Fediverse.