By Martijn Steenbergen

The architecture of my life

This is a blog post in the series of the architecture of my life. Earlier versions from 2021 and 2019.

Automation is something dear to my heart. I’ve been working on this entire framework on and off for more than 5 years. In those years the definition of automation has also shifted. What started out as running small automations in the background have grown to full fledged apps.

This blogpost has the following things:

  • The Foundation: The base for how I think about automation. If you’re just interested in getting inspired, you can skip this part.
  • Areas: I’ve found that I am building most automations in a group of areas, so I’ve grouped them for you: Music, Lights, Tasks, Calendar, Places and Other.

Hope you enjoy!


An Action

The core of my automation are actions. An action is a function that given input (or no input) will act on my behalf and perform an action. Some actions will check for themselves if they need to run (adding a reminder for a sent email). The action can also decide how often it wants to run, from every 15 minutes to once a week. Others I only want to run when I need them to (checking the uptime of my systems).

Some require input to do their job correctly (adding a todo to my todo list). The most complicated actions have state, as they require multiple inputs or require multiple steps to get to the requested input. By interacting with the action multiple times, this state can be filled up until the action can complete. Actions are stateless, which sounds contradictory, but isn’t. If you call an action with the same state you should get the same result. That result is a response object with a status (if it still requires more information) and the full state of the action. The place where all the actions are execute is called Atlas. Atlas runs in the cloud using Azure Functions. The code lives in a GitHub repository, which automatically deploys using GitHub actions.

User Interaction

Originally, Atlas was just a Telegram chat bot. Telegram, a chat application, has extensive support for bots, which I heavily used. An upgrade to use the Microsoft Bot Framework also enabled it to also for a short while run on my Amazon Alexa. This bot enables me to quickly talk to it. Telegram also has support for multiple options, so that makes choosing from a set of predetermined options easier than just writing them down.

Because Atlas is running in the cloud, I am also able to use it as a web-api. Scheduled actions are automatically run there as well. Calling specific endpoints enable me to call specific actions and parameters (or a POST body) enable to also send parameters and state.

The introduction of IOS Shortcuts introduced a lot of possibilities. So much so that my main interaction with Atlas is through the shortcut application. The base shortcut calls the web api and keeps the local state, while it asks for input.

Error Handling

One of the problems of building your own automation is that things are breaking. Constantly. I am connecting to 17 online services and having 35.000+ lines of code means that it is likely something will break. Most of the errors occur within Actions, as they make the calls to external services and change (and therefore break) most often. To make sure one action does not break the entire system, all actions are run in a try-catch block.

Once an action crashes, automation will start running to handle the crash. Independently running actions will start to send me messages to tell me that it is broken after eight failed runs, so that timeouts and other temporary problems don’t bother me. It will also automatically throttle itself, postponing its next run in an exponential way, to make sure it does not break anything and I do not get spammed with messages.

Error messages used to show up in my Telegram, but I’ve switched to Pushcut, which enables me to give native notifications on my phone and disable the action (for a day) with a simple tap.

The Telegram chatbot will ask the user after a single crash if it wants to make a GitHub issue, as this is deemed more important.

Now, you have a good overview of the basics, we can discuss the cool parts.


I listen to a lot of music. Like a lot. Last year I listened to around 60 days of music. That makes it an important part of my life and therefore a big place for automation.

Last 4 weeks

I (used to) spend a lot of time biking and travelling by train. I have a data plan, but don't want to overshoot it. This leads to the fact that I need Spotify to download a lot of music. However, I also have a lot of new music that I want to bring with me. I could download all my music, but my phone does not have enough storage for that. To solve this problem, Atlas will update a playlist every night with all of the songs I added in the last 4 weeks. I then tell Spotify to keep this playlist downloaded at all times. This leads to an almost always updated playlist with my newest songs.

Full Release Radar

Spotify has a feature called Release Radar, where each week, you can listen to music that came out that week from artists you follow or might find interesting. This is great and I’ve gotten a lot of new music from it, however it might miss artists that I like and if an artist released an entire album, it will only display one song in the playlist, which I can definitely understand, but I don’t want. So I created an Action on Atlas, which every Friday checks all the artists I follow. If they released any new music in the last week and it puts the songs into a playlist called “Full release radar”, so that I do have this overview. As an addition, another action checks if I added music from a new artist and automatically follows them, so this list is constantly expanding.

Sort by loudness

To aid you in finding new music, Spotify presents you with two auto-generated personalised playlists. A Discover Weekly playlist with new music from new artists and a Release Radar playlist which contains music released this week. Both are very nice, but have one problem, they jump from very loud energetic to peaceful piano music. This is very jarring if you are listening. To solve this, I download all songs from the playlist and get the features of the songs. These features are provided by Spotify and contain things like energy, danceability, liveness and loudness. I order all songs by loudness and put them in a new playlist for me. This way I can listen to my music from very loud to very peaceful.


Once you’ve extracted loudness from all your music, you don’t have to stop there. There are many more features that Spotify enables you to play with. From all those features you can generate playlists. However to do that, you would need to find the perfect settings to create a nice playlist. To do this, I created Playlister, a universal Windows app, which enables me to play with all the features you see on the right of the image below. It also enables you to pick songs and create automatic filters that would include them.

Personally generated playlists

Using Playlister, I have created playlists named Summer, Winter, Piano and Energy. Every week, Atlas downloads all my saved songs from Spotify and runs it through each of the finely tuned filters for my playlists and updates each with new songs I’ve added and removes songs I no longer like. So if I want to listen to music that gets me hyped, I listen to the Energy playlist, which consists of songs I like that, following my tweaks, can be considered full of energy.

Machine learning playlists

Building these playlist is time consuming, so I tried to automate it. Features are something that computers and also machine learning is really good at. So I loaded all the songs from the playlist Winter, took their features through a Logistic Regression model and generated a new playlist that is called WinterML. By adding and removing songs to this playlist I am able to tweak it further.


Imagine that you have friends over. You have no idea what music they like, but you also don’t want them to play your music. Imagine a website with a tinder like interface, that enables you to swipe on songs, so that it would in real time train the music on your friends needs, while still playing only your music. Well wait no more. It is here and I’ve built it.

We start out with 10 random songs and the 10 latest songs as an initial set. I then use my machine learning model to train on those swipes, returning the highest rated songs, together with a small set of songs that you might like. You can keep swiping until you think its nice enough and then generate an entire playlist for the rest of the evening.


My automation of my lights comes from a single annoyance; I don’t like to turn on/off lights. Furthermore I love light, so I usually have my lights on the entire day. Some friends complained that I was wasting energy. Furthermore, having smart lights also enable you set different light levels. In the end, my light automation has two axes:

  • Moods: Different ways I can make my apartment feel using the lightlevels and colors. I have a work mood, night mood (where all lights are dimmed) and a sleep mood (where all lights are off). I also have an automatic mood that tries to automatically tries to move between each.
  • Modes: How the lights in the house respond to movement. I’ve put motion sensors all over my apartment to be able to track where I am at all times. This enables me to turn off lights in places where I am not. I can also turn on sentry, a mode that turns off all lights, until it sees that I am back home.

Lastly, because I am able to control all of my lights separately and am able to see which music I am listening to and able to know the beats of that music, I can also make my apartment into a disco.


I like to be on top of all the things I need to do. My tool of choice is Todoist. The goal is for all tasks that I will need to do to be in that system. By using projects and sections, I am able to make a relevant difference between the things I am doing, things I can do and things I might not be able to do or have not prioritised.

GitHub Synchronisation

A task management system is for all the tasks in your life that you are planning to do. However, sometimes tasks do not live in my Todoist, namely GitHub issues. So I have an action that keeps track of all issues in all my repositories on GitHub and make tasks for them in my todo system, making sure to link to them. If there are any changes in the title, it also makes sure to update them. It is only one way sync, as some bugs resulted in the creation of wayy to many issues on GitHub.


After having a system for all my tasks and being able to see my tasks in a single place, I want to be constantly reminded of my priorities. In comes Taskist, which is displayed on every new tab of my browser, making sure that I either change what I am doing or refocus on what I should be doing, including a little plus button to add any tasks that come to mind.


I subscribe to the idea that my calendar is the single source of truth for what I am doing. This means that my calendar is always up to date and that I am able to easily share with other people what I will be doing by sending them calendar invites. Which I send a lot of.

Event Body

The normal calendar event is nice, but it is not very pretty. Often I don't write anything in it at all, since the invite should say enough. This is where the event body action comes in. It adds an html table to the email with the subject, place and time, so that you're quickly able to see the event if your email program of choice does not give it.


I don't remember the homes of all my friends, but luckily for me I religiously write them down and save them in my contact cards. This enables me to write down in the calendar invite @{name of person} and it will automatically find the address of the person I am going to. Furthermore, writing @{teams} will create a teams link with all of the preferences that I have.

Calendar invites

Sometimes you are in a chat and don't have everyone's email address. Or sometimes you don't want to bother people, sending them a calendar invite. After all there is a slight expectation that if you send someone a calendar invite, that they show up. Instead I have made a website. With an action I am able to open up any calendar invite to the wider world, enabling them to fill in their email and they will receive a calendar invite. Also handy for people that do not user calendar invites.


Often people recommend me places or tell me where they’ve been. I love these stories, but am sad that I can’t really do anything with this information. Furthermore, I still haven’t found a good app or website to plan out where to go when I go on holiday. So I built one for myself: places

Places enables me to do all the above and more. Collections enable me to sort groups of places together. I can add any place by calling the Google Maps API from within the api or using an action. Its mobile friendly. as A Wikipedia Action adds the relevant wikipedia article to a place if it is in the same spot. Another actions enables me to find any articles written close by. I’ve used it recently when going on holiday and loved it and will continue using it going forward.


Not all things I built fall into the above categories. Here’s some bonus things!

Design System

You might notice that all these websites have the same vibe. And you would be correct! For the past year I’ve been working on centralising all my colors, fonts and all design into a single design system, so that I can more easily create new websites for new projects.

Remembering links can be difficult. When creating a Microsoft teams link, it might not even come across as a valid link for some software. To help you can use a link shortener. There exist a lot of link shorteners already, but I like to be in charge of any personal links that I have. Therefore I created As an example, take a look at my CV.

This blog

View the code

Yes, you read this right. This blog is part of my automation. Using Notion, I am able to write any blog post that I want. Using Atlas, I extract the text from Notion and convert it to html to display on the blog you are reading right now!


One of the more cute examples of my own code is Wallsetter. This is a small app which I built to set a new lock screen and wallpaper every two hours. It gets new images from Unsplash, an amazing website to find free to use images. Wallsetter is then able to apply all sorts of effects to it.

The settings menu for my app Wallsetter
The settings menu for my app Wallsetter

The cool thing is that for the lock screen is that it is able to check my Trakt and look at which TV show airs today or if there are any shows from yesterday that I have not watched yet. Then it will grab an image of that show and set it as my lock screen or wallpaper.

However, that is not my setup currently I use it to download an image of a cute dog, set it as my wallpaper and set a black and white version of that as my lock screen image. It is gorgeous and I am very happy with it.

That is all! I hope you are inspired to go do some automation of your own!

Arrow Back

View all posts

Hi! I'm Martijn Steenbergen. I am a Software Engineer at, helping you find what you need. I got my M.Sc. at the wonderful Technical University of Delft. I love automating my life (music, lights, calendar and more). I'm fascinated with design, how the world works and everything else