Recently PostsOdds & Ends
now playing

A tour of my desktop through the years

14min read · View all posts

One of my many hobbies used to be spending an inordinate amount of time “ricing,” or customizing the appearance and functionality of my desktop. I have largely outgrown it now since I have a Job and Responsibilities, though I’ll still sink a weekend into it from time to time.

This is a record of my desktop evolution through the years.

2021: Windows

I first started getting into desktop customization around 2020/2021. This is my heavily customized Nord-themed Windows 10 laptop.

Fun fact, the laptop that this screenshot was taken on has now become my home server.

Windows desktop c. 2021

2022: BSPWM/Rofi/Polybar

I had been generally curious about Linux for a long time and had some experience with it from prior coursework. Seeing the level of customization available in cool dotfiles online motivated me to finally make the leap from Windows to Linux. My first distro was Arch (btw), which contrary to the memes is not too difficult as long as you RTFM :-) Below was my basic setup using BSPWM, Rofi, and Polybar.

2022-2023: Cozy (AwesomeWM)

Eventually I had customization ideas that the BSPWM/Rofi/Polybar stack was too rudimentary to support, and after seeing rxhyn’s AwesomeWM dotfiles I was inspired to also use AwesomeWM. It was my first taste of a truly limitless WM/shell - I could build literally anything I could think of, and I spent the majority of my free time in this period doing exactly that.

This is the point where my config began to have actual technical merit and value instead of just being me spending 12 straight hours messing with colorschemes. I was leaning heavily into using Linux tools for a lot of life admin at the time, and my desktop shell slowly morphed into a carefully designed (aesthetically and technically speaking) frontend to integrate all of those tools. The setup felt extremely cozy, so I named it as such.

If I remember correctly I genuinely clocked 300+ hours1 working on this, tracked in Timewarrior. Out of all of my many desktop iterations, this one is by far my favorite and the one I am most proud of.

Dashboard

The core feature of this config was the dashboard. The home page of the dash provided an at-a-glance summary of basically my whole life.

The left column is just eye candy. The middle column includes an overview of events and tasks scheduled for the next few days, pulling data from Google Calendar and Taskwarrior. The right column is a time tracker integrated with Timewarrior; a habit tracker integrated with Pixela, an API-based habit and effort tracker; and a weather widget, which while functional was mostly just eye candy.

Cozy (AwesomeWM) dashboard c. 2023

In addition to the tasks overview on the home page, there is a separate Taskwarrior tab for more detailed planning. My workflow used Taskwarrior’s built-in tag and project fields, treating tags as broad categories and projects as sub-categories within them.

I liked the design for this a lot - left side for navigating and sorting, with badges next to tags/projects to indicate upcoming due dates, and right side for viewing details. There were keybinds for adding, modifying, and resyncing the tasklist. The scrollbar layout and logic for the right side was additionally implemented from scratch (I remember this being moderately challenging, though I don’t recall the specifics) and supported both mouse scrolling and Vimlike scrolling.

There was also a separate tab to display calendar information in a weekview format. The data source was Google Calendar, with data obtained via gcalcli. The gif below demonstrates using a keybind to re-sync the desktop calendar with the Google Calendar remote.

And below shows an interactive popup on the calendar weekview for adding and modifying events.

Another tool I used was Ledger, a plain-text accounting system, for managing my personal finances. I wanted something like Mint for budgeting and tracking spending but I was not willing to entrust a third party with my banking information, so instead I would frequently go through my statements for every account and manually input each transaction into my ledger files.2

# sample entry in my personal ledger
2024/04/12 * Raley's
    Expenses:Food:Groceries   $41.72
    Liabilities:Credit:Capital One

I of course had to build a frontend for this system into my dashboard. It had the basics that you would expect from a personal finance overview: account balances, monthly cashflow, budget progress, recent transactions, and a running list of who owes me what. (Or what I owe other people.)

This was particularly handy while filling out the ledger - write in my entries, hit r to refresh, and see if reported account balances matched the actual values.

Cozy (AwesomeWM) ledger integration c. 2023

Other panels

And now for some other miscellaneous things in this config.

Note: Every panel in this config supported Vimlike keyboard navigation as well as custom keybindings. All of the messy, complicated keynav logic was implemented from scratch, as AwesomeWM does not have robust enough keybind defaults to support it. This took forever to implement correctly, especially because the layouts were mostly freeform. I started writing a library for it for others to use, but I left AWM before I could fully flesh it out.

2024-2025: AGS (GTK)

AwesomeWM is so flexible and powerful because it gives you building blocks that you can use for whatever you want. Its drawback, however, is that it only gives you building blocks. If you want anything complex, you’re building it yourself. (In Lua, by the way, which has ONE native data structure.)

At the end of 2023, I got my first full-time SWE job and could no longer spend so much time DIY-ing things. I shopped around for a suitable shiny new desktop shell framework to move to, preferably one with more batteries included and configured in a language better than Lua, and picked Aylur’s GTK Shell (AGS). It is a tool for making desktop shells using GTK, offering support for multiple languages. I chose Typescript as it had first-class support from the maintainer.

Dashboard

The first thing I did was implement another dashboard. It was significantly faster to develop because I didn’t have to implement literally everything from scratch! I could actually use classes! Inheritance! Enums, structs, whatever I wanted, without having to do some weird fuckery with tables or metatables or whatever!

Below is the home page, with some notable additions including an RSS feed reader and a goals tracker. Clicking an RSS entry opened the article in the browser, and clicking a goal opened it in the dedicated goals tab of the dashboard.

Home screen of AGS dashboard c. 2025

The calendar tab looks much the same. It is not shown here, but there is a much more complex algorithm for laying out overlapping events. It also supports dragging and dropping to reschedule!

Maybe one day I will reinstall this config to take better screenshots.

The Taskwarrior tab is also fairly similar, except it displays a nested hierarchy in the left sidebar instead of the previous tags/projects split.

The most improvements were made in the ledger tab, which was split into three sub-tabs. The main overview tab was redesigned to accommodate the larger number of bank accounts I had at the time. There is also a new data obfuscation keybind o, which would toggle anonymization of data for privacy during regular desktop use or for showing off the UI… like now. An asterisk next to the header indicates that obfuscation is enabled.

I started an analytics tab for tracking more specific financial statistics and trends. The tab was pretty barebones, and the only analytic implemented is spending by category by month.

Finally, I added a tab for tracking progress towards financial independence. The dashed green line indicates how my net worth must accumulate over time in order to meet my financial targets. The orangey-brown lines indicate how my actual net worth has changed over time, with an added trendline for easier visualization.

After recreating and expanding upon those core dashboard tabs, I started exploring more of what GTK had to offer. One thing was maps! GTK has a built-in map widget. For whatever reason I have a particular affinity for map-related projects3.

Around this time I was using the Transit app for my daily work commute, and I discovered that there was a Transit API with a decent free tier. I got access to it and built a clone of the Transit mobile app into my dashboard. Upon selecting a trip in the dashboard, there was an option to send a push notification to my phone with a deep link to directly open the Transit mobile app with that exact start/end point.

This was built more for fun than out of necessity. It was pretty useful while working remote from coffee shops though, since my coffee shop of choice4 was located next to a train station. Slightly less friction when going home - instead of pulling out my phone, just Ctrl + J to open the dash and start trip planning.

I also added a new tab for goals tracking. I track them in Taskwarrior, and I wanted a nice overview where I could see everything. Historically my problem with setting goals is that after planning them, I never check the plans again so I forget what I was working towards. I thought it would help if I built a tracker into my dashboard which I use and see every day.5

This tab displayed each goal in a grid, where the color of grid items represented its category (health goals, financial goals, education, travel, etc.) Clicking one would open a small sidebar panel with more details like the description, subgoals or linked tasks, progress, and so on.

Goals could also be pinned and shown on the main tab of the dashboard, as seen earlier in this post.

Control panel

In this config, I made the control panel a separate slide-out side panel rather than a centered popup. This is because I had so much more content to add:

  • Really nice theme switcher. The theme previews for each theme were handmade in Figma.
  • UI scaling controls to account for monitors with different DPIs.
  • Power saver settings.
  • Wifi, Bluetooth, and audio controls.
  • Monitor positioning controls. This widget showed a canvas with appropriately-scaled boxes to represent each monitor, and the positioning could be controlled by dragging the boxes around.6
  • Notification center.

Below is the theme switcher in action. I was happy with how smooth I was able to make this!

Utility panel

I also added a separate panel for miscellaneous utility tools.

In early 2025 I picked up painting and had a lot of initial difficulty with mixing colors. As part of this desktop shell, I made a widget to help with accurately color-matching when painting from reference images. The widget launches a color picker, then makes a Gemini API call to provide steps for exactly how to mix it using the colors available in my palette with adjustment/correction tips included. I added an option in the shell’s config file to specify available palettes to mix from since I was trying out different mediums (watercolor, 12-color palette; gouache, 5-color palette).

This is probably my favorite and most useful widget I have developed. After enough usage I eventually learned to intuit how to mix colors on my own, so I stopped needing it so much.

The utility panel also featured a Gemini chat interface. This was very convenient - no more clicking around in a separate browser tab; just Ctrl+H to open the panel and ask whatever.

2026: Digital minimalism

Main laptop: Labyrinthine (Qt)

As you can see, I spent a lot of time with AGS adding many cool and useful features for myself. I had a lot of fun!

However… AGS was also incredibly unstable, pushing out three major breaking versions (there might be a fourth now?) within the span of about two years. I migrated from V1 to V2, rewriting almost everything in the process, because V2’s syntax was much easier to work with (I think - I don’t quite recall anymore). V2 had crazy memory leaks and would freeze a few times a day, and I’d have to hop into another tty to kill and restart it. There was a V3 which addressed the leak, but it required a large rewrite. I was so tired of the churn that I left in search of something more stable.

I landed on Qt6 which has a very stable ecosystem and lots of batteries included. This config is called Labyrinthine, after an album by a band I like. The frontend is written with QtQuick, a declarative UI framework with Javascript-like syntax, and heavier backend logic is written in C++. There is an existing desktop shell toolkit called Quickshell which uses this exact stack, but it is extremely early in development, and after AGS I no longer trust shiny new things. Qt/QtQuick by itself is stable. It is sane. It will probably outlive me.

I don’t have many good screenshots of this config as it is still quite barebones. Part of it is because my workflows have changed which creates less incentive for me to add features to it. I value digital minimalism a lot more now, and the important life admin stuff like my calendar, tasklist, goals tracking, habit tracking, etc. are all on paper in a bullet journal. All this config has right now is a basic dashboard with a home tab and a ledger tab. The ledger tab is actually functional, since I still use hledger a lot.

There is also a new tab featuring a custom music player. As part of the digital minimalism thing, I left Spotify and started buying my own music. I was using cmus and then ncmpcpp for listening, but I really missed certain aspects of Spotify, namely looking really pretty and also having rich playlist metadata support. Surprisingly, a Linux local music player with these features did not exist. It exists now.

This tab is a frontend for mpd. The artist images and background videos were hand-selected, and playlist metadata is stored in sidecar YAML files. I wanted to practice more C++ with this, so I spent a very long time ensuring the software design was robust and flexible, implemented unit/integration tests, and added a CICD pipeline.7

Travel laptop: Nothing

Mid-2026 I installed Nix on my old Surface Go to be used as a travel laptop because it’s much more portable and also not as valuable to me. This device has no shell or background at all - at first because I hadn’t made time to install one, and now because I don’t want one.

  • To check the battery: cat /sys/class/power_supply/BAT1/capacity every once in a while.
  • Launcher: keybinds, or firefox & disown
  • Managing and monitoring connectivity: nmcli, bluetoothctl, rfkill
  • Workspace indicators: none; I just remember where I am.

Sometimes when I power it on I get confused why it’s just a black screen, sigh resolutely because I think I borked my Nix install again, reboot it, and then I remember that it is actually supposed to be a black screen.

I am using this setup to write this post and I honestly love it. It’s functional, it’s minimal, and it just does what I need it to do.

Reflections

It is kind of amusing to see the stark contrast of my 2023 vs. 2026 setups. I have spent hundreds of hours customizing my desktop through the years and sometimes I wonder what it was all for, especially since one of my devices now has zero customization. I had a lot of fun though which is what matters most - it’s a hobby, after all - and genuine, thoughtful engineering went into these projects. I feel like this post has chronicled not only how my desktop has changed, but also how I as a person have changed over time as well.


  1. I was unemployed for much of this. ↩︎

  2. Now I use tools to automate this a little more. I recommend reckon, which takes in an exported CSV of bank transactions and uses Bayesian inference on past ledger entries to automatically categorize transactions. It is so useful! ↩︎

  3. I once tried to draw out the entirety of Subnautica by hand using the in-game compass. I kept having to restart because my paper was not big enough, and eventually it fizzled out, but I made a decent amount of progress. ↩︎

  4. Elaichi in Berkeley. A chai shop, not a coffee shop, but whatever. If you are in the Bay Area, check it out - it’s cozy and the drinks are tasty. ↩︎

  5. And it did kind of help! As pictured in the screenshot, I did in fact learn Tim’s part of Classical Dragon (although I’m not quite at speed yet - it’s hard). I also did read 12 books in 2025, go on all those solo trips, and meet all those financial goals. ↩︎

  6. I don’t even want to think about how long this would have taken to implement in AwesomeWM. ↩︎

  7. CI is… not passing, but at least I bothered to set it up in the first place. ↩︎