Imre Gera
9 supporters
Creating a pomodoro app with open-source ...

Creating a pomodoro app with open-source tools

Jan 11, 2021

In this short and not-too-deeply technical post I'll take a look at the choice of software used to create AnotherPomodoro.

The web as a platform

So I knew I wanted to build a pomodoro timer. The question was: where do I distribute the app? Do I build a mobile app or a desktop app? Do I really need to build something that users should install at all?

I've been playing around with web development for quite a while, so I was quite biased towards front-end web technologies: just building something with HTML, CSS and JavaScript. You can actually build mobile and desktop apps with these technologies (Ionic for mobile, Electron for desktop), but since web browsers are essential and frequently-used apps in almost every operating system, I can just build a webpage and there's no need to install anything: just type in the address and there you go. Or if the webpage is a Progressive Web App (PWA), you can easily pin it to your home screen, too. Zero effort.

Vue and Nuxt.js

Web page it is, then. But I did not want to write my own HTML files because as the app would get bigger, so would its maintenance become more difficult.

I've grown to like VueJS recently with its huge flexibility (use JavaScript or TypeScript and integrate any CSS pre-processor, among others). Reactive frameworks make it really easy to build an app where once you change something, that change is immediately reflected everywhere else in the app. You can notice this behaviour in AnotherPomodoro as well: go to the settings menu, to the display tab and toggle the schedule or change the number of items in the schedule. You'll see that once you click the checkbox or enter a different number, the changes are immediately applied - no need to press a "Save" button or reload the page! The best thing is that I did not need to program this behaviour into the app, first: Vue does it all for me.

Before starting out with AnotherPomodoro I've found that there's something that makes it even easier to build a Vue app: Nuxt.js.

Nuxt allows me to create websites that just work: no need to set up things like a router (what to do when the user types in /timer into the address bar) or some kind of state management (Vuex) and on top of that, the app is optimized out of the box thanks to something called server-side rendering. It also lets you create statically generated websites. With that nothing special required to run your web app other than the "dumbest" kind of web server: one that can serve plain old HTML, CSS and JavaScript files. That's really cool.

That's what I wanted, so I focused on building a fully static website. I probably cannot list all the benefits of using something like Nuxt.js and it might not be too interesting either: they are most noticeable to me, a developer. Among a lot of advantages I can easily separate my app into components - like how the three styles of timers are just different components: when you switch between them, they get swapped. This makes it really easy to build more stuff into the app without it getting too bloated (like having thousands of lines of code in a single file).

Extending Nuxt.js

Right, web technologies are cool. Nuxt.js is really cool. How do I make it even easier to develop a web app? Well, let's get ourselves a UI library first to create a beautiful app quickly!

At first I tried Vuetify. I loved it because it allowed me build an app without having to know how to style stuff and program things like a modal (dialog) window. I just wrote v-dialog and I had a modal window with beautiful material design looks.

In the end, I felt that it slowed the app down and without effort the whole site started to look really generic. I then decided to switch to Tailwind CSS (kind of the opposite of what Vuetify provides) and refreshed the app's looks with a hand-crafted design. There were no ready-made components any more but it's really easy to create whatever you want using Tailwind. I just write p-4 border border-gray-200 shadow and I have a box that now looks like a card: it has padding inside it, a grey border and a shadow. Awesome!

Later on some more plug-ins were added to the site: I needed an app that can be translated into different languages (thanks nuxt-i18n and vue-i18n!), I wanted it to save the settings so when the user comes back they are reloaded (thanks vuex-persistedstate!), I did not want to write my own date and time formatting functions (thanks Day.js!) and so on. You can find the full list of modules I used on the project's GitHub page! There's actually a lot and they all helped make AnotherPomodoro what it is now.

Publishing the results with Netlify

Once the app was sort-of ready, I needed a place where I could host it so that it has a URL address and anyone can access it without having to execute commands on their own computers. Normally one would say that you cannot host your own website without paying for a hosting service. Sure, when you want to build an app with a database and extra logic and authentication (register and log in) - anything that requires some extra work on the server's side - that's not necessarily free. Or if it is free, you'd soon reach the free tier's limits, anyway.

Remember when I mentioned that AnotherPomodoro is actually a static website? There are services like Netlify (and Vercel) that allow you to not only upload a static website (one that consists of HTML, CSS and JavaScript files and no server-side logic) but also offer you to build that website from your source code! That means that whenever I change the app's code, Netlify runs a command so that Nuxt.js creates a static website from the app's code. These services are also a lot more generous with their free tiers: you get 100 GBs of bandwidth per month (the full app is around 2-300 KBs but you likely won't download everything of that) and 300 minutes spent building your app (at least on Netlify) - of which one build takes around 2 minutes. This is more than enough even for a growing app.

"Hacking the system" with static websites

AnotherPomodoro is equipped with features that one could easily say would require a "proper" server: storing your settings and tasks, for example. Thanks to frameworks like Nuxt.js and their static site generation functionality, this can be avoided in a lot of cases. You can even build a blog or a news site with static site generation! Since there's no authentication (you edit the code of your site on your machine, not the content in some database on the internet) there's also a lot less space for attacks. Just be sure to protect the source code and your materials properly.

Static site generation is not some universal magic wand to avoid databases and more complex servers, though. Since no data is stored on servers, AnotherPomodoro is not able to synchronize your settings and tasks across your devices: if your browser does that for you, all the better. There's no way to create leaderboards, either. In fact, sharing any user-generated content (think social media posts, for example) through a static app is without any supporting server is (mostly) impossible. To me, these things were never really important, anyway. I am willing to spend 30 seconds to configure the app and I don't think that pomodoro apps need leaderboards. I can build a statistics module into the app, though 🙂

The key is to recognize when the features you want in your app actually don't require more than what a static website can provide. It might be tempting to include a log in feature just to share data across devices but in some cases it might be overkill. In AnotherPomodoro's case, a quick setup page is being made to set the app up for first use even quicker so users will not need to delve into the settings that much. This also helps avoid having to sync settings across multiple browsers.

The app's source code (along with more technical information) is available at the project's GitHub page.

Thanks for reading this little snippet of the making of AnotherPomodoro. If you haven't yet, check out the app at!

Enjoy this post?

Buy Imre Gera a coffee

More from Imre Gera