My Year in Review 2025

Another year has passed, and it’s time to reflect on what I accomplished, what I learned, and where I’m heading next. 2025 was a year of shipping projects, learning new technologies, and making some significant life changes. Looking Back: 2025 Goals Review My core aims were: Release a working version of Banter Bus by end of January Try to release say 20ish YouTube videos next year Look at making some money from my side projects I successfully completed the first goal, though the other two took a back seat due to changing priorities. With regards to YouTube, I didn’t really find the motivation to make videos. I will likely have another crack at it this year, aiming at creating content with simpler editing which takes less effort. ...

Posted On:  2026-01-01 1376 words 7 min

How to Setup a New PC With Lanzaboote, TPM Decryption, sops-nix, Impermanence and nixos-anywhere

Background Be Careful Make sure if you follow this guide you could lose your data. Make sure to back up whatever important data you have. Or do what I did and test this on a new device where it doesn’t matter if something goes wrong. But don’t try to do this on a machine that has important data, or you need to use day to day. Though I was able to set up a new laptop in about 20 mins once I got everything working. It can be fiddly. ...

TIL - How to Fix Tailscale Using Mullvad as Exit Nodes on NixOS

On NixOS when ever I enabled mullvad as exit nodes via tailscale (the trayscale app). My internet would stop working, which was weird as this worked fine on my other devices i.e. Ubuntu or my phone. Well turns out it seems to be the way NixOS works with the firewall, you can read all the details here 1. Where the poster explains it really well. My understanding is the following: This changes RPF (reverse path filtering) from “strict” to “loose” mode: ...

TIL - How to Fix App Lounge Updates Getting Stuck (MurenaOS/eOS)

If you use a FairPhone, or a phone running eOS/MurenaOS, which is as degoogled version of Android (no affiliation to me besides I use their devices/OS). Sometimes the app store “App Lounge” gets stuck updating apps, my old solution was to delete the app and reinstall it but that can be a pain. Then I discovered a slightly better solution. Go to settings Apps & Notifications Find App Lounge Then go to Storage & cache Clear storage and “Delete app data” You will need to log in again to the app, but the update process shouldn’t get stuck anymore hopefully. ...

How to Fix PAM Issues With Home Manager on Non-NixOS Setups

[!WARNING] The pam_shim is POC code, so be careful with using it on your own machine. Use it at your own risk. The problem At work I have to use Ubuntu but I want to share my nix config between all my devices i.e. desktop and work laptop. On my home setup I have been using Niri with Noctalia shell (quickshell) on NixOS. Everything works fine I can use the Noctalia shell lock screen and can authenticate fine. ...

TIL - How to Enable Video Thumbnails for SMB Share on Nixos and Nautilus

So recently I have setup a mini NAS and I connect to it via an SMB share, but on nautilus I noticed that unlike my local files for the videos it would not create thumbnails when I was using nautilus (file manager for Gnome). The fix ended up being pretty simple 1: Nautilus > Preference > Show thumbnails. Set it to "On this computer only" for only seeing thumbnails on your system, . If u need it to do same for a remote server, select "All files" Or since we are managing this via NixOS and want to do things declaratively we can do do the following in our Nix config 2. ...

Yak Shaving: Neotest Edition

TL;DR: The fix is in this commit: https://gitlab.com/hmajid2301/nixicle/-/commit/cfababc9e3a1dfdd1917d0b87cb17fcdd655bfdc Fixing stuff is fun! 🥳 Background I use Neovim (btw!) and Nix (btw btw!!!). I mean, half the reason to use these tools is to tell other people you use them, right? 😉 Otherwise, why would I go through the pain I experienced today? “What pain?” you ask. Good question! A few weeks ago, I noticed that running tests in Neovim was failing with a no test found error. I’m using neotest and neotest-golang to run tests within Neovim. ...

TIL - How to Change Emojis in nh

TIL - How to Change Emojis in nh Recently I have been trying to update the emojis when I run nh. Particularly the nom output. The old output was like so: To fix this update your nh derivation like so: environment.systemPackages = with pkgs; [ (pkgs.nh.override { nix-output-monitor = pkgs.nix-output-monitor.overrideAttrs (old: { postPatch = old.postPatch or "" + '' substituteInPlace lib/NOM/Print.hs \ --replace 'down = "↓"' 'down = "\xf072e"' \ --replace 'up = "↑"' 'up = "\xf0737"' \ --replace 'clock = "⏱"' 'clock = "\xf520"' \ --replace 'running = "⏵"' 'running = "\xf04b"' \ --replace 'done = "✔"' 'done = "\xf00c"' \ --replace 'todo = "⏸"' 'todo = "\xf04d"' \ --replace 'warning = "⚠"' 'warning = "\xf071"' \ --replace 'average = "∅"' 'average = "\xf1da"' \ --replace 'bigsum = "∑"' 'bigsum = "\xf04a0"' ''; }); }) ]; Note you will no longer be able to use the default nix cache to build this. So everytime nh updates you will need to manually build it. ...

Posted On:  2025-08-10 166 words 1 min

Voxicle Build Log 16

⏮️ Previous Build Log Objectives Finish the setting page Improve observability Send data to LGTM Grafana Cloud 🛠️ What I Worked On Observability This was more for my Gophercon talk, but I fixed the local LGTM stack setup so that we can send logs, metrics and traces and view it all in Grafana. Then correleate them correctly and move between them in the GUI. Worked on the terraform code to then create the same stack in Grafana cloud to setup the LGTM stack. Including deploying an alloy agent on my VPS. So we can send all of our OTLP data their and have consumed by the Grafana cloud. ...

How to Use Tailscale GitLab CI to Deploy to Our Nix Home lab

Background So I have a small home lab, where I have a few random things running, like a GitLab CI runner, a media server etc. All my home lab servers (3 of them) are running NixOS and are defined within my Nix flake what services they run. For example: https://gitlab.com/hmajid2301/nixicle/-/blob/main/systems/x86_64-linux/ms01/default.nix?ref_type=heads They are set up using nixos-anywhere like most of my other services. Then using deploy-rs we can ssh onto our home lab servers and deploy nix config, i.e. updating packages. ...

How to Fix Shell Completions When Using Nix Direnv and Fish Shell

If you read this post, I finally managed to figure out how to get shell completions in fish shell when you install a tool using a devshell in Nix, while using direnv. This plugin makes sure that the fish shell completions get resynced. Currently, I am using a fork of the original plugin, as the fish shell v4 broke it but eventually can use the original. How it works: Fish will search $fish_complete_path dynamically, so the idea is to implement a function which listens for changes to $XDG_DATA_DIRS, and attempts to keep that in sync with $fish_complete_path. ...

Posted On:  2025-07-02 193 words 1 min

Voxicle Build Log 15

⏮️ Previous Build Log Objectives Mark feedback public/private Start on settings page 🛠️ What I Worked On Mark feedback as private/public Logged in users can mark feedback as private so it won’t be shown on the public dashboard. Gitlab Dependency Proxy I started using the Gitlab dependency proxy so that we can pull in image from Docker hub using Gitlab to avoid hiting rate limits. But also means we can use image cache which should makes jobs a quicker when pulling say postgres. ...

How to Use the GitLab Proxy in CI

Personal Projects For the moment, the GitLab proxy will not work if the project is in your personal namespace i.e. gitlab.com/hmajid2301. So to make it work with my project Voxicle I had to move to its own group. GitLab Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/323773 Background The GitLab dependency proxy, allows us to cache Docker images that we pull from Docker Hub. This allows us to reduce bandwidth and speed up builds, i.e. quicker to pull Postgres for our tests in CI. ...

Posted On:  2025-06-18 345 words 2 min

Voxicle Build Log 14

⏮️ Previous Build Log Objectives Public page for feedback private and public feedbacks allow anonymous voting 🛠️ What I Worked On Public Feedback Dashboard We started of with this: And finish with this Users can now do the almost everything they can when logged in but when anonymous. We attach a deviceID cookie to them to be able to spot if its the same user. This only works for the same device and until they clear their cookies but should be good enough for most of the users I think for now. ...

Voxicle Build Log 13

I will stop making these weekly I think and produce them when there is actual stuff to share, as not make them stale and boring. Some times they may end up weekly, depending on how much progress I am making. ⏮️ Previous Build Log Objectives ✅ Better error modals (fixed) ✅ Start working on public page ✅ Multi tenant sub domains i.e. org1.voxicle.app 🛠️ What I Worked On Error Modal Bug I have some middleware that will show an error modal when we return an error back to the client. I may change this to be a toast for certain actions vs a full on modal but we can do that in the middleware. ...

Part 8: Neovim as Part of Your Development Workflow

After another 5 months (again) I’m finally back blogging about my development setup, opps! What is Neovim? Neovim is a text editor, that you can run in your terminal. Much like vim and vi or nano. So we would run this inside our terminal emulator and Zellij. It differs from vim because you can configure it using lua vs vimscript . Some of the other unique features it had, you can now do in vim (I believe). Such as tree sitter support and LSPs. ...

Posted On:  2025-05-15 2340 words 11 min

Voxicle Build Log Week 12

⏮️ Last Weeks Objectives Implement Authorization using RLS in Postgres Better error modals (fixed) 🛠️ What I Worked On 🔒 Row Level Security (Authorization) Row Level Security for Feedback and Upvotes. With row level security we can add policies and use config variables. Such that we set the organization ID and users can only get feedback that is part of their organization. This means we can simplify our SQL queries with fewer joins and fewer where clauses. Making them easier to read. Essentially it lets us do a simple form of authorization inside the web app. ...

How I Setup Tailwindcss LSP With Neovim & Nix (With DaisyUI)

Recently, I have been building an app (https://voxicle.app #ShamelessPlug), with tailwind and DaisyUI. I have been having issues getting the tailwind LSP to work nicely in Neovim, and only recently managed to make it work. So in this article, I will go over how I set up, assuming you are using Nix as a package manager. Why Nix? In my project, it is a go web app, so all the dependencies in the project are managed as go modules by my go.mod file. Then everything else the developer needs is set up as a dev shell. Things like the standalone tailwind CLI, I am using a nix flake which already has DaisyUI built in so it can also generate those types i.e. btn in the final styles.css (or whatever you called it). The flake is here: https://github.com/aabccd021/tailwindcss-daisyui-nix ...

Voxicle Week 11

Cricket is back this week, so I didn’t have as much time as I would over the weekend as I was out playing both weekends. But I made progress every day even a little on Voxicle. I need to work out, what the minimum features I want before I start to market and share with others to try it and provide feedback. Last Week Fixed my Tailwind LSP for a better DevEx Improved my Gitlab CI file when building the dev Docker image Improved the UI Allow users to change the sort filters i.e. latest or oldest Next Week Implement Authorization using RLS in Postgres Better error modals (fixed)

Why I Built a Web App With HTMX, Go & Postgres

Introduction Recently, I have started to build apps using the web stack: frontend htmx tailwindcss daisyui alpine backend go templ postgres devex gitlab ci nix devshells I have now built two apps using this stack, one of them being banterbus.games a browser-based party game (currently broken). Using web sockets, so it isn’t the most normal web application. As there are a few quirks of web sockets. Banter Bus Code: https://gitlab.com/hmajid2301/banterbus I am currently building a more normal CRUD app, called Voxicle (https://voxicle.app), a SaaS platform for collecting and acting on user feedback. The first time, I am trying to build something which I will charge others for (hence the code also not being open-source yet). Some more context here: https://haseebmajid.dev/posts/2025-03-03-go-feedback-my-new-side-project/ ...

TIL - How to Set Dynamic URL With HTMX and AlpineJS

TLDR; Add this attribute to your x-bind:hx-delete x-effect="currentItemId;htmx.process($el)" as an example (adjust for your example). Background In my app, I show the user 25 feedbacks per page, and they can delete them which opens a modal to confirm the action. If the user presses the delete button in the modal I want to send a HTTP DELETE request to an endpoint like /feedback/{id}, but the ID is dynamic, as we are using one modal for all the feedbacks vs having one modal per one feedback. ...

TIL - Fix Telescope Ignoring Env Files

Recently I noticed when I searched using Telescope in Neovim, that I could see env.local.template but not .env.local. Where my keybinding looked like this: vim.keymap.set("n", "<leader>ff", function() builtin.find_files({ hidden = true, follow = true }) end, { desc = "Find all files" }) This was because I was ignoring the .env* paths in my gitignore, I could tell telescope to not follow the gitignore. But I would get a lot more junk when searching in Telescope. I just wanted to see certain patterns but still mostly respect the gitignore file. You can do the following: ...

Voxicle Week 9 & Week 10

Last 2 week Again got really busy with some personal stuff, and stuff at work so didn’t really have much motivation to work on this project. But I have been forcing myself to code, so at least make some progeres. I did the following: Worked out we can use row level security in Postgres for better authorization Added lots more tests Edit Feedback Dynamic URL using Alpine Figure out duplication bug Filter on search More filter options Next Week Next week I want to; ...

Voxicle Week 7 & Week 8

Last 2 week Some stuff kept me busy so I couldn’t really work on my project work. I did the following: Added tests E2E with new skeleton How to debug E2E tests with delve (i.e. the server running separately) Fixed a bunch of TODOs in the code base Delete feedback However I got a busy with other random pieces of work that come up that kept me busy. Hopefully this week will be more productive. ...

TIL - How to Get Dropbar and Auto Session to Work

Original Article You can find more context on the problem here In my post last month I thought I had fixed this issue but turns out I did not. The actual fix to stop getting this error: 5108: Error executing lua [string "v:lua"]:1: attempt to call global 'dropbar' (a nil value) stack traceback: [string "v:lua"]:1: in main chunk bat /home/haseeb/.local/share/nixCats-nvim/sessions/%2Fhome%2Fhaseeb%2Fprojects%2Fvoxicle.vim | rg dropbar setlocal winbar=%{%v:lua.dropbar()%} setlocal winbar=%{%v:lua.dropbar()%} setlocal winbar=%{%v:lua.dropbar()%} We want the winbar to nil. The fix that worked for me was this: ...