{"@attributes":{"version":"2.0"},"channel":{"title":"Haseeb Majid","link":"https:\/\/haseebmajid.dev\/","description":"Recent content on Haseeb Majid","generator":"Hugo -- gohugo.io","language":"en","lastBuildDate":"Mon, 09 Mar 2026 00:00:00 +0000","item":[{"title":"TIL - How to Git Push to Multiple Repositories","link":"https:\/\/haseebmajid.dev\/posts\/2026-03-09-til-how-to-git-push-to-multiple-repositories\/","pubDate":"Mon, 09 Mar 2026 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2026-03-09-til-how-to-git-push-to-multiple-repositories\/","description":"<p>I have a personal project that I wanted to push to both tangled.sh (self-hosted) and GitLab. In case something\nhappened to my personal homelab and backups.<\/p>\n<p>You can do this but adding another remote i.e. <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">git remote set-url --add --push origin git@gitlab.com:hmajid2301\/go-routinely.git\n<\/span><\/span><\/code><\/pre><\/div><blockquote>\n<p>Make sure to add both repositories with this command<\/p>\n<\/blockquote>\n<p>Then when you go git push it will push to all repositories.<\/p>\n<p>You can double check with:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">goroutinely on \ue0a0 fix\/ci <span class=\"o\">[<\/span>$<span class=\"o\">]<\/span> via \ud83d\udc39 v1.25.5 via \u2744  impure <span class=\"o\">(<\/span>nix-shell-env<span class=\"o\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u276f git remote show origin\n<\/span><\/span><span class=\"line\"><span class=\"cl\">Welcome to this knot!\n<\/span><\/span><span class=\"line\"><span class=\"cl\">* remote origin\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  Fetch URL: git@git.haseebmajid.dev:majiy00.tngl.sh\/go-routinely\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  Push  URL: git@git.haseebmajid.dev:majiy00.tngl.sh\/go-routinely\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  Push  URL: git@gitlab.com:hmajid2301\/go-routinely.git\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  HEAD branch: main\n<\/span><\/span><\/code><\/pre><\/div><div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"fn:1\">\n<p><a href=\"https:\/\/stackoverflow.com\/questions\/14290113\/git-pushing-code-to-two-remotes\">https:\/\/stackoverflow.com\/questions\/14290113\/git-pushing-code-to-two-remotes<\/a>&#160;<a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">&#x21a9;&#xfe0e;<\/a><\/p>"},{"title":"My Year in Review 2025","link":"https:\/\/haseebmajid.dev\/posts\/2026-01-01-my-year-in-review-2025\/","pubDate":"Thu, 01 Jan 2026 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2026-01-01-my-year-in-review-2025\/","description":"<p>Another year has passed, and it&rsquo;s time to reflect on what I accomplished, what I learned, and where I&rsquo;m\nheading next. 2025 was a year of shipping projects, learning new technologies, and making some significant\nlife changes.<\/p>\n<h2 id=\"looking-back-2025-goals-review\">Looking Back: 2025 Goals Review<\/h2>\n<p>My core aims were:<\/p>\n<ul>\n<li>Release a working version of Banter Bus by end of January<\/li>\n<li>Try to release say 20ish YouTube videos next year<\/li>\n<li>Look at making some money from my side projects<\/li>\n<\/ul>\n<p>I successfully completed the first goal, though the other two took a back seat due to changing priorities.\nWith regards to YouTube, I didn&rsquo;t really find the motivation to make videos. I will likely have another\ncrack at it this year, aiming at creating content with simpler editing which takes less effort.<\/p>"},{"title":"How to Setup a New PC With Lanzaboote, TPM Decryption, sops-nix, Impermanence and nixos-anywhere","link":"https:\/\/haseebmajid.dev\/posts\/2025-12-31-how-to-setup-a-new-pc-with-lanzaboote-tpm-decryption-sops-nix-impermanence-nixos-anywhere\/","pubDate":"Wed, 31 Dec 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-12-31-how-to-setup-a-new-pc-with-lanzaboote-tpm-decryption-sops-nix-impermanence-nixos-anywhere\/","description":"<h2 id=\"background\">Background<\/h2>\n<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Be Careful<\/summary>\n  \n  <p>Make sure if you follow this guide you could lose your data. Make sure to back up whatever important data you have.\nOr do what I did and test this on a new device where it doesn&rsquo;t matter if something goes wrong.<\/p>\n<p>But don&rsquo;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\nset up a new laptop in about 20 mins once I got everything working. It can be fiddly.<\/p>"},{"title":"TIL - How to Fix Tailscale Using Mullvad as Exit Nodes on NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2025-12-29-til-how-to-fix-tailscale-using-mullvad-as-exit-nodes-on-nixos\/","pubDate":"Mon, 29 Dec 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-12-29-til-how-to-fix-tailscale-using-mullvad-as-exit-nodes-on-nixos\/","description":"<p>On NixOS when ever I enabled <a href=\"https:\/\/tailscale.com\/kb\/1258\/mullvad-exit-nodes\">mullvad<\/a> as exit nodes via tailscale (the <a href=\"https:\/\/github.com\/DeedleFake\/trayscale\">trayscale app<\/a>).\nMy internet would stop working, which was weird as this worked fine on my other devices i.e. Ubuntu or my phone.<\/p>\n<p>Well turns out it seems to be the way NixOS works with the firewall, you can read all the details here <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>. Where\nthe poster explains it really well.<\/p>\n<p>My understanding is the following:<\/p>\n<p>This changes RPF (reverse path filtering) from &ldquo;strict&rdquo; to &ldquo;loose&rdquo; mode:<\/p>"},{"title":"TIL - How to Fix App Lounge Updates Getting Stuck (MurenaOS\/eOS)","link":"https:\/\/haseebmajid.dev\/posts\/2025-12-28-til-how-to-fix-app-lounge-updates-getting-stuck-murenaos-eos-\/","pubDate":"Sun, 28 Dec 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-12-28-til-how-to-fix-app-lounge-updates-getting-stuck-murenaos-eos-\/","description":"<p>If you use a FairPhone, or a phone running <a href=\"https:\/\/e.foundation\/e-os\/\">eOS\/MurenaOS<\/a>, which is as degoogled version of\nAndroid (no affiliation to me besides I use their devices\/OS).<\/p>\n<p>Sometimes the app store &ldquo;App Lounge&rdquo; gets stuck updating apps, my old solution was to delete the app and reinstall it\nbut that can be a pain. Then I discovered a slightly better solution.<\/p>\n<ul>\n<li>Go to settings<\/li>\n<li>Apps &amp; Notifications<\/li>\n<li>Find App Lounge<\/li>\n<li>Then go to Storage &amp; cache<\/li>\n<li>Clear storage and &ldquo;Delete app data&rdquo;<\/li>\n<\/ul>\n<p>You will need to log in again to the app, but the update process shouldn&rsquo;t get stuck anymore hopefully.<\/p>"},{"title":"How to Fix PAM Issues With Home Manager on Non-NixOS Setups","link":"https:\/\/haseebmajid.dev\/posts\/2025-12-12-how-to-fix-pam-issues-with-home-manager-on-non-nixos-setups\/","pubDate":"Fri, 12 Dec 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-12-12-how-to-fix-pam-issues-with-home-manager-on-non-nixos-setups\/","description":"<blockquote>\n<p>[!WARNING]\nThe pam_shim is POC code, so be careful with using it on your own machine. Use it at your own risk.<\/p>\n<\/blockquote>\n<h2 id=\"the-problem\">The problem<\/h2>\n<p>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.\nOn my home setup I have been using Niri with Noctalia shell (quickshell) on NixOS. Everything works fine I can use\nthe Noctalia shell lock screen and can authenticate fine.<\/p>"},{"title":"TIL - How to Enable Video Thumbnails for SMB Share on Nixos and Nautilus","link":"https:\/\/haseebmajid.dev\/posts\/2025-11-06-til-how-to-enable-video-thumbnails-for-smb-share-on-nixos\/","pubDate":"Thu, 06 Nov 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-11-06-til-how-to-enable-video-thumbnails-for-smb-share-on-nixos\/","description":"<p>So recently I have setup a mini NAS and I connect to it via an SMB share, but on nautilus I noticed that\nunlike my local files for the videos it would not create thumbnails when I was using nautilus (file manager for Gnome).<\/p>\n<p>The fix ended up being pretty simple <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>:<\/p>\n<pre tabindex=\"0\"><code>Nautilus &gt; Preference &gt; Show thumbnails.\n\nSet it to &#34;On this computer only&#34; for only seeing thumbnails on your system, .\n\nIf u need it to do same for a remote server, select &#34;All files&#34;\n<\/code><\/pre><p>Or since we are managing this via NixOS and want to do things declaratively we can do do the following in our Nix config <sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2<\/a><\/sup>.<\/p>"},{"title":"Yak Shaving: Neotest Edition","link":"https:\/\/haseebmajid.dev\/posts\/2025-11-02-yak-shaving-neotest-edition\/","pubDate":"Sun, 02 Nov 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-11-02-yak-shaving-neotest-edition\/","description":"<p><strong>TL;DR:<\/strong> The fix is in this commit: <a href=\"https:\/\/gitlab.com\/hmajid2301\/nixicle\/-\/commit\/cfababc9e3a1dfdd1917d0b87cb17fcdd655bfdc\">https:\/\/gitlab.com\/hmajid2301\/nixicle\/-\/commit\/cfababc9e3a1dfdd1917d0b87cb17fcdd655bfdc<\/a>  Fixing stuff is fun! \ud83e\udd73<\/p>\n<h2 id=\"background\">Background<\/h2>\n<p>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? \ud83d\ude09 Otherwise, why would I go through the pain I experienced today? &ldquo;What pain?&rdquo; you ask. Good question!<\/p>\n<p>A few weeks ago, I noticed that running tests in Neovim was failing with a <code>no test found<\/code> error. I&rsquo;m using <code>neotest<\/code> and <code>neotest-golang<\/code> to run tests within Neovim.<\/p>"},{"title":"TIL - How to Change Emojis in nh","link":"https:\/\/haseebmajid.dev\/posts\/2025-08-10-til-how-to-change-emojis-in-nh\/","pubDate":"Sun, 10 Aug 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-08-10-til-how-to-change-emojis-in-nh\/","description":"<p><strong>TIL - How to Change Emojis in nh<\/strong><\/p>\n<p>Recently I have been trying to update the emojis when I run <a href=\"https:\/\/github.com\/nix-community\/nh\">nh<\/a>. Particularly\nthe nom output.<\/p>\n<p>The old output was like so:<\/p>\n<p><\/p>\n<p>To fix this update your nh derivation like so:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-nix\" data-lang=\"nix\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">environment<\/span><span class=\"o\">.<\/span><span class=\"n\">systemPackages<\/span> <span class=\"err\">=<\/span> <span class=\"k\">with<\/span> <span class=\"n\">pkgs<\/span><span class=\"p\">;<\/span> <span class=\"p\">[<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"p\">(<\/span><span class=\"n\">pkgs<\/span><span class=\"o\">.<\/span><span class=\"n\">nh<\/span><span class=\"o\">.<\/span><span class=\"n\">override<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">nix-output-monitor<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pkgs<\/span><span class=\"o\">.<\/span><span class=\"n\">nix-output-monitor<\/span><span class=\"o\">.<\/span><span class=\"n\">overrideAttrs<\/span> <span class=\"p\">(<\/span><span class=\"n\">old<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"n\">postPatch<\/span> <span class=\"o\">=<\/span> <span class=\"n\">old<\/span><span class=\"o\">.<\/span><span class=\"n\">postPatch<\/span> <span class=\"n\">or<\/span> <span class=\"s2\">&#34;&#34;<\/span> <span class=\"o\">+<\/span> <span class=\"s1\">&#39;&#39;\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">        substituteInPlace lib\/NOM\/Print.hs \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;down = &#34;\u2193&#34;&#39; &#39;down = &#34;\\xf072e&#34;&#39; \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;up = &#34;\u2191&#34;&#39; &#39;up = &#34;\\xf0737&#34;&#39; \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;clock = &#34;\u23f1&#34;&#39; &#39;clock = &#34;\\xf520&#34;&#39; \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;running = &#34;\u23f5&#34;&#39; &#39;running = &#34;\\xf04b&#34;&#39; \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;done = &#34;\u2714&#34;&#39; &#39;done = &#34;\\xf00c&#34;&#39; \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;todo = &#34;\u23f8&#34;&#39; &#39;todo = &#34;\\xf04d&#34;&#39; \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;warning = &#34;\u26a0&#34;&#39; &#39;warning = &#34;\\xf071&#34;&#39; \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;average = &#34;\u2205&#34;&#39; &#39;average = &#34;\\xf1da&#34;&#39; \\\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">          --replace &#39;bigsum = &#34;\u2211&#34;&#39; &#39;bigsum = &#34;\\xf04a0&#34;&#39;\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s1\">      &#39;&#39;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">});<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"p\">})<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">];<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Note you will no longer be able to use the default nix cache to build this. So everytime nh updates you will need to\nmanually build it.<\/p>"},{"title":"Voxicle Build Log 16","link":"https:\/\/haseebmajid.dev\/posts\/2025-07-07-voxicle-build-log-16\/","pubDate":"Mon, 04 Aug 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-07-07-voxicle-build-log-16\/","description":"<h2 id=\"-previous-build-log-objectives\">\u23ee\ufe0f Previous Build Log Objectives<\/h2>\n<ul>\n<li>Finish the setting page<\/li>\n<li>Improve observability\n<ul>\n<li>Send data to LGTM Grafana Cloud<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2 id=\"-what-i-worked-on\">\ud83d\udee0\ufe0f What I Worked On<\/h2>\n<h3 id=\"observability\">Observability<\/h3>\n<p>This was more for my Gophercon talk, but I fixed the local LGTM stack setup so that we can send logs, metrics and traces\nand view it all in Grafana. Then correleate them correctly and move between them in the GUI.<\/p>\n<p>Worked on the terraform code to then create the same stack in Grafana cloud to setup the LGTM stack. Including deploying\nan alloy agent on my VPS. So we can send all of our OTLP data their and have consumed by the Grafana cloud.<\/p>"},{"title":"How to Use Tailscale GitLab CI to Deploy to Our Nix Home lab","link":"https:\/\/haseebmajid.dev\/posts\/2025-07-10-how-to-use-tailscale-gitlab-ci-to-deploy-to-our-nix-homelab\/","pubDate":"Thu, 10 Jul 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-07-10-how-to-use-tailscale-gitlab-ci-to-deploy-to-our-nix-homelab\/","description":"<h2 id=\"background\">Background<\/h2>\n<p>So I have a small home lab, where I have a few random things running, like a GitLab CI runner, a media server etc.\nAll my home lab servers (3 of them) are running NixOS and are defined within my Nix flake what services they run.<\/p>\n<p>For example: <a href=\"https:\/\/gitlab.com\/hmajid2301\/nixicle\/-\/blob\/main\/systems\/x86_64-linux\/ms01\/default.nix?ref_type=heads\">https:\/\/gitlab.com\/hmajid2301\/nixicle\/-\/blob\/main\/systems\/x86_64-linux\/ms01\/default.nix?ref_type=heads<\/a><\/p>\n<p>They are set up using <a href=\"https:\/\/haseebmajid.dev\/posts\/2024-05-02-part-5b-installing-our-nix-configuration-as-part-of-your-workflow\">nixos-anywhere like most of my other services<\/a>. Then using deploy-rs we can ssh onto our home lab servers and deploy nix config, i.e. updating packages.<\/p>"},{"title":"How to Fix Shell Completions When Using Nix Direnv and Fish Shell","link":"https:\/\/haseebmajid.dev\/posts\/2025-07-02-how-to-fix-shell-completions-when-using-nix-direnv\/","pubDate":"Wed, 02 Jul 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-07-02-how-to-fix-shell-completions-when-using-nix-direnv\/","description":"<p>If you read this <a href=\"https:\/\/haseebmajid.dev\/posts\/2024-09-12-til-how-to-get-shell-completions-in-nix-shell-with-direnv\/#issues\">post<\/a>,\nI finally managed to figure out how to get shell completions in fish shell when you install a tool using\na devshell in Nix, while using direnv. This plugin makes sure that the fish shell completions get resynced.<\/p>\n<p>Currently, I am using a fork of the <a href=\"https:\/\/github.com\/pfgray\/fish-completion-sync\">original plugin<\/a>,\nas the fish shell v4 broke it but eventually can use the original.<\/p>\n<p>How it works:<\/p>\n<blockquote>\n<p>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.<\/p>"},{"title":"Voxicle Build Log 15","link":"https:\/\/haseebmajid.dev\/posts\/2025-06-23-voxicle-build-log-15\/","pubDate":"Mon, 23 Jun 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-06-23-voxicle-build-log-15\/","description":"<h2 id=\"-previous-build-log-objectives\">\u23ee\ufe0f Previous Build Log Objectives<\/h2>\n<ul>\n<li>Mark feedback public\/private<\/li>\n<li>Start on settings page<\/li>\n<\/ul>\n<h2 id=\"-what-i-worked-on\">\ud83d\udee0\ufe0f What I Worked On<\/h2>\n<h3 id=\"mark-feedback-as-privatepublic\">Mark feedback as private\/public<\/h3>\n<p>Logged in users can mark feedback as private so it won&rsquo;t be shown on the public dashboard.<\/p>\n<h3 id=\"gitlab-dependency-proxy\">Gitlab Dependency Proxy<\/h3>\n<p>I started using the Gitlab dependency proxy so that we can pull in image from Docker hub using Gitlab to avoid hiting\nrate limits. But also means we can use image cache which should makes jobs a quicker when pulling say <code>postgres<\/code>.<\/p>"},{"title":"How to Use the GitLab Proxy in CI","link":"https:\/\/haseebmajid.dev\/posts\/2025-06-18-how-to-use-the-gitlab-proxy-in-ci\/","pubDate":"Wed, 18 Jun 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-06-18-how-to-use-the-gitlab-proxy-in-ci\/","description":"<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Personal Projects<\/summary>\n  \n  <p>For the moment, the GitLab proxy will not work if the project is in your personal namespace\ni.e. <code>gitlab.com\/hmajid2301<\/code>. So to make it work with my project Voxicle I had to move to its own group.<\/p>\n<p>GitLab Issue: <a href=\"https:\/\/gitlab.com\/gitlab-org\/gitlab\/-\/issues\/323773\">https:\/\/gitlab.com\/gitlab-org\/gitlab\/-\/issues\/323773<\/a><\/p>\n\n<\/details>\n\n<h2 id=\"background\">Background<\/h2>\n<p>The GitLab dependency proxy, allows us to cache Docker images that we pull from Docker Hub. This allows us to\nreduce bandwidth and speed up builds, i.e. quicker to pull Postgres for our tests in CI.<\/p>"},{"title":"Voxicle Build Log 14","link":"https:\/\/haseebmajid.dev\/posts\/2025-06-02-voxicle-build-log-14\/","pubDate":"Mon, 09 Jun 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-06-02-voxicle-build-log-14\/","description":"<h2 id=\"-previous-build-log-objectives\">\u23ee\ufe0f Previous Build Log Objectives<\/h2>\n<ul>\n<li>Public page for feedback\n<ul>\n<li>private and public feedbacks<\/li>\n<li>allow anonymous voting<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2 id=\"-what-i-worked-on\">\ud83d\udee0\ufe0f What I Worked On<\/h2>\n<h3 id=\"public-feedback-dashboard\">Public Feedback Dashboard<\/h3>\n<p>We started of with this:<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2025-06-02-voxicle-build-log-14\/images\/old_public_dashboard.png\"\n        type=\"\"\n        alt=\"Old Dashboard\"\n        \n      \/><\/p>\n<p>And finish with this<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2025-06-02-voxicle-build-log-14\/images\/new_public_dashboard.png\"\n        type=\"\"\n        alt=\"New Dashboard\"\n        \n      \/><\/p>\n<p>Users can now do the almost everything they can when logged in but when anonymous. We attach a <code>deviceID<\/code> cookie to them\nto be able to spot if its the same user. This only works for the same device and until they clear their cookies but\nshould be good enough for most of the users I think for now.<\/p>"},{"title":"Voxicle Build Log 13","link":"https:\/\/haseebmajid.dev\/posts\/2025-05-19-voxicle-build-log-week-13\/","pubDate":"Mon, 19 May 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-05-19-voxicle-build-log-week-13\/","description":"<p>I will stop making these weekly I think and produce them when there is actual stuff to share, as not make them\nstale and boring. Some times they may end up weekly, depending on how much progress I am making.<\/p>\n<h2 id=\"-previous-build-log-objectives\">\u23ee\ufe0f Previous Build Log Objectives<\/h2>\n<ul>\n<li>\u2705 Better error modals (fixed)<\/li>\n<li>\u2705 Start working on public page<\/li>\n<li>\u2705 Multi tenant sub domains\n<ul>\n<li>i.e. org1.voxicle.app<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2 id=\"-what-i-worked-on\">\ud83d\udee0\ufe0f What I Worked On<\/h2>\n<h3 id=\"error-modal-bug\">Error Modal Bug<\/h3>\n<p>I have some middleware that will show an error modal when we return an error back to the client. I may change this to\nbe a toast for certain actions vs a full on modal but we can do that in the middleware.<\/p>"},{"title":"Part 8: Neovim as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2025-05-15-part-8-neovim-as-part-of-your-development-workflow\/","pubDate":"Thu, 15 May 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-05-15-part-8-neovim-as-part-of-your-development-workflow\/","description":"<p>After another 5 months (again) I&rsquo;m finally back blogging about my development setup, opps!<\/p>\n<h2 id=\"what-is-neovim\">What is Neovim?<\/h2>\n<p>Neovim is a text editor, that you can run in your terminal. Much like <code>vim<\/code> and <code>vi<\/code> or <code>nano<\/code>. So we would run\nthis inside our terminal emulator and Zellij. It differs from vim because you can configure it using lua vs vimscript\n. Some of the other unique features it had, you can now do in vim (I believe). Such as tree sitter support and LSPs.<\/p>"},{"title":"Voxicle Build Log Week 12","link":"https:\/\/haseebmajid.dev\/posts\/2025-05-12-voxicle-build-log-week-12\/","pubDate":"Mon, 12 May 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-05-12-voxicle-build-log-week-12\/","description":"<h2 id=\"-last-weeks-objectives\">\u23ee\ufe0f Last Weeks Objectives<\/h2>\n<ul>\n<li>Implement Authorization using RLS in Postgres<\/li>\n<li>Better error modals (fixed)<\/li>\n<\/ul>\n<h2 id=\"-what-i-worked-on\">\ud83d\udee0\ufe0f What I Worked On<\/h2>\n<h3 id=\"-row-level-security-authorization\">\ud83d\udd12 Row Level Security (Authorization)<\/h3>\n<p>Row Level Security for Feedback and Upvotes. With row level security we can add policies and use config variables.\nSuch that we set the organization ID and users can only get feedback that is part of their organization.\nThis means we can simplify our SQL queries with fewer joins and fewer where clauses. Making them easier to read.\nEssentially it lets us do a simple form of authorization inside the web app.<\/p>"},{"title":"How I Setup Tailwindcss LSP With Neovim & Nix (With DaisyUI)","link":"https:\/\/haseebmajid.dev\/posts\/2025-05-06-how-i-setup-tailwindcss-lsp-with-neovim-nix-with-daisyui-\/","pubDate":"Tue, 06 May 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-05-06-how-i-setup-tailwindcss-lsp-with-neovim-nix-with-daisyui-\/","description":"<p>Recently, I have been building an app (<a href=\"https:\/\/voxicle.app\">https:\/\/voxicle.app<\/a> #ShamelessPlug), with tailwind and DaisyUI. I have been\nhaving issues getting the tailwind LSP to work nicely in Neovim, and only recently managed to make it work.\nSo in this article, I will go over how I set up, assuming you are using Nix as a package manager.<\/p>\n<h2 id=\"why-nix\">Why Nix?<\/h2>\n<p>In my project, it is a go web app, so all the dependencies in the project are managed as go modules by my <code>go.mod<\/code> file.\nThen everything else the developer needs is set up as a dev shell. Things like the standalone tailwind CLI,\nI am using a nix flake which already has DaisyUI built in so it can also generate those types i.e. <code>btn<\/code> in the final\nstyles.css (or whatever you called it). The flake is here: <a href=\"https:\/\/github.com\/aabccd021\/tailwindcss-daisyui-nix\">https:\/\/github.com\/aabccd021\/tailwindcss-daisyui-nix<\/a><\/p>"},{"title":"Voxicle Week 11","link":"https:\/\/haseebmajid.dev\/posts\/2025-05-05-voxicle-week-11\/","pubDate":"Mon, 05 May 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-05-05-voxicle-week-11\/","description":"<p>Cricket is back this week, so I didn&rsquo;t have as much time as I would over the weekend as I was out playing both weekends.\nBut I made progress every day even a little on Voxicle. I need to work out, what the minimum features I want before\nI start to market and share with others to try it and provide feedback.<\/p>\n<h2 id=\"last-week\">Last Week<\/h2>\n<ul>\n<li>Fixed my Tailwind LSP for a better DevEx<\/li>\n<li>Improved my Gitlab CI file when building the dev Docker image<\/li>\n<li>Improved the UI<\/li>\n<li>Allow users to change the sort filters i.e. latest or oldest<\/li>\n<\/ul>\n<h2 id=\"next-week\">Next Week<\/h2>\n<ul>\n<li>Implement Authorization using RLS in Postgres<\/li>\n<li>Better error modals (fixed)<\/li>\n<\/ul>"},{"title":"Why I Built a Web App With HTMX, Go & Postgres","link":"https:\/\/haseebmajid.dev\/posts\/2025-05-03-why-i-build-a-web-app-with-htmx-go-postgres\/","pubDate":"Mon, 05 May 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-05-03-why-i-build-a-web-app-with-htmx-go-postgres\/","description":"<h2 id=\"introduction\">Introduction<\/h2>\n<p>Recently, I have started to build apps using the web stack:<\/p>\n<ul>\n<li>\n<p>frontend<\/p>\n<ul>\n<li>htmx<\/li>\n<li>tailwindcss\n<ul>\n<li>daisyui<\/li>\n<\/ul>\n<\/li>\n<li>alpine<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>backend<\/p>\n<ul>\n<li>go\n<ul>\n<li>templ<\/li>\n<\/ul>\n<\/li>\n<li>postgres<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>devex<\/p>\n<ul>\n<li>gitlab ci<\/li>\n<li>nix devshells<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>I have now built two apps using this stack, one of them being <code>banterbus.games<\/code> a browser-based party game (currently broken).\nUsing web sockets, so it isn&rsquo;t the most normal web application. As there are a few quirks of web sockets.<\/p>\n<p>Banter Bus Code: <a href=\"https:\/\/gitlab.com\/hmajid2301\/banterbus\">https:\/\/gitlab.com\/hmajid2301\/banterbus<\/a><\/p>\n<p>I am currently building a more normal CRUD app, called Voxicle (<a href=\"https:\/\/voxicle.app\">https:\/\/voxicle.app<\/a>), a SaaS platform for collecting\nand acting on user feedback. The first time, I am trying to build something which I will charge others for (hence\nthe code also not being open-source yet). Some more context here: <a href=\"https:\/\/haseebmajid.dev\/posts\/2025-03-03-go-feedback-my-new-side-project\/\">https:\/\/haseebmajid.dev\/posts\/2025-03-03-go-feedback-my-new-side-project\/<\/a><\/p>"},{"title":"TIL - How to Set Dynamic URL With HTMX and AlpineJS","link":"https:\/\/haseebmajid.dev\/posts\/2025-04-29-til-set-dynamic-url-with-htmx-and-alpinejs\/","pubDate":"Tue, 29 Apr 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-04-29-til-set-dynamic-url-with-htmx-and-alpinejs\/","description":"<p>TLDR; Add this attribute to your x-bind:hx-delete <code>x-effect=&quot;currentItemId;htmx.process($el)&quot;<\/code> as an example (adjust for your example).<\/p>\n<h2 id=\"background\">Background<\/h2>\n<p>In my app, I show the user 25 feedbacks per page, and they can delete them which opens a modal to confirm the action.\nIf the user presses the delete button in the modal I want to send a HTTP DELETE request to an endpoint like\n<code>\/feedback\/{id}<\/code>, but the ID is dynamic, as we are using one modal for all the feedbacks vs having one modal\nper one feedback.<\/p>"},{"title":"TIL - Fix Telescope Ignoring Env Files","link":"https:\/\/haseebmajid.dev\/posts\/2025-04-28-til-fix-telescope-ignoring-env-files\/","pubDate":"Mon, 28 Apr 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-04-28-til-fix-telescope-ignoring-env-files\/","description":"<p>Recently I noticed when I searched using Telescope in Neovim, that I could see <code>env.local.template<\/code> but not\n<code>.env.local<\/code>.<\/p>\n<p>Where my keybinding looked like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-lua\" data-lang=\"lua\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">vim.keymap<\/span><span class=\"p\">.<\/span><span class=\"n\">set<\/span><span class=\"p\">(<\/span><span class=\"s2\">&#34;n&#34;<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&#34;&lt;leader&gt;ff&#34;<\/span><span class=\"p\">,<\/span> <span class=\"kr\">function<\/span><span class=\"p\">()<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">builtin.find_files<\/span><span class=\"p\">({<\/span> <span class=\"n\">hidden<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span><span class=\"p\">,<\/span> <span class=\"n\">follow<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">true<\/span> <span class=\"p\">})<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"kr\">end<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"n\">desc<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&#34;Find all files&#34;<\/span> <span class=\"p\">})<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>This was because I was ignoring the <code>.env*<\/code> paths in my gitignore, I could tell telescope to not follow the gitignore.\nBut I would get a lot more junk when searching in Telescope. I just wanted to see certain patterns but still\nmostly respect the gitignore file. You can do the following:<\/p>"},{"title":"Voxicle Week 9 & Week 10","link":"https:\/\/haseebmajid.dev\/posts\/2025-04-28-voxicle-week-9-week-10\/","pubDate":"Mon, 28 Apr 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-04-28-voxicle-week-9-week-10\/","description":"<h3 id=\"last-2-week\">Last 2 week<\/h3>\n<p>Again got really busy with some personal stuff, and stuff at work so didn&rsquo;t really have much motivation to work\non this project. But I have been forcing myself to code, so at least make some progeres.<\/p>\n<p>I did the following:<\/p>\n<ul>\n<li>Worked out we can use row level security in Postgres for better authorization<\/li>\n<li>Added lots more tests<\/li>\n<li>Edit Feedback\n<ul>\n<li>Dynamic URL using Alpine<\/li>\n<\/ul>\n<\/li>\n<li>Figure out duplication bug<\/li>\n<li>Filter on search<\/li>\n<li>More filter options<\/li>\n<\/ul>\n<h3 id=\"next-week\">Next Week<\/h3>\n<p>Next week I want to;<\/p>"},{"title":"Voxicle Week 7 & Week 8","link":"https:\/\/haseebmajid.dev\/posts\/2025-04-14-voxicle-week-7-week-8\/","pubDate":"Mon, 14 Apr 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-04-14-voxicle-week-7-week-8\/","description":"<h3 id=\"last-2-week\">Last 2 week<\/h3>\n<p>Some stuff kept me busy so I couldn&rsquo;t really work on my project work.<\/p>\n<p>I did the following:<\/p>\n<ul>\n<li>Added tests\n<ul>\n<li>E2E with new skeleton<\/li>\n<li>How to debug E2E tests with delve (i.e. the server running separately)<\/li>\n<\/ul>\n<\/li>\n<li>Fixed a bunch of TODOs in the code base<\/li>\n<li>Delete feedback<\/li>\n<\/ul>\n<p>However I got a busy with other random pieces of work that come up that kept me busy. Hopefully this week will be\nmore productive.<\/p>"},{"title":"TIL - How to Get Dropbar and Auto Session to Work","link":"https:\/\/haseebmajid.dev\/posts\/2025-04-12-til-how-to-get-dropbar-and-auto-session-to-work\/","pubDate":"Sat, 12 Apr 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-04-12-til-how-to-get-dropbar-and-auto-session-to-work\/","description":"<details\n  class=\"notice info\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Original Article<\/summary>\n  \n  You can find more context on the problem <a href=\"https:\/\/haseebmajid.dev\/posts\/2025-03-22-til-fix-issue-with-dropbar-and-auto-session\">here<\/a>\n<\/details>\n\n<p>In my post last month I thought I had fixed this issue but turns out I did not. The actual fix to stop getting\nthis error:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">5108: Error executing lua <span class=\"o\">[<\/span>string <span class=\"s2\">&#34;v:lua&#34;<\/span><span class=\"o\">]<\/span>:1: attempt to call global <span class=\"s1\">&#39;dropbar&#39;<\/span> <span class=\"o\">(<\/span>a nil value<span class=\"o\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">stack traceback:\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        <span class=\"o\">[<\/span>string <span class=\"s2\">&#34;v:lua&#34;<\/span><span class=\"o\">]<\/span>:1: in main chunk\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">bat \/home\/haseeb\/.local\/share\/nixCats-nvim\/sessions\/%2Fhome%2Fhaseeb%2Fprojects%2Fvoxicle.vim <span class=\"p\">|<\/span> rg dropbar\n<\/span><\/span><span class=\"line\"><span class=\"cl\">setlocal <span class=\"nv\">winbar<\/span><span class=\"o\">=<\/span>%<span class=\"o\">{<\/span>%v:lua.dropbar<span class=\"o\">()<\/span>%<span class=\"o\">}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">setlocal <span class=\"nv\">winbar<\/span><span class=\"o\">=<\/span>%<span class=\"o\">{<\/span>%v:lua.dropbar<span class=\"o\">()<\/span>%<span class=\"o\">}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">setlocal <span class=\"nv\">winbar<\/span><span class=\"o\">=<\/span>%<span class=\"o\">{<\/span>%v:lua.dropbar<span class=\"o\">()<\/span>%<span class=\"o\">}<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>We want the winbar to nil. The fix that worked for me was this:<\/p>"},{"title":"Voxicle Week 6","link":"https:\/\/haseebmajid.dev\/posts\/2025-03-31-voxicle-week-6\/","pubDate":"Mon, 31 Mar 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-03-31-voxicle-week-6\/","description":"<h3 id=\"this-week\">This week<\/h3>\n<p>I did the following:<\/p>\n<ul>\n<li>Finish core feedback page\n<ul>\n<li>Add new feedback<\/li>\n<li>upvote<\/li>\n<li>display as list or grid<\/li>\n<\/ul>\n<\/li>\n<li>Stretch\n<ul>\n<li>try to implement basic RBAC (more of a PoC)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>However I got a busy with other random pieces of work that come up that kept me busy. Hopefully this week will be\nmore productive.<\/p>\n<h3 id=\"next-week\">Next Week<\/h3>\n<p>Next week I want to;<\/p>\n<ul>\n<li>Finish core feedback page\n<ul>\n<li>search<\/li>\n<li>display as list or grid<\/li>\n<li>email updates when a feature has been completed<\/li>\n<li>more filter options<\/li>\n<\/ul>\n<\/li>\n<li>Stretch\n<ul>\n<li>public\/private views<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Carry on working on the core feature set and make it so we can share with other people.<\/p>"},{"title":"Voxicle Week 5","link":"https:\/\/haseebmajid.dev\/posts\/2025-03-24-voxicle-week-5\/","pubDate":"Mon, 24 Mar 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-03-24-voxicle-week-5\/","description":"<h3 id=\"this-week\">This week<\/h3>\n<p>On my list of tasks I had the following:<\/p>\n<ul>\n<li>Fix auth refresh token flow not fully working<\/li>\n<li>Add span information to the auth middleware<\/li>\n<li>Simplify templ with pop drilling<\/li>\n<li>Update project name<\/li>\n<\/ul>\n<p>And managed to do all of them, even starting to work the core feedback part of the application i.e. allowing\nusers to actually add feedback to the project. I rebranded the app from Go Feedback to Voxicle (which means voice and cycle).<\/p>"},{"title":"TIL: How to Fix Issue With Dropbar and Auto Session","link":"https:\/\/haseebmajid.dev\/posts\/2025-03-22-til-fix-issue-with-dropbar-and-auto-session\/","pubDate":"Sat, 22 Mar 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-03-22-til-fix-issue-with-dropbar-and-auto-session\/","description":"<details\n  class=\"notice danger\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Actual Fix<\/summary>\n  \n  This fix didn&rsquo;t actually work the actual fix can be found <a href=\"https:\/\/haseebmajid.dev\/posts\/2025-04-12-til-how-to-get-dropbar-and-auto-session-to-work\">here<\/a>\n<\/details>\n\n<p>I recently moved to <a href=\"https:\/\/github.com\/Bekaboo\/dropbar.nvim\">dropbar<\/a> from barbecue as it has been archived and kept\ngetting a weird error for buffer open when I would reopen Neovim. I use the <a href=\"https:\/\/github.com\/rmagatti\/auto-session\">auto-session plugin<\/a>,\nwhich loads back the previous state of NixVim when I last exited in that folder, i.e. open buffers.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-lua\" data-lang=\"lua\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">E5108<\/span><span class=\"p\">:<\/span> <span class=\"n\">Error<\/span> <span class=\"n\">executing<\/span> <span class=\"n\">lua<\/span> <span class=\"p\">[<\/span><span class=\"n\">string<\/span> <span class=\"s2\">&#34;v:lua&#34;<\/span><span class=\"p\">]:<\/span><span class=\"mi\">1<\/span><span class=\"p\">:<\/span> <span class=\"n\">attempt<\/span> <span class=\"n\">to<\/span> <span class=\"n\">call<\/span> <span class=\"n\">global<\/span> <span class=\"s1\">&#39;dropbar&#39;<\/span> <span class=\"p\">(<\/span><span class=\"n\">a<\/span> <span class=\"kc\">nil<\/span> <span class=\"n\">value<\/span><span class=\"p\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"n\">stack<\/span> <span class=\"n\">traceback<\/span><span class=\"p\">:<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        <span class=\"p\">[<\/span><span class=\"n\">string<\/span> <span class=\"s2\">&#34;v:lua&#34;<\/span><span class=\"p\">]:<\/span><span class=\"mi\">1<\/span><span class=\"p\">:<\/span> <span class=\"kr\">in<\/span> <span class=\"n\">main<\/span> <span class=\"n\">chunk<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>I noticed though I would only get this error the second time I would open Neovim, which then made think maybe it was\nan issue with auto-session. So I looked at the serialised file it generates so it knows what to load when we open\nNeovim again. Which I found at:<\/p>"},{"title":"Go Feedback Week 4","link":"https:\/\/haseebmajid.dev\/posts\/2025-03-17-go-feedback-week-4\/","pubDate":"Mon, 17 Mar 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-03-17-go-feedback-week-4\/","description":"<h3 id=\"this-week\">This week<\/h3>\n<p>I decided to use wristband to the tenant and then organization on my side of the app. I am not fully happy with it.\nDuring sign up the user creates a tenant but that might be confusing to the customer vs telling them its an organization.\nBut it does mean a new user is created and tenant on both wristband side and in the service database.<\/p>\n<p>Then I moved onto working on the subscription logic with paddle. Updated the pricing page to pull in data from the\nbackend when populating the page. Also integrating the overlay checkout, which is the simplest way to integrate\npaddle with my app. I cannot style it as much as the inline one, but it involves writing less JS. So I will use that\nfor now. I am finishing off the subscription webhook logic, to create the data on our side.<\/p>"},{"title":"Go Feedback Week 3","link":"https:\/\/haseebmajid.dev\/posts\/2025-03-10-go-feedback-week-3\/","pubDate":"Mon, 10 Mar 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-03-10-go-feedback-week-3\/","description":"<h3 id=\"week-3\">Week 3<\/h3>\n<p>I finished off the auth flow this week, decided to move over to using the wristband UI instead of using my own components.\nIt ended up being a lot of code which was nice to actually delete and I think the wristband setup is pretty nice\nand slick. I had to adjust slightly how I will create users in my own DB but it wasn&rsquo;t a big deal.<\/p>"},{"title":"Go Feedback My New Side Project","link":"https:\/\/haseebmajid.dev\/posts\/2025-03-03-go-feedback-my-new-side-project\/","pubDate":"Mon, 03 Mar 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-03-03-go-feedback-my-new-side-project\/","description":"<h2 id=\"background\">Background<\/h2>\n<p>Last year, I worked on two main side projects:<\/p>\n<ul>\n<li>OptiNix: CLI tool to easily find nix options.<\/li>\n<li>Banter Bus: My third attempt at building a browser based multi-player game.<\/li>\n<\/ul>\n<p>Whilst Banter Bus is not fully done, I got it to an almost working state and at some point will go back and fix a bunch\nof the bugs and add some new features.<\/p>\n<p>However, I finally decided I wanted to try my hand at building something that I could try to make some money from.\nWhilst also learning more about business, product design etc. How can I launch an actual product vs building something?\nPurely for fun.<\/p>"},{"title":"How to Fix Firefox Rendering Emoji Font (NixOS)","link":"https:\/\/haseebmajid.dev\/posts\/2025-01-20-how-to-fix-firefox-rendering-emoji-font-black-bold-numbers-issue\/","pubDate":"Mon, 20 Jan 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-01-20-how-to-fix-firefox-rendering-emoji-font-black-bold-numbers-issue\/","description":"<p>I was some issues with the ways some fonts were rendering in Nix\/NixOS machines. It seemed to specifically effect\na few apps, mainly Firefox and only certain webpages. Sometimes numbers would render like below:<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2025-01-20-how-to-fix-firefox-rendering-emoji-font-black-bold-numbers-issue\/images\/bad.png\"\n        type=\"\"\n        alt=\"Bad Rendering\"\n        \n      \/><\/p>\n<h2 id=\"debugging-steps\">Debugging Steps<\/h2>\n<p>This occurred off and on over the course of a few weeks. My font setup was primarily done using\n<a href=\"https:\/\/github.com\/danth\/stylix\">stylix<\/a> and a bit of NixOS option config.<\/p>\n<p>I noticed this only seemed to happen when the CSS on the page include a font-family like so &ldquo;monospace&rdquo; i.e.\nthe monospace font in quotes. But without quotes, the font would render fine.<\/p>"},{"title":"TIL: How to Fix PipeWire\/WirePlumber Issues on NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2025-01-15-til-how-to-fix-pipewire-wireplumber-issues-on-nixos\/","pubDate":"Wed, 15 Jan 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-01-15-til-how-to-fix-pipewire-wireplumber-issues-on-nixos\/","description":"<p><strong>TIL: How to Fix PipeWire\/WirePlumber Issues on NixOS<\/strong><\/p>\n<p>For the last month or so, the audio on my Desktop was broken in the sense I had to run these three commands to make it work<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">pipewire <span class=\"p\">&amp;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">wireplumber <span class=\"p\">&amp;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">pipewire-pulse\n<\/span><\/span><\/code><\/pre><\/div><p>Now, normally I hibernate my computer, so I didn&rsquo;t really have to do this more than once or twice. However, it was very\nannoying either way to remember to know how to do it.<\/p>"},{"title":"My Year in Review 2024","link":"https:\/\/haseebmajid.dev\/posts\/2025-01-01-my-year-in-review-2024\/","pubDate":"Thu, 02 Jan 2025 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2025-01-01-my-year-in-review-2024\/","description":"<p>I did one of these last year, and thought why not do another quick year in review. Catch people up with what I&rsquo;ve been\nup to. This year was not nearly as transformative as my previous year in terms of changes I made to my workflow.<\/p>\n<p>I am still using Nix and NixOS, I am still using Neovim. I moved onto from tmux to zellij mainly because I just like\nthe floating terminal it provides. But other than that, it&rsquo;s basically the same as the end of last year.<\/p>"},{"title":"Part 7: Zellij as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2024-12-18-part-7-zellij-as-part-of-your-development-workflow\/","pubDate":"Wed, 18 Dec 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-12-18-part-7-zellij-as-part-of-your-development-workflow\/","description":"<p>After another 5 months I&rsquo;m finally back blogging about my development setup. Which since my last post, has been\na lot more stable. As much closer to a workflow I am mostly happy with. In this post, we will go over how I integrate\n<a href=\"https:\/\/github.com\/zellij-org\/zellij\">Zellij<\/a>.<\/p>\n<h2 id=\"what-is-a-terminal-multiplexer\">What is a terminal multiplexer?<\/h2>\n<p>Zellij is a terminal multiplexer think like tmux or screen. It another one of those projects written in rust.\nWhich seems pretty popular for creating similar tools to existing ones but usually faster.<\/p>"},{"title":"Speaking Tips I Have Learnt From Conferences","link":"https:\/\/haseebmajid.dev\/posts\/2024-12-15-speaking-tips-i-ve-learnt\/","pubDate":"Sun, 15 Dec 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-12-15-speaking-tips-i-ve-learnt\/","description":"<p>Since 2022 I have tried to speak at least one conference\/meetup a year. The main reason for this was it forces to\nreally learn the area I want to present about a lot deeper. If you can explain something new to someone clearly\nthen it really shows you understand it very well.<\/p>\n<p>Recently, I was lucky enough to speak at <a href=\"https:\/\/hachyderm.io\/@golab@mastodon.uno\/113475429722773280\">GoLabs 2024 in Florence<\/a>,\nwhich was a load of fun and a week later at the <a href=\"https:\/\/www.meetup.com\/londongophers\/events\/303598426\/\">London Gophers November Meet<\/a>.<\/p>"},{"title":"How to Wrap NixGL Around Package in Home Manager","link":"https:\/\/haseebmajid.dev\/posts\/2024-10-15-how-to-wrap-nixgl-around-package-in-home-manager\/","pubDate":"Tue, 15 Oct 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-10-15-how-to-wrap-nixgl-around-package-in-home-manager\/","description":"<p>I use Nix mainly with home manager on my Ubuntu laptop, and for the most part, it works fine. However, some apps installed\nusing Nix, need to use <a href=\"https:\/\/github.com\/nix-community\/nixGL\">nixGL<\/a>. A wrapper tool for OpenGL, allowing Nix installed\ntooling to use the system&rsquo;s OpenGL and Vulkan APIs. Some apps including kitty and Firefox (mainly for Google Meet).<\/p>\n<p>There is currently a <a href=\"https:\/\/github.com\/nix-community\/home-manager\/pull\/5355\">branch<\/a> in home-manager we can pull\ninto our config, which provides a convenient way to wrap these apps in nixGL rather than needing to specify say\n<code>nixGLIntel kitty<\/code> in our terminal or say Hyprland config (key bindings).<\/p>"},{"title":"How to Set up Cloudflare Tunnels With Traefik (In NixOS)","link":"https:\/\/haseebmajid.dev\/posts\/2024-09-30-how-to-setup-cloudflare-tunnels-to-point-to-service-behind-traefik\/","pubDate":"Mon, 30 Sep 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-09-30-how-to-setup-cloudflare-tunnels-to-point-to-service-behind-traefik\/","description":"<p>Recently, I was setting up Navidrome, kind of like a self-hosted Spotify, in my home lab and I wanted to set it up to use\nproxy auth in Authentik. But to do this I needed to use with a reverse proxy, i.e. Traefik. In this article\nI will show you how to you can point your Cloudflare tunnel to Traefik and have that forward the request to the service.<\/p>\n<h2 id=\"prerequisite\">Prerequisite<\/h2>\n<p>In this article, I assume you are already familiar with Cloudflare Tunnels and Traefik.<\/p>"},{"title":"TIL: How to Cancel Stale Pipelines in GitLab CI","link":"https:\/\/haseebmajid.dev\/posts\/2024-09-15-til-how-to-cancel-stale-pipelines-in-gitlab-ci\/","pubDate":"Sun, 15 Sep 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-09-15-til-how-to-cancel-stale-pipelines-in-gitlab-ci\/","description":"<p><strong>TIL: How to Cancel Stale Pipelines in GitLab CI<\/strong><\/p>\n<p>Today I learnt that we can cancel old pipelines in MRs. For example, you push a new commit, and you don&rsquo;t care about the\nold pipeline running any more. You want to cancel them to save CI minutes etc.<\/p>\n<p>Here is an example, you can see the 2nd pipeline is cancelled:<\/p>\n<p><\/p>\n<p>We need to add this to our <code>.gitlab-ci.yml<\/code> file. Where the <code>default.interruptible<\/code> marks every job as it can be\ncancelled <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>.<\/p>"},{"title":"TIL: How to Get Shell Completions in Nix Shell With Direnv","link":"https:\/\/haseebmajid.dev\/posts\/2024-09-12-til-how-to-get-shell-completions-in-nix-shell-with-direnv\/","pubDate":"Thu, 12 Sep 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-09-12-til-how-to-get-shell-completions-in-nix-shell-with-direnv\/","description":"<p><strong>TIL: How to Get Shell Completions in Nix Shell With Direnv<\/strong><\/p>\n<p>When shell completions don&rsquo;t work with direnv, you may need to use <code>nix develop<\/code> to load the shell manually.<\/p>\n<h2 id=\"background\">Background<\/h2>\n<p>I am using <code>nix-direnv<\/code>, with nix devshell to autoload into my development environments. I changed the directory\nand the devshell is automagically loaded without me doing anything, which is great. Provides me with a bunch of tools\nspecific for that project. With all the benefits of Nix, mainly reproducibility.<\/p>"},{"title":"How to Set up Authentik Forward Auth With Traefik on NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2024-09-06-how-to-setup-authentik-forward-auth-with-traefik-on-nixos\/","pubDate":"Fri, 06 Sep 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-09-06-how-to-setup-authentik-forward-auth-with-traefik-on-nixos\/","description":"<p>In this post, I will show you how you can set up forward auth for a single host in Authentik, with Traefik as our reverse\nproxy on NixOS. This is particularly useful way to protect apps that don&rsquo;t have any built in auth.<\/p>\n<p>Authentik is a great app which can handle authentication for almost all of our home lab. So we only need to log in\nwith Authentik, to log in to any of our apps. Rather than needing separate passwords and usernames for each app.<\/p>"},{"title":"Setup TLS Certificate With Traefik & Tailscale on NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2024-08-19-setup-tls-certificate-with-traefik-tailscale-on-nixos\/","pubDate":"Mon, 19 Aug 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-08-19-setup-tls-certificate-with-traefik-tailscale-on-nixos\/","description":"<p>Recently I have been playing around with running a homelab directly on a NixOS machine without kubernetes.\nI didn&rsquo;t want to bother to have to setup certificates using Traefik (DNS challenge) and Cloudflare. I wanted to use\nthe certificate that comes with Tailscale (wireguard VPN I use to connect to my home lab).<\/p>\n<p>In this post I will show you how I set this up as a Nix module.<\/p>\n<h2 id=\"nix\">Nix<\/h2>\n<p>Let us look at the relevant Nix code.<\/p>"},{"title":"How to Configure Kitty on Nix to Show Emojis","link":"https:\/\/haseebmajid.dev\/posts\/2024-08-06-how-to-configure-kitty-on-nix-to-show-emojis\/","pubDate":"Tue, 06 Aug 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-08-06-how-to-configure-kitty-on-nix-to-show-emojis\/","description":"<p>Recently, I was trying to configure the terminal emulator Kitty with Nix and Stylix, and I was having issues with it\nshowing emojis. It took me a lot longer to figure out than I would like to admit. So I decided to write a blog post,\nshowing you how I did it and perhaps saving you some time.<\/p>\n<p>I did this in my <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/blob\/79d1ddee586a98816af3f5605de3059d675d58fe\/modules\/home\/cli\/terminals\/kitty\/default.nix\">home-manger config<\/a>.\nFirst we install the <code>Symbols Nerd Font<\/code>, there are two ways we can normally add nerd fonts. Either patch our font,\nwhich I had already done with my font Mono Lisa or use this font (symbols), alongside your font (as a fallback).\nI haven&rsquo;t fully managed to get that to work on my system, so I have both normal Mono Lisa and Nerd Font variants on my\nsystem at the moment. Else other apps besides Kitty break. Anyway, tangent aside, you can install like this:<\/p>"},{"title":"How I Set up BTRFS and LUKS on NixOS Using Disko","link":"https:\/\/haseebmajid.dev\/posts\/2024-07-30-how-i-setup-btrfs-and-luks-on-nixos-using-disko\/","pubDate":"Tue, 30 Jul 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-07-30-how-i-setup-btrfs-and-luks-on-nixos-using-disko\/","description":"<p>In this post, I will show you how you can declaratively partition our drives using Nix(OS).<\/p>\n<details\n  class=\"notice info\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">TL;DR;<\/summary>\n  \n  We can use a tool called disko to partition our drives declaratively and combine it with NixOS anywhere for a remote\ninstall. Showing an example setting up LUKS encryption with BTRFS file system.\n<\/details>\n\n<h2 id=\"background\">Background<\/h2>\n<p>If you&rsquo;re like me, then when you started playing with NixOS, You found yourself constantly reinstalling it and\nstarting again. Either setting up new machines. Playing around with it in a VM or even realising how to set up LUKS and\nhibernate properly. Or even when setting up impermanence.<\/p>"},{"title":"How I Configured Zellij Status Bar","link":"https:\/\/haseebmajid.dev\/posts\/2024-07-26-how-i-configured-zellij-status-bar\/","pubDate":"Fri, 26 Jul 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-07-26-how-i-configured-zellij-status-bar\/","description":"<p>As some of you may know, I moved to Zellij a few months ago from tmux. In this post, I will show you have I configured\nthe zellij status bar in nix. So it acts more like how my config did in tmux.<\/p>\n<p>My current Zellij status bar.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2024-07-26-how-i-configured-zellij-status-bar\/images\/status.png\"\n        type=\"\"\n        alt=\"My current status bar\"\n        \n      \/><\/p>\n<h2 id=\"optional-background\">(Optional) Background<\/h2>\n<p>A bit of background, which you can skip if you&rsquo;d like.<\/p>\n<h3 id=\"what-is-zellij\">What is zellij?<\/h3>\n<p>Some of you may be wondering what is zellij\/tmux. They are what we call multiplexers. Essentially, our terminals\nnow can have a client server architecture. So we can kill our terminal but, our session will still be alive.\nWhich makes it great for jumping between projects if you are using say Neovim. When I first moved to tmux, I found\nit is great because now I don&rsquo;t need 4\/5 VS Code instances open. Instead, I could use a script to jump between my projects,\nand tmux would keep the session alive, so just how I left the project. Zellij does basically the same thing for me.<\/p>"},{"title":"Part 6: Fish Shell as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2024-07-01-part-6-fish-shell-as-part-of-your-development-workflow\/","pubDate":"Mon, 01 Jul 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-07-01-part-6-fish-shell-as-part-of-your-development-workflow\/","description":"<p>After a long break, I am again writing about my workflow. The big issue I have with this series is that my workflow is\nkind of always in flux and changing. Which maybe is a bad thing. I just need to pick some tools and stick to it.\nRather than trying four different terminal emulators, i.e. alacritty, kitty, foot and wezterm.<\/p>\n<p>However, over the last ~5ish years, one thing that has remained pretty constant is my use of <a href=\"https:\/\/github.com\/fish-shell\/fish-shell\">fish<\/a> shell.\nIn this post, I will go over why I stick with fish, and how I have set it up for my own use case.<\/p>"},{"title":"Rewriting a Python script as a Bash one-liner","link":"https:\/\/haseebmajid.dev\/posts\/2024-06-30-rewriting-a-python-script-as-a-bash-one-liner\/","pubDate":"Sun, 30 Jun 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-06-30-rewriting-a-python-script-as-a-bash-one-liner\/","description":"<p>In this post, I will describe how I went about replacing a Python with a bash liner and how it decreased the runtime from 30 seconds to 1 second<\/p>\n<h2 id=\"background\">Background<\/h2>\n<p>For this blog, I used to have a Python script which I would use to generate open graph images. These are images you sometimes see in apps when you share a link. For example:<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2024-06-30-rewriting-a-python-script-as-a-bash-one-liner\/images\/og.png\"\n        type=\"\"\n        alt=\"open graph image\"\n        \n      \/><\/p>\n<p>Essentially, what it would do is go through every post in my blog repository.\nThen run a go program to generate the open graph images based on the markdown\nfront matter.<\/p>"},{"title":"Migrating My Homelab to Flux","link":"https:\/\/haseebmajid.dev\/posts\/2024-06-17-migrating-my-homelab-to-flux\/","pubDate":"Mon, 17 Jun 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-06-17-migrating-my-homelab-to-flux\/","description":"<h2 id=\"background\">Background<\/h2>\n<p>This series is a continuation of the other <a href=\"https:\/\/haseebmajid.dev\/series\/setup-raspberry-pi-cluster-with-k3s-and-nixos\/\">series<\/a>. I have\nsince updated my <a href=\"https:\/\/docs.homelab.haseebmajid.dev\/\">home lab<\/a>, removing the RPIs and replacing them with some\nmini pcs.<\/p>\n<p>As part of this change I am now using <a href=\"https:\/\/github.com\/serokell\/deploy-rs\">deploy-rs<\/a> instead of colmena. As its\neasier to integrate into my own flake, and it won&rsquo;t roll out the change if breaks the networking, i.e. you cannot ssh\nto the machine.<\/p>\n<h2 id=\"why-move-away-from-pulumi\">Why move away from Pulumi?<\/h2>\n<p>As per the title of this post of the most significant changes I have made it moving my Kubernetes config from Pulumi to fluxcd.\nPulumi I suspect is great for deploying infrastructure but became painful for managing the YAML config for the k3s\ncluster.<\/p>"},{"title":"TIL: How to Fix Did No Resolve Alias Errors in Podman","link":"https:\/\/haseebmajid.dev\/posts\/2024-06-15-til-how-to-fix-did-no-resolve-alias-errors-in-podman\/","pubDate":"Sat, 15 Jun 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-06-15-til-how-to-fix-did-no-resolve-alias-errors-in-podman\/","description":"<p><strong>TIL: How to Fix Did No Resolve Alias Errors in Podman<\/strong><\/p>\n<p>Recently, I was trying to pull docker images using <code>podman<\/code>, on an Ubuntu laptop and was getting an error which\nlooked something like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">Error: error creating build container: short-name <span class=\"s2\">&#34;node:18.17&#34;<\/span> did not resolve to an <span class=\"nb\">alias<\/span> and no unqualified-search registries are defined in <span class=\"s2\">&#34;\/etc\/containers\/registries.conf&#34;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>This is because Podman doesn&rsquo;t allow us to use short names, by default we need to specify the registry i.e. <code>docker.io\/node:18.17<\/code>.\nBut for existing <code>docker-compose.yml<\/code> files, this would be a pain to edit. Especially because most people use Docker\nnot Podman. So, in the end, you can edit a config file in home directory to enable the old way of pulling images.<\/p>"},{"title":"TIL: How to Fix DNS Resolution Issues in K3s Related to Flannel Networking","link":"https:\/\/haseebmajid.dev\/posts\/2024-06-02-til-how-to-fix-dns-resolution-issues-in-k3s-related-to-flannel-networking\/","pubDate":"Sun, 02 Jun 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-06-02-til-how-to-fix-dns-resolution-issues-in-k3s-related-to-flannel-networking\/","description":"<p><strong>TIL: How to Fix DNS Resolution Issues in K3s Related to Flannel Networking<\/strong><\/p>\n<p>Recently, I was trying to set up the kubernetes-dashboard, to make it easier to monitor my k8s cluster. I however noticed\nI was getting the following error:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">\u2026 \ue0a0&gt; add-kubernetes-dashboard via \ud83d\udc39 v1.22.2 via \uf1b2  via \u2744  impure <span class=\"o\">(<\/span>nix-shell-env<span class=\"o\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"> k$ kubectl logs -n monitoring kubernetes-dashboard-kong-75bb76dd5f-b27ll\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024\/05\/05 20:55:21 <span class=\"o\">[<\/span>error<span class=\"o\">]<\/span> 1319#0: *274054 <span class=\"o\">[<\/span>lua<span class=\"o\">]<\/span> init.lua:371: execute<span class=\"o\">()<\/span>: DNS resolution failed: failed to receive reply from UDP server 10.43.0.10:53: timeout. Tried: nil, client: 127.0.0.1, server: kong, request: <span class=\"s2\">&#34;GET \/ HTTP\/2.0&#34;<\/span>, host: <span class=\"s2\">&#34;localhost:8443&#34;<\/span>, request_id: <span class=\"s2\">&#34;af30b3162db70e2de8f1073a40f7d865&#34;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Weird the DNS resolution seems to be failing, so I decided to follow the\n<a href=\"https:\/\/kubernetes.io\/docs\/tasks\/administer-cluster\/dns-debugging-resolution\/\">Kubernetes guide<\/a> to try to debug issues.<\/p>"},{"title":"How I Fixed Hibernate on My NixOS Machine","link":"https:\/\/haseebmajid.dev\/posts\/2024-05-27-how-i-fixed-hibernation-on-my-nixos-machine\/","pubDate":"Mon, 27 May 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-05-27-how-i-fixed-hibernation-on-my-nixos-machine\/","description":"<details\n  class=\"notice info\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">tl:dr;<\/summary>\n  \n  <p>Wi-Fi drivers were stopping the PC from suspending. I am using an Ethernet cable to connect my PC. So didn&rsquo;t need the\nWi-Fi drivers. By adding them to a blocklist. I think you only need the 2nd one in the list.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-nix\" data-lang=\"nix\"><span class=\"line\"><span class=\"cl\"><span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">boot<\/span><span class=\"o\">.<\/span><span class=\"n\">blacklistedKernelModules<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"s2\">&#34;ath12k_pci&#34;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"s2\">&#34;ath12k&#34;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">];<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">}<\/span>\n<\/span><\/span><\/code><\/pre><\/div>\n<\/details>\n\n<p>Recently, I upgraded my PC to an am5 machine with an X670E Gigabyte motherboard. However, when I did this hibernate\nwas left broken, alongside suspend. This gave me an idea, it wasn&rsquo;t to do with my hibernate setup being broken by something\nelse going on.<\/p>"},{"title":"How to Add reveal-hugo to a Hugo Site","link":"https:\/\/haseebmajid.dev\/posts\/2024-05-26-how-to-add-hugo-revealjs-to-a-hugo-site\/","pubDate":"Sun, 26 May 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-05-26-how-to-add-hugo-revealjs-to-a-hugo-site\/","description":"<p>What we are trying to achieve hosting RevealJS slides on our Hugo blog like\n<a href=\"https:\/\/haseebmajid.dev\/slides\/reproducible-envs-with-nix\/#\/\">so<\/a>. The markdown that the slides are built from\nIt can be found <a href=\"https:\/\/gitlab.com\/hmajid2301\/blog\/-\/blob\/main\/content\/slides\/reproducible-envs-with-nix\/_index.md\">here<\/a><\/p>\n<h2 id=\"background\">Background<\/h2>\n<p>Recently, I did a talk at the Conf42 conference <a href=\"https:\/\/haseebmajid.dev\/content\/talks\/reproducible-envs-with-nix\">shameless plug here<\/a>. At\nthe time I was working on the slides using <a href=\"https:\/\/revealjs.com\/\">Reveal.js<\/a>, as I did for all of my slides\nas I can create a slideshow using just plain markdown. I hosted all of my talks in a separate\n<a href=\"https:\/\/gitlab.com\/hmajid2301\/talks\">repository<\/a>. Which published to a simple <a href=\"https:\/\/talks.haseebmajid.dev\/\">site<\/a>.<\/p>"},{"title":"How to Deploy Kubernetes Dashboard Using Pulumi to a K3s Cluster","link":"https:\/\/haseebmajid.dev\/posts\/2024-05-24-how-to-deploy-kubernetes-dashboard-using-pulumi-to-a-k3s-cluster\/","pubDate":"Fri, 24 May 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-05-24-how-to-deploy-kubernetes-dashboard-using-pulumi-to-a-k3s-cluster\/","description":"<details\n  class=\"notice warn\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Kubernetes Knowledge<\/summary>\n  \n  I don&rsquo;t know a ton about Kubernetes. I am still learning, hence this home-lab project. So there may be better ways\nto do stuff that I have described below. If that is the case, please let me know! Just take what I say with a pinch of\nsalt.\n<\/details>\n\n<p>It&rsquo;s been a while since I made an update about my home lab, also an aside, I should&rsquo;ve given this series a better name.\nSo recently, I finally went back to my PI cluster and started to actually setup properly. The first thing I decided\nto put on it was the Kubernetes dashboard. I could get a nice GUI look into what is happening with my cluster at a\nglance. It also looked simple to deploy.<\/p>"},{"title":"How to Use Env Variables With Viper Config Library in Go","link":"https:\/\/haseebmajid.dev\/posts\/2024-05-19-how-to-use-env-variables-with-viper-config-library-in-go\/","pubDate":"Sun, 19 May 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-05-19-how-to-use-env-variables-with-viper-config-library-in-go\/","description":"<p>This is part of a series of where I am going to blog about issues I had building my CLI tool OptiNix and documenting\nhow I resolved those issues. Most will be random things not specifically related to building CLI tools.<\/p>\n<p>In this example, we will use the <a href=\"https:\/\/github.com\/spf13\/viper\">viper<\/a> library. Mainly because I am already using cobra, the library to help us make CLI tools.\nFrom the same author and wanted to see how well they integrated. The Viper config library is probably over kill\nin my case.<\/p>"},{"title":"TIL: How to Pull Submodules in a Nix Derivation","link":"https:\/\/haseebmajid.dev\/posts\/2024-05-12-til-how-to-pull-submodules-in-a-nix-derivation\/","pubDate":"Sun, 12 May 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-05-12-til-how-to-pull-submodules-in-a-nix-derivation\/","description":"<p><strong>TIL: How to Pull Submodules in a Nix Derivation<\/strong><\/p>\n<p>Recently, I was trying to create a derivation which needed to pull git submodules as well. I was getting an error which\nlook something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">data\/meson.build:76:0: ERROR: Nonexistent build file <span class=\"s1\">&#39;data\/submodules\/meson.build&#39;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>It was coming from this derivation <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/blob\/c153de146a3bf9339cbef013ac65bc32e6305c8e\/packages\/gradience\/default.nix\">https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/blob\/c153de146a3bf9339cbef013ac65bc32e6305c8e\/packages\/gradience\/default.nix<\/a> for building the latest version of gradience.<\/p>\n<p>It turns out when we do a <code>fetchFromGitHub<\/code> we need to explicitly tell it to also pull submodules, which makes sense.\nSo I was able to fix this. I had to add the <code>fetchSubmodules<\/code> argument:<\/p>"},{"title":"Part 5B: Installing Our Nix Configuration (NixOS Anywhere) as Part of Your Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2024-05-02-part-5b-installing-our-nix-configuration-as-part-of-your-workflow\/","pubDate":"Thu, 02 May 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-05-02-part-5b-installing-our-nix-configuration-as-part-of-your-workflow\/","description":"<p>I wanted to do a short article showing you how you can use your Nix config to install NixOS on a new device. Have your\ndevice setup with NixOS in a few commands with all the packages and tooling you want.<\/p>\n<p>Previously I was creating my own ISO and then burning that to a USB and using that USB as live media to install my config.\nI had a <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/blob\/3371d7774c133a36d4986a9dcaeb972d4e4638a2\/hosts\/iso\/configuration.nix#L73\"> custom script <\/a>\n<code>nix_installer<\/code>, which would run automatically when you loaded into the gnome shell.<\/p>"},{"title":"Part 5: Nix as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2024-04-28-part-5-nix-as-part-of-your-development-workflow\/","pubDate":"Sun, 28 Apr 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-04-28-part-5-nix-as-part-of-your-development-workflow\/","description":"<p>My original plan for this article was to discuss my shell and how I configure it. But I have made some significant changes,\nto how I structure my Nix configuration and I wanted to go over Why I did that.<\/p>\n<p>I mean, likely this will probably happen a lot, as my configuration changes more often than it should \ud83d\ude48.\nAnyway, into the main topic.<\/p>\n<p>My <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/tree\/590f2329d41ac2710d149bbe14425c79e49c2784\">dotfiles<\/a><\/p>\n<h2 id=\"snowfall-what\">Snowfall what?<\/h2>\n<p>I <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/tags\/snowfall\">recently<\/a> ported my Nix configuration (dotfiles), to use the\n<a href=\"https:\/\/snowfall.org\/guides\/lib\/quickstart\/\">snowfall-lib<\/a> to structure my Nix config.<\/p>"},{"title":"Part 4b Foot Terminal as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2024-04-25-part-4b-foot-terminal-as-part-of-your-development-workflow\/","pubDate":"Thu, 25 Apr 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-04-25-part-4b-foot-terminal-as-part-of-your-development-workflow\/","description":"<p>Earlier this year I spoke about using Wezterm as my terminal of choice, however since then, I have swapped back to the\nfoot terminal emulator. I also have kitty available on my system. However, I don&rsquo;t use it much.<\/p>\n<p>In this article, I want to add a quick addendum to why I moved away from Wezterm. Note as per that post, this is again\nnot a super important decision, almost any full colour supported terminal will basically like every other. So if one\nwork for you, feel free to stick to it.<\/p>"},{"title":"TIL: How to Fix Neorg Metadata Treesitter Issues With Nixvim","link":"https:\/\/haseebmajid.dev\/posts\/2024-04-21-til-how-to-fix-neorg-metadata-treesitter-issues-with-nixvim\/","pubDate":"Sun, 21 Apr 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-04-21-til-how-to-fix-neorg-metadata-treesitter-issues-with-nixvim\/","description":"<p><strong>TIL: How to Fix Neorg Metadata Tree Sitter Issues With NixVim<\/strong><\/p>\n<p>If you are like me, you may be configuring your Neovim configuration using NixVim. Which is a &ldquo;framework&rdquo; making it\neasier to configure Neovim using mostly Nix configuration. Allowing us to keep most of our config in one language,\nat least in my case.<\/p>\n<p>I started using Neorg to manage my notes and to-do lists in my &ldquo;second-brain&rdquo;, but noticed that the metadata part\nwas not being highlighted as I expected.<\/p>"},{"title":"My Favourite Neovim Plugins","link":"https:\/\/haseebmajid.dev\/posts\/2024-04-06-my-favourite-neovim-plugins\/","pubDate":"Sat, 06 Apr 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-04-06-my-favourite-neovim-plugins\/","description":"<p>In this post, I will go over some of my Neovim plugins I really like that aren&rsquo;t as well known. So I won&rsquo;t really be\ntalking about telescope, LSP or nvim-cmp. As most users know about these plugins and use them extensively in their\nconfiguration.<\/p>\n<h2 id=\"oilnvim\">oil.nvim<\/h2>\n<ul>\n<li>Link: <a href=\"https:\/\/github.com\/stevearc\/oil.nvim\">https:\/\/github.com\/stevearc\/oil.nvim<\/a><\/li>\n<\/ul>\n<p>oil.nvim creates a file explorer but as a true vim buffer, so it&rsquo;s effortless to create new files and folders. We\ncan also move files easily. Again, using all of our normal key bindings we use in Nix.<\/p>"},{"title":"TIL: How to Set up Layouts in Zellij That Use Direnv and Nix","link":"https:\/\/haseebmajid.dev\/posts\/2024-03-18-til-how-to-setup-layouts-in-zellij-that-use-direnv-and-nix\/","pubDate":"Mon, 18 Mar 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-03-18-til-how-to-setup-layouts-in-zellij-that-use-direnv-and-nix\/","description":"<p><strong>TIL: How to Set up Layouts in Zellij That Use Direnv and Nix<\/strong><\/p>\n<p>I have been using <a href=\"https:\/\/github.com\/zellij-org\/zellij\">Zellij<\/a> for a while now. I tried to set up layouts for\none of my personal projects. So that we could have tests and linting running and any other tasks we may want\nwhilst doing development <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>.<\/p>\n<p>However, I had an issue working out how to call commands that required direnv and nix to set up development environments.\nIn my case, my nix dev shell installed the go-task tool to run tasks such as <code>task lint<\/code> or <code>task tests<\/code>. However\nthe shell that zellij was running the commands in for the layout did not load my Nix dev shell, so the go-task binary\nwas not available.<\/p>"},{"title":"TIL: How to Get Sway Notification Center to Play Nice With Waybar","link":"https:\/\/haseebmajid.dev\/posts\/2024-03-15-til-how-to-get-swaync-to-play-nice-with-waybar\/","pubDate":"Fri, 15 Mar 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-03-15-til-how-to-get-swaync-to-play-nice-with-waybar\/","description":"<p><strong>TIL: How to Get swaync to Play Nice With Waybar<\/strong><\/p>\n<p>I added Sway Notification Center as my notification manager and added a small &ldquo;widget&rdquo; to my Waybar, so I can see how many notifications\nI have and silence notifications by clicking on it. However, I found when I opened the swaync sidebar, in my case by\nright-clicking on the icon. I found that I could not click on anything else on my Waybar like workspaces. Now I know\nI should be using my keyboard, but sometimes it&rsquo;s just easier to use a mouse.<\/p>"},{"title":"TIL: Clean Up Tmux Service When Removed by Home Manager","link":"https:\/\/haseebmajid.dev\/posts\/2024-03-10-til-clean-up-tmux-service-when-removed-by-home-manager\/","pubDate":"Sun, 10 Mar 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-03-10-til-clean-up-tmux-service-when-removed-by-home-manager\/","description":"<p><strong>TIL: Clean Up Tmux Service When Removed by Home Manager<\/strong><\/p>\n<p>Recently I stopped using tmux to try zellij, however I noticed when I removed tmux from my nix config. I was getting\nthe following error, when rebuilding my home-manager config:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">The user systemd session is degraded:\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  UNIT         LOAD   ACTIVE SUB    DESCRIPTION\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u25cf tmux.service loaded failed failed tmux default session <span class=\"o\">(<\/span>detached<span class=\"o\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">Legend: LOAD   \u2192 Reflects whether the unit definition was properly loaded.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        ACTIVE \u2192 The high-level unit activation state, i.e. generalization of SUB.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        SUB    \u2192 The low-level unit activation state, values depend on unit type.\n<\/span><\/span><\/code><\/pre><\/div><p>I was wondering where this error was coming from, turns it the symlink to tmux.service has not been deleted that\nnix would create.<\/p>"},{"title":"TIL: How to Run Android Emulator Using avd on Hyprland","link":"https:\/\/haseebmajid.dev\/posts\/2024-03-02-til-how-to-run-android-emulator-using-avd-on-hyprland\/","pubDate":"Sat, 02 Mar 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-03-02-til-how-to-run-android-emulator-using-avd-on-hyprland\/","description":"<p><strong>TIL: How to Run Android Emulator Using avd on Hyprland<\/strong><\/p>\n<p>Recently, I was having issues when trying to run an Android Emulator using Android Studio (avd). When I would try to\nrun an Emulator from the device manager, I would get the following <code>The emulator process for avd xxx has terminated error<\/code>.<\/p>\n<p>Looking deeper into the logs at <code>~\/.local\/cache\/Google\/AndroidStudio2023.1\/log\/idea.log<\/code>, I noticed the following:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:45,859 <span class=\"o\">[<\/span> 781674<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Android emulator version 33.1.24.0 <span class=\"o\">(<\/span>build_id 11237101<span class=\"o\">)<\/span> <span class=\"o\">(<\/span>CL:N\/A<span class=\"o\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:45,859 <span class=\"o\">[<\/span> 781674<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Found systemPath \/home\/haseebmajid\/Android\/Sdk\/system-images\/android-34\/google_apis_playstore\/x86_64\/\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,037 <span class=\"o\">[<\/span> 781852<span class=\"o\">]<\/span>   WARN - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Failed to process .ini file \/home\/haseebmajid\/.config\/.android\/avd\/..\/avd\/Pixel_7_Pro_API_34.avd\/quickbootChoice.ini <span class=\"k\">for<\/span> reading.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,053 <span class=\"o\">[<\/span> 781868<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Storing crashdata in: , detection is enabled <span class=\"k\">for<\/span> process: <span class=\"m\">194632<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,054 <span class=\"o\">[<\/span> 781869<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Fatal: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,054 <span class=\"o\">[<\/span> 781869<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Duplicate loglines will be removed, <span class=\"k\">if<\/span> you wish to see each individual line launch with the -log-nofilter flag.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,054 <span class=\"o\">[<\/span> 781869<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - \n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,054 <span class=\"o\">[<\/span> 781869<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Increasing RAM size to 3072MB\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,054 <span class=\"o\">[<\/span> 781869<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Available platform plugins are: xcb.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,054 <span class=\"o\">[<\/span> 781869<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Warning: Could not find the Qt platform plugin <span class=\"s2\">&#34;wayland&#34;<\/span> in <span class=\"s2\">&#34;\/home\/haseebmajid\/Android\/Sdk\/emulator\/lib64\/qt\/plugins&#34;<\/span> <span class=\"o\">((<\/span>null<span class=\"o\">)<\/span>:0, <span class=\"o\">(<\/span>null<span class=\"o\">))<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,054 <span class=\"o\">[<\/span> 781869<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - <span class=\"o\">((<\/span>null<span class=\"o\">)<\/span>:0, <span class=\"o\">(<\/span>null<span class=\"o\">))<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">2024-02-20 12:01:46,055 <span class=\"o\">[<\/span> 781870<span class=\"o\">]<\/span>   INFO - Emulator: Pixel <span class=\"m\">7<\/span> Pro API <span class=\"m\">34<\/span> - Fatal: This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.\n<\/span><\/span><\/code><\/pre><\/div><p>Note, I did have qtwayland5 installed on my Ubuntu machine.\nSo get it working based on this log line <code>Available platform plugins are: xcb.<\/code> The simplest thing I could think of was\nto run<\/p>"},{"title":"How to Load Secret Environment Variables in Fish Shell","link":"https:\/\/haseebmajid.dev\/posts\/2024-02-28-how-to-load-secret-environment-variables-in-fish-shell\/","pubDate":"Wed, 28 Feb 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-02-28-how-to-load-secret-environment-variables-in-fish-shell\/","description":"<p>Often you want to load environment variables that are secrets, and you don&rsquo;t want them in your shell history.\nSuch as your GitHub Access Token or API Token when making requests with curl.<\/p>\n<p>One easy solution is to load environment variables from a file, say an <code>.env<\/code> file. Now, since I am using fish shell,\nloading env variables from a file like we do in bash and zsh won\u2019t work, i.e.<\/p>"},{"title":"TIL: How to Add New Vim Plugins to nixpkgs Repository","link":"https:\/\/haseebmajid.dev\/posts\/2024-02-20-til-how-to-add-new-vim-plugins-to-nixpkgs-repository\/","pubDate":"Tue, 20 Feb 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-02-20-til-how-to-add-new-vim-plugins-to-nixpkgs-repository\/","description":"<p>Recently, I wanted to add a Neovim plugin to nixpkgs, so I can then add it to NixVim. I tried following the guide\nfrom the <a href=\"https:\/\/github.com\/NixOS\/nixpkgs\/blob\/master\/doc\/languages-frameworks\/vim.section.md#adding-new-plugins-to-nixpkgs-adding-new-plugins-to-nixpkgs\">docs<\/a>.<\/p>\n<p>However, I kept getting the following errors:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">nix-shell -p vimPluginsUpdater --run vim-plugins-updater\n<\/span><\/span><span class=\"line\"><span class=\"cl\">error:\n<\/span><\/span><span class=\"line\"><span class=\"cl\">       \u2026 <span class=\"k\">while<\/span> calling the <span class=\"s1\">&#39;derivationStrict&#39;<\/span> <span class=\"nb\">builtin<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">         at \/builtin\/derivation.nix:9:12: <span class=\"o\">(<\/span><span class=\"nb\">source<\/span> not available<span class=\"o\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">       \u2026 <span class=\"k\">while<\/span> evaluating derivation <span class=\"s1\">&#39;shell&#39;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">         whose name attribute is located at \/nix\/store\/whhzjfgalghpm34irclh01c0afynmyll-nixpkgs\/nixpkgs\/pkgs\/stdenv\/generic\/make-derivation.nix:300:7\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">       \u2026 <span class=\"k\">while<\/span> evaluating attribute <span class=\"s1\">&#39;buildInputs&#39;<\/span> of derivation <span class=\"s1\">&#39;shell&#39;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">         at \/nix\/store\/whhzjfgalghpm34irclh01c0afynmyll-nixpkgs\/nixpkgs\/pkgs\/stdenv\/generic\/make-derivation.nix:347:7:\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">          346<span class=\"p\">|<\/span>       <span class=\"nv\">depsHostHost<\/span>                <span class=\"o\">=<\/span> lib.elemAt <span class=\"o\">(<\/span>lib.elemAt dependencies 1<span class=\"o\">)<\/span> 0<span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">          347<span class=\"p\">|<\/span>       <span class=\"nv\">buildInputs<\/span>                 <span class=\"o\">=<\/span> lib.elemAt <span class=\"o\">(<\/span>lib.elemAt dependencies 1<span class=\"o\">)<\/span> 1<span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">             <span class=\"p\">|<\/span>       ^\n<\/span><\/span><span class=\"line\"><span class=\"cl\">          348<span class=\"p\">|<\/span>       <span class=\"nv\">depsTargetTarget<\/span>            <span class=\"o\">=<\/span> lib.elemAt <span class=\"o\">(<\/span>lib.elemAt dependencies 2<span class=\"o\">)<\/span> 0<span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">       error: undefined variable <span class=\"s1\">&#39;vimPluginsUpdater&#39;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">       at \u00abstring\u00bb:1:107:\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\">            1<span class=\"p\">|<\/span> <span class=\"o\">{<\/span>...<span class=\"o\">}<\/span>@args: with import &lt;nixpkgs&gt; args<span class=\"p\">;<\/span> <span class=\"o\">(<\/span>pkgs.runCommandCC or pkgs.runCommand<span class=\"o\">)<\/span> <span class=\"s2\">&#34;shell&#34;<\/span> <span class=\"o\">{<\/span> <span class=\"nv\">buildInputs<\/span> <span class=\"o\">=<\/span> <span class=\"o\">[<\/span> <span class=\"o\">(<\/span>vimPluginsUpdater<span class=\"o\">)<\/span> <span class=\"o\">]<\/span><span class=\"p\">;<\/span> <span class=\"o\">}<\/span> <span class=\"s2\">&#34;&#34;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Or I was getting 429 network errors, too many requests to GitHub.<\/p>"},{"title":"TIL: How to Fix Firefox Rendering Bug in Hyprland","link":"https:\/\/haseebmajid.dev\/posts\/2024-02-15-til-how-to-fix-firefox-rendering-bug-in-hyprland\/","pubDate":"Thu, 15 Feb 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-02-15-til-how-to-fix-firefox-rendering-bug-in-hyprland\/","description":"<p><strong>TIL: How to Fix Firefox Rendering Bug in Hyprland<\/strong><\/p>\n<p>Recently, I had an issue with my Ubuntu laptop running Hyprland, when running Firefox it had this ugly border around\nit. Which looked something like this:<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2024-02-15-til-how-to-fix-firefox-rendering-bug-in-hyprland\/images\/firefox.png\"\n        type=\"\"\n        alt=\"Firefox\"\n        \n      \/><\/p>\n<p>You can see a weird border around the browser, and if you try to view some of the context menus, they appear small and difficult to read.<\/p>\n<h2 id=\"fix\">Fix<\/h2>\n<p>As per this <a href=\"https:\/\/old.reddit.com\/r\/hyprland\/comments\/18o8m8q\/firefox_croppingbad_rendering\/\">Reddit thread<\/a> <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>.\nThere are two fixes, one upgrade to version 0.33 which I could not easily do with Ubuntu. So I used the other fix,<\/p>"},{"title":"How to Move Files Between Two Git Repositories and Keep its History","link":"https:\/\/haseebmajid.dev\/posts\/2024-02-11-til-how-to-move-a-file-between-repos-and-keep-its-git-history\/","pubDate":"Sun, 11 Feb 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-02-11-til-how-to-move-a-file-between-repos-and-keep-its-git-history\/","description":"<h2 id=\"background\">Background<\/h2>\n<p>Recently, I had to move one of my to-do files from its own repository, <code>todo<\/code>, to my <code>second-brain<\/code> repository.\nSo I could better keep track of my ideas, and tasks to be done. However, I realised just copying the file over I\nwould lose all the git history the file had.<\/p>\n<p>Strictly speaking, I don&rsquo;t need the git history of that file, as the most important thing is the current tasks to be\ncompleted. I could, also, go look in the older repository if I really needed to see the file history. However, I decided it would be a nice exercise to learn how to copy files over and keep their history.<\/p>"},{"title":"How To Create A Custom NixOS ISO","link":"https:\/\/haseebmajid.dev\/posts\/2024-02-04-how-to-create-a-custom-nixos-iso\/","pubDate":"Sun, 04 Feb 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-02-04-how-to-create-a-custom-nixos-iso\/","description":"<h2 id=\"introduction\">Introduction<\/h2>\n<p>In this post, I will show you how you can create a custom NixOS ISO image, using our normal nix configuration as if it\nanother machine\/device. Some of you may be wondering why you want to do that vs using the normal ISO. Particular for\ninstalling on my machines I would like to have my device setup in one go, rather than previously I would install using the\nnormal ISO, then clone my dot files and build my config again.<\/p>"},{"title":"How to Get sops-nix Working with home-manager Modules","link":"https:\/\/haseebmajid.dev\/posts\/2024-01-28-how-to-get-sops-nix-working-with-home-manager-modules\/","pubDate":"Sun, 28 Jan 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-01-28-how-to-get-sops-nix-working-with-home-manager-modules\/","description":"<h2 id=\"introduction\">Introduction<\/h2>\n<p>In this article, I will go over how to get <a href=\"https:\/\/github.com\/Mic92\/sops-nix\">sops-nix<\/a> to work properly with\nhome-manager. One issue I noticed was that when I used with home-manager modules\/options, I would see a string\nlike &ldquo;%r\/secrets\/haseeb\/&hellip;&rdquo;. The <code>%r<\/code> would not be replaced.<\/p>\n<p>Relevant Issue: <a href=\"https:\/\/github.com\/Mic92\/sops-nix\/issues\/28\">https:\/\/github.com\/Mic92\/sops-nix\/issues\/28<\/a><\/p>\n<h2 id=\"assumption\">Assumption<\/h2>\n<p>I will assume you have already setup sops-nix and are using it. In the sense, you have a <code>.sops.yaml<\/code> file and are already\nusing it with NixOS. The instructions in the README is mostly pretty clear how to get setup, but I may in future\ncreate another article how I set up sops-nix. But in this post, we will simply go over how we can make it work with\nhome-manager. I will also assume you are using nix flakes and have passed sops-nix as an input.<\/p>"},{"title":"TIL: How to fix being unable to change locations in Mullvad VPN on NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2024-01-14-til-how-to-fix-unable-to-change-locations-in-mullvad-on-nixos\/","pubDate":"Sun, 14 Jan 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-01-14-til-how-to-fix-unable-to-change-locations-in-mullvad-on-nixos\/","description":"<p>Recently, I was unable to change the location on my Mullvad VPN from other thing other than sweden. Even using the\nmullvad cli tool I would keep getting errors like:<\/p>\n<pre tabindex=\"0\"><code>invalid argument for type conversion: missing custom lists settings\n<\/code><\/pre><p>it turned out to somehow a mismatch in versions where everything was running 2023.6 but my mullvad cli was using\n2023.5. So I ended up fixing this by changing my config to:<\/p>"},{"title":"TIL: How to Fix `Verification Failed` With Ventoy USB","link":"https:\/\/haseebmajid.dev\/posts\/2024-01-09-til-how-to-fix-verification-failed-with-ventoy-usb\/","pubDate":"Tue, 09 Jan 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-01-09-til-how-to-fix-verification-failed-with-ventoy-usb\/","description":"<p><strong>TIL: How to Fix <code>Verification Failed<\/code> With Ventoy USB<\/strong><\/p>\n<p>Recently, I tried to boot with my Ventoy USB on my new AMD motherboard Framework. However, I was getting a which looked\nlike <code>Verification failed:(0x1A) Security Violation<\/code>. It turns out this was because secure boot was turned on. So we\nneeded to turn it off initially to boot off the Ventoy. You can follow the instructions\n<a href=\"https:\/\/community.frame.work\/t\/solved-secure-boot-and-custom-keys-on-the-amd-motherboard\/38362\/3\">here<\/a>.<\/p>\n<p>We can then turn on secure boot after, I will do a future post how we can do this with NixOS. When I get it working.<\/p>"},{"title":"Part 4: Wezterm Terminal as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2024-01-05-part-4-wezterm-terminal-as-part-of-your-development-workflow\/","pubDate":"Fri, 05 Jan 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-01-05-part-4-wezterm-terminal-as-part-of-your-development-workflow\/","description":"<p>I will preface this article by saying, out of all the tools\/apps in this series, this is probably the least important\ndecision you will make. You can use any terminal editor and basically still have the same development workflow as me.\nSome common terminal emulators include:<\/p>\n<ul>\n<li>kitty<\/li>\n<li>alacritty<\/li>\n<li>foot<\/li>\n<li>wezterm<\/li>\n<\/ul>\n<h2 id=\"background\">Background<\/h2>\n<p>After a break that was probably too long in this series, we&rsquo;re on to the next part looking at our terminal and how we\nset it up. Part of the reason was when I started this series I was using alacritty, however after moving to\nHyprland I soon moved over to the foot terminal. The main reason for this was the sixel support with a CLI file manager.\n<code>lf<\/code>. Which worked with the foot terminal emulator, but I couldn&rsquo;t get working with alacritty. This was so that I could\npreview images in the CLI when using <code>lf<\/code>.<\/p>"},{"title":"TIL: Show to Use the Media Keys on a ZSA Keyboard With Hyprland","link":"https:\/\/haseebmajid.dev\/posts\/2024-01-01-how-to-use-the-media-keys-on-a-zsa-keyboard-with-hyprland\/","pubDate":"Mon, 01 Jan 2024 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2024-01-01-how-to-use-the-media-keys-on-a-zsa-keyboard-with-hyprland\/","description":"<p><strong>TIL: Show to Use the Media Keys on a ZSA Keyboard With Hyprland<\/strong><\/p>\n<p>Recently, I started using a ZSA Voyager split keyboard, moving to this keyboard has some advantages but the last thing\nI felt I was missing from my old keyboard (which has a volume knob) was being able to control the volume. So I set up\nthe key maps in their software (Oryx) however, I noticed that binding were not working.<\/p>"},{"title":"2023 In Summary, My Year of The Terminal","link":"https:\/\/haseebmajid.dev\/posts\/2023-12-31-2023-in-summary-my-year-of-the-terminal\/","pubDate":"Sun, 31 Dec 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-12-31-2023-in-summary-my-year-of-the-terminal\/","description":"<p>For once, I am actually doing a year in review, to go over some of the things I&rsquo;ve learnt over the last year.\nPart of the reason is this has been probably my most transformative year since I have been a software engineer.\nI have become far more terminal development driven, if that is a phrase one can use. What I mean is I changed my\ndevelopment workflow to leverage being in the terminal more. I feel far more productive and efficient than I was at\nthe beginning of the year, for what it&rsquo;s worth<\/p>"},{"title":"TIL: How to Use Default Values in docker-compose.yml","link":"https:\/\/haseebmajid.dev\/posts\/2023-12-30-til-how-to-use-default-values-in-docker-compose-yml\/","pubDate":"Sat, 30 Dec 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-12-30-til-how-to-use-default-values-in-docker-compose-yml\/","description":"<p><strong>TIL: How to Use Default Values in docker-compose.yml<\/strong><\/p>\n<p>Sometimes we want to use env variables in our docker-compose files like so:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-yml\" data-lang=\"yml\"><span class=\"line\"><span class=\"cl\"><span class=\"nt\">services<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span><span class=\"nt\">client<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">        <\/span><span class=\"nt\">image<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"l\">${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}\/nginx<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">        <\/span><span class=\"nt\">ports<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">            <\/span>- <span class=\"m\">8000<\/span><span class=\"p\">:<\/span><span class=\"m\">80<\/span><span class=\"w\">\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>Here we are going to use the GitLab CI dependency proxy to pull our Nginx image, so we can speed up our pipelines but\nalso avoid being rate limited by docker hub. However, when running this locally, we will need to make sure the\n<code>CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX<\/code> env variable is set. Which just adds a bit more work, instead we can leverage\nsome of the special syntax docker-compose provides <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>, which I think it inherits from bash.<\/p>"},{"title":"TIL: How to Use Open Buffers When Debugging With Neovim's DAP Plugin","link":"https:\/\/haseebmajid.dev\/posts\/2023-12-24-til-how-to-use-open-buffers-when-debugging-with-neovim-dap-plugin\/","pubDate":"Sun, 24 Dec 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-12-24-til-how-to-use-open-buffers-when-debugging-with-neovim-dap-plugin\/","description":"<p><strong>TIL: How to Use Open Buffers When Debugging With Neovim&rsquo;s DAP Plugin<\/strong><\/p>\n<p>I had an issue that whilst debugging my Golang tests in Neovim, the buffer I was focusing on would always change to\nthe breakpoint. Even when the buffer was open and visible already, say I had the code with the breakpoint on the left\nbuffer and the tests I was starting the debugger from on the right buffer.<\/p>"},{"title":"TIL: How to Use Tailscale to Connect to K3S PI Cluster","link":"https:\/\/haseebmajid.dev\/posts\/2023-12-20-til-how-to-use-tailscale-to-connect-to-k3s-pi-cluster\/","pubDate":"Wed, 20 Dec 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-12-20-til-how-to-use-tailscale-to-connect-to-k3s-pi-cluster\/","description":"<p><strong>TIL: How to Use Tailscale to Connect to K3S PI Cluster<\/strong><\/p>\n<p>So what do we do if want to connect to our K3S cluster running our RPIs, but we are not on the same network\/at home.\nWell we can look to use a VPN, in this article we will be using <a href=\"https:\/\/tailscale.com\/\">tailscale<\/a>. It is super easy\nto setup on NixOS, and we need very little config for Tailscale. It also has a generous free tier, which will be\nmore than enough for our home lab use case.<\/p>"},{"title":"How to Deploy K3s With Colmena on Pi Cluster","link":"https:\/\/haseebmajid.dev\/posts\/2023-12-16-how-to-deploy-k3s-with-colmena-on-pi-cluster\/","pubDate":"Sat, 16 Dec 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-12-16-how-to-deploy-k3s-with-colmena-on-pi-cluster\/","description":"<p>In this post, we will go over how we can deploy K3S on our PI cluster we have set up. Which is running NixOS,\nand we can also pass secrets using sops nix based on the previous parts of this series.<\/p>\n<p>Some of you maybe wondering what is <a href=\"https:\/\/k3s.io\/\">K3S<\/a>, it is a Kubernetes distribution which is tiny i.e.\nthe binary is only 50 MB. It also has fewer dependencies. Make it perfect our PI cluster and home lab and IoT apps.\nI am still going to work out how to manage the Kubernetes cluster itself, perhaps I will use Pulumi you could also\nterraform if you wanted a reproducible PI cluster.<\/p>"},{"title":"TIL: How to Fix a NTFS Drive on NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2023-12-06-til-how-to-ntfs-drive-on-nixos\/","pubDate":"Wed, 06 Dec 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-12-06-til-how-to-ntfs-drive-on-nixos\/","description":"<p><strong>TIL: How to NTFS Drive on NixOS<\/strong><\/p>\n<p>Recently, I was trying to open an NTFS drive on my NixOS machine; however, the drive was corrupted. So I did the\nfollowing to fix the drive.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">nix-shell -p ntfs3g\n<\/span><\/span><span class=\"line\"><span class=\"cl\">ntfsfix \/dev\/sda1\n<\/span><\/span><\/code><\/pre><\/div><p>Where <code>\/dev\/sda1<\/code> is the broken drive. This was enough for me to be able to mount the drive and access the files on it.\nI didn&rsquo;t need to fix it on a Window machine.<\/p>"},{"title":"TIL: How to Append to a Config Option String in Nix","link":"https:\/\/haseebmajid.dev\/posts\/2023-12-01-til-how-to-append-to-a-config-option-string-in-nix\/","pubDate":"Fri, 01 Dec 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-12-01-til-how-to-append-to-a-config-option-string-in-nix\/","description":"<p><strong>TIL: How to Append to a Config Option String in Nix<\/strong><\/p>\n<p>Recently on my laptop I had to add some extra config settings to my Hyprland config. Rather than polluting my\n<code>hyprland.nix<\/code> file with if, else depending on the host. I wanted to add the extra config in the <code>home.nix<\/code> of the\nhost. So it&rsquo;s contained within that host. Where my <code>home.nix<\/code> is the entry point for my\nhome-manager config for that host.<\/p>"},{"title":"TIL: How to Use Sops Nix With Colmena","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-30-til-how-to-use-sops-nix-with-colmena\/","pubDate":"Thu, 30 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-30-til-how-to-use-sops-nix-with-colmena\/","description":"<p><strong>TIL: How to Use Sops Nix With Colmena<\/strong><\/p>\n<p>If we are using colmena, how can we set it up when we deploy a secret, for example when deploying k3s the token?\ni.e. <code>services.k3s.tokenFile = &quot;\/my.token&quot;;<\/code>.<\/p>\n<p>So to do this first, I will assume you already have a colmena config and sops-nix setup in your config.\nFirst, let&rsquo;s set up our hosts, in this case RPIs which already come <code>\/etc\/ssh\/ssh_host_ed25519_key<\/code> ssh key we can turn\nto an age key, i.e. in our <code>.sops.yaml<\/code>.<\/p>"},{"title":"How I Manage My Raspberry Pi Cluster Using Colmena","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-28-how-to-manage-my-raspberry-pi-cluster-using-colmena\/","pubDate":"Tue, 28 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-28-how-to-manage-my-raspberry-pi-cluster-using-colmena\/","description":"<p>So in the previous article I showed you how I had set up my 4 RPI (Raspberry Pi) cluster and put NixOS on the machines.\nThey are now connectable over SSH using just their hostnames, i.e. <code>ssh strawberry@strawberry.local<\/code>. Initially\nwe deployed NixOS and a basic configuration to each of the RPIs manually.<\/p>\n<p>We want to automate this process rather than deploying to each machine manually. I looked at\n<a href=\"https:\/\/github.com\/rapenne-s\/bento\/\">bento<\/a>, but couldn&rsquo;t quite work out how to make it work for my use case.\nThen I found <a href=\"https:\/\/github.com\/zhaofengli\/colmena\">colmena<\/a>, which worked (is working) to do what I needed.<\/p>"},{"title":"TIL: How to Set the Path Variable When Using Ubuntu With Nix (Home Manager)","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-25-til-how-to-set-the-path-variable-when-using-ubuntu-with-nix-home-manager\/","pubDate":"Sat, 25 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-25-til-how-to-set-the-path-variable-when-using-ubuntu-with-nix-home-manager\/","description":"<p><strong>TIL: How to Set the Path Variable When Using Ubuntu With Nix (Home Manager)<\/strong><\/p>\n<p>As per some of my recent articles, you will be aware I am using Hyprland (tiling manager) on Ubuntu and managing the\nconfig using nix (home-manager). I was having issues where for some reason it wouldn&rsquo;t set the <code>PATH<\/code> variable correctly.<\/p>\n<p>On my NixOS machine, the following would be fine:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\"><span class=\"nv\">bind<\/span><span class=\"o\">=<\/span>,XF86AudioRaiseVolume,exec, volume --inc\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"nv\">bind<\/span><span class=\"o\">=<\/span>,XF86AudioLowerVolume,exec, volume --dec\n<\/span><\/span><\/code><\/pre><\/div><p>However, on Ubuntu I needed to provide the full path:<\/p>"},{"title":"How to Install Hyprland on Ubuntu (22.04)","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-24-how-to-install-hyprland-on-ubuntu-22-04\/","pubDate":"Fri, 24 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-24-how-to-install-hyprland-on-ubuntu-22-04\/","description":"<p>As you may know from my previous articles, my work laptop is an Ubuntu (22.04) laptop. However, on the rest of my devices\nI use NixOS with Hyprland as my tiling window manager. I wanted to be able to use Hyprland on my laptop as well,\nI tried using Sway and, it worked mostly pretty well, but it was yet another to manage and there were some slight\ndifferences. Also, I like the animations on Hyprland \ud83d\ude05.<\/p>"},{"title":"TIL: How to Title Your Terminals When Running Tmux","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-22-til-how-to-title-your-terminals-when-running-tmux\/","pubDate":"Wed, 22 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-22-til-how-to-title-your-terminals-when-running-tmux\/","description":"<p><strong>TIL: How to Title Your Terminals When Running Tmux<\/strong><\/p>\n<p>I have been tmux with the foot terminal and when trying to share my screen I couldn&rsquo;t work out which terminal to share\nbased on the name. Since they are running tmux, all the terminals were titled <code>terminal - t<\/code>.<\/p>\n<p>To fix this and name it after what is running (and where) in tmux, i.e. <code>foot blog\/nvim<\/code>. We can do this by adding the\nfollowing to our tmux config:<\/p>"},{"title":"TIL: How to Start Gnome Wayland Session From TTY","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-21-til-how-to-start-gnome-wayland-session-from-tty\/","pubDate":"Tue, 21 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-21-til-how-to-start-gnome-wayland-session-from-tty\/","description":"<p><strong>TIL: How to Start Gnome Wayland Session From TTY<\/strong><\/p>\n<details\n  class=\"notice info\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Better Version<\/summary>\n  \n  <p>veganomy posted a better version: <a href=\"https:\/\/github.com\/hmajid2301\/blog\/issues\/2\">https:\/\/github.com\/hmajid2301\/blog\/issues\/2<\/a><\/p>\n<p>Copy <code>org.gnome.Shell.desktop<\/code> file locally:<\/p>\n<pre tabindex=\"0\"><code>$ cp \/usr\/share\/applications\/org.gnome.Shell.desktop ~\/.local\/share\/applications\/org.gnome.Shell-Wayland.desktop\n<\/code><\/pre><p>Edit it so that it so that it runs <code>gnome-shell<\/code> as a wayland compositor:<\/p>\n<pre tabindex=\"0\"><code>$ less ~\/.local\/share\/applications\/org.gnome.Shell-Wayland.desktop\n...\nExec=\/usr\/bin\/gnome-shell --wayland\n...\n<\/code><\/pre><p>Copy <code>gnome.session<\/code> file locally:<\/p>\n<pre tabindex=\"0\"><code>$ cp \/usr\/share\/gnome-session\/sessions\/gnome.session ~\/.config\/gnome-session\/sessions\/gnome-wayland.session\n<\/code><\/pre><p>Edit it to use <code>org.gnome.Shell-Wayland<\/code>:<\/p>\n<pre tabindex=\"0\"><code>$ less ~\/.config\/gnome-session\/sessions\/gnome-wayland.session\n...\nRequiredComponents=org.gnome.Shell-Wayland;gnome-settings-daemon;\n...\n<\/code><\/pre><p>Now create an executable <code>~\/.local\/bin\/gnome<\/code> :<\/p>\n<pre tabindex=\"0\"><code>\n#!\/bin\/sh\n\n[ -r \/bin\/gnome-session ] &amp;&amp; {\n\texport \\\n\t\tEGL_PLATFORM=wayland \\\n\t\tGDK_BACKEND=wayland \\\n\t\tXDG_SESSION_DESKTOP=gnome\n\t\/bin\/gnome-session --session=gnome-wayland\n}\n<\/code><\/pre><p>Make sure this directory is in your <code>~\/.bash_profile<\/code> $PATH : <code>export PATH=~\/.local\/bin:$PATH<\/code><\/p>"},{"title":"How I Setup My Raspberry Pi Cluster With Nixos","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-18-how-i-setup-my-raspberry-pi-cluster-with-nixos\/","pubDate":"Sat, 18 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-18-how-i-setup-my-raspberry-pi-cluster-with-nixos\/","description":"<h2 id=\"background\">Background<\/h2>\n<p>Recently, I proceeded to experiment with some Raspberry PIs (RPI) that I had lying around. I wanted to do something\nwith them, so I decided I would turn them into a k8s cluster and put various random tools that might be nice to have\non it. Such as a GitLab runner, Jellyfin media server &amp; pi hole for ad blocking.<\/p>\n<h2 id=\"hardware\">Hardware<\/h2>\n<p>The list below shows the things I used to set up my rpi cluster. None of this is sponsored! I paid for everything\nlisted below:<\/p>"},{"title":"TIL: How to Debug a Test in Golang With Build Tags in Neovim","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-16-til-how-to-debug-a-test-in-golang-with-build-tags-in-neovim\/","pubDate":"Thu, 16 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-16-til-how-to-debug-a-test-in-golang-with-build-tags-in-neovim\/","description":"<p><strong>TIL: How to Debug a Test in Golang With Build Tags in Neovim<\/strong><\/p>\n<p>I was having issues with my debugger today (well technically yesterday because I am publishing this a day later to spread\nout my blog posts but same difference) and it took me a few hours to realise what was going on. In my case, I was\ntrying to debug a test written in Golang using <code>nvim-dap-go<\/code> on Neovim.<\/p>"},{"title":"Part 3: Hyprland as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-15-part-3-hyprland-as-part-of-your-development-workflow\/","pubDate":"Wed, 15 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-15-part-3-hyprland-as-part-of-your-development-workflow\/","description":"<h2 id=\"preamble\">Preamble<\/h2>\n<p>Now we have looked at our choice of hardware, which OS to use and specifically, how to configure NixOS (at a high-level),\nusing a git repository.<\/p>\n<p>In this part, we will go over which window manager to use. There are two main types we could use here. Either a desktop\nenvironment like Gnome or KDE. Which comes with batteries included, it provides us with everything we need and we\ndon&rsquo;t need to configure much to get stuff working. Things like a notification daemon, polkit (for auth).<\/p>"},{"title":"TIL: How to Install Neovim Nightly Using Nix Home Manager (and NixVim)","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-15-til-how-to-install-neovim-nightly-using-nix-home-manager\/","pubDate":"Wed, 15 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-15-til-how-to-install-neovim-nightly-using-nix-home-manager\/","description":"<p><strong>TIL: How to Install Neovim Nightly Using Nix Home Manager (and NixVim)<\/strong><\/p>\n<p>Recently, I wanted to install the nightly version of Neovim (version 0.10) because it supports inlay hints.\nHowever, on nixpkgs the latest version of Neovim as of writing is 0.9.4. So how can we get the nightly release?\nUsing nix\/home-manager.<\/p>\n<p>Simple, we can use an overlay that will add the Neovim nightly package with the nightly. Assuming we are using nix flakes.<\/p>"},{"title":"TIL: How to Set Network Manager Priority to Use Wired Connection Over WIFI","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-10-how-to-set-network-manager-priority-to-use-wired-connection-over-wifi\/","pubDate":"Fri, 10 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-10-how-to-set-network-manager-priority-to-use-wired-connection-over-wifi\/","description":"<p><strong>TIL: How to Set Network Manager Priority to Use Wired Connection Over Wi-Fi<\/strong><\/p>\n<p>If you use network manager on Linux and have both Wi-Fi and wired connection. You may want to prefer using\na wired connection over Wi-Fi, due to stability. To do open the <code>nm-connection-editor<\/code>, if you are using Nix, you can\ndownload it from nixpkgs like usual.<\/p>\n<p><\/p>\n<blockquote>\n<p>Higher number means higher priority.<\/p>\n<\/blockquote>\n<p>So for our wired connection I set the priority to <code>100<\/code> (it was previously -1) and then for our Wi-Fi connection\nI set the priority to <code>1<\/code>.<\/p>"},{"title":"A Simple Way to Convert JSON to Nix Attribute Sets","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-06-a-simple-way-to-convert-json-to-nix-attribute-sets\/","pubDate":"Mon, 06 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-06-a-simple-way-to-convert-json-to-nix-attribute-sets\/","description":"<p>In this post, I will show you how you can take some JSON and convert it into a Nix attribute set.\nThis was particularly useful when I was creating my waybar configuration. Which is usually in JSON, but defined in my\nhome-manager Nix config it has to be in nixlang.<\/p>\n<p>So given this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-json\" data-lang=\"json\"><span class=\"line\"><span class=\"cl\">  <span class=\"s2\">&#34;custom\/notification&#34;<\/span><span class=\"err\">:<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;tooltip&#34;<\/span><span class=\"p\">:<\/span> <span class=\"kc\">false<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;format&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;{icon}&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;format-icons&#34;<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nt\">&#34;notification&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;\uf0a2&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;\uf444&lt;\/sup&gt;&lt;\/span&gt;&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nt\">&#34;none&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;\uf0a2&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nt\">&#34;dnd-notification&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;\uf1f7&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;\uf444&lt;\/sup&gt;&lt;\/span&gt;&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nt\">&#34;dnd-none&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;\uf1f7&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nt\">&#34;inhibited-notification&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;\uf0a2&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;\uf444&lt;\/sup&gt;&lt;\/span&gt;&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nt\">&#34;inhibited-none&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;\uf0a2&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nt\">&#34;dnd-inhibited-notification&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;\uf1f7&lt;span foreground=&#39;red&#39;&gt;&lt;sup&gt;\uf444&lt;\/sup&gt;&lt;\/span&gt;&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nt\">&#34;dnd-inhibited-none&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;\uf1f7&#34;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">},<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;return-type&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;json&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;exec-if&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;which swaync-client&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;exec&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;swaync-client -swb&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;on-click&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;swaync-client -t -sw&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;on-click-right&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;swaync-client -d -sw&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nt\">&#34;escape&#34;<\/span><span class=\"p\">:<\/span> <span class=\"kc\">true<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"p\">}<\/span><span class=\"err\">,<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>We want it to look something like:<\/p>"},{"title":"How Can You Export Your Atuin History to Fish History?","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-05-how-can-you-export-your-atuin-history-to-fish-history\/","pubDate":"Sun, 05 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-05-how-can-you-export-your-atuin-history-to-fish-history\/","description":"<p>I have made an <a href=\"https:\/\/haseebmajid.dev\/2023-08-12-how-sync-your-shell-history-with-atuin-in-nix\/\">post in the past<\/a> about how you can set up\n<a href=\"https:\/\/atuin.sh\/\">Atuin<\/a> to sync share history across multiple devices.<\/p>\n<p>Whilst this works great and does the job, fish shell doesn&rsquo;t have the same history that Atuin does. Sometimes\nwe want to have better suggestions in Fish. For example, when you start to type fish shell will suggest the last command\nin your history that best matches what you are typing (see example below).<\/p>"},{"title":"TIL: How to Use Clipboard Data as File Input in Bash","link":"https:\/\/haseebmajid.dev\/posts\/2023-11-01-til-how-to-use-clipboard-data-as-file-input-in-bash\/","pubDate":"Wed, 01 Nov 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-11-01-til-how-to-use-clipboard-data-as-file-input-in-bash\/","description":"<p><strong>TIL: How to Use Clipboard Data as File Input in Bash<\/strong><\/p>\n<p>Recently, I wanted to run a bash script where it needed to receive a JSON file as input. However, the JSON I had\nwas taken from somewhere on the internet. In this case, it was taking a JSON blob and converting it to a nix attribute\nset. However, I didn&rsquo;t want to save the contents to a file beforehand.<\/p>"},{"title":"How to Setup a Go Development Shell With Nix Flakes","link":"https:\/\/haseebmajid.dev\/posts\/2023-10-26-how-to-setup-a-go-development-shell-with-nix-flakes\/","pubDate":"Thu, 26 Oct 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-10-26-how-to-setup-a-go-development-shell-with-nix-flakes\/","description":"<p>As you may know, I have been using Nix\/NixOS for the last few months. I finally started doing some development, after\nspending lots and lots and lots of time tweaking my setup (and neovim).<\/p>\n<p>As part of starting to do some real development work, I am now trying to leverage devshells with Nix flakes.\nI like the concept of Nix devshells, I have tried using Docker dev containers in the past, but the issue I had\nwith those was adding my tools such as shell (fish) or cli tools was not easy. Whereas Nix shells just add\ntools and scripts to our existing shell.<\/p>"},{"title":"Part 2: How to Setup Nixos as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2023-10-24-part-2-how-to-setup-nixos-as-part-of-your-development-workflow\/","pubDate":"Tue, 24 Oct 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-10-24-part-2-how-to-setup-nixos-as-part-of-your-development-workflow\/","description":"<h2 id=\"premable\">Premable<\/h2>\n<p>In this second part of the series, we will look at how we can not set up NixOS past installation. How we can install\nsoftware and various other tools. After part 1 we should have NixOS installed, mind you since I&rsquo;ve written that blog\npost I found a way to create a custom ISO image from my Nix config. This ISO contains a custom install script,\nthe main advantage being able to use a tool called <a href=\"https:\/\/github.com\/diskonauts\/disko\">disko<\/a> to partition our disks.\nAnyway, I will probably write another post in the future going over how you can do this in another blog post.<\/p>"},{"title":"TIL: How to Fix Networking Issues in a Libvirt VM and Mullvad VPN","link":"https:\/\/haseebmajid.dev\/posts\/2023-10-21-til-how-to-fix-networking-issues-in-a-libvirt-vm-and-mullvad-vpn\/","pubDate":"Sat, 21 Oct 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-10-21-til-how-to-fix-networking-issues-in-a-libvirt-vm-and-mullvad-vpn\/","description":"<p><strong>TIL: How to Fix Networking Issues in a Libvirt VM and Mullvad VPN<\/strong><\/p>\n<p>Recently, I was trying to run a libvirt virtual machine, created using <a href=\"https:\/\/virt-manager.org\/\">virt-manager<\/a>.\nThe VM was running NixOS and somehow no matter what I did it would not connect to the internet.<\/p>\n<p>I was running Mullvad as my VPN, and it turned out this was the app causing issues, I had to turn on\n<code>Local network share<\/code> <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>. Like in the photo below:<\/p>"},{"title":"TIL: How to Disable Linters in Golangci Lint for Test Files","link":"https:\/\/haseebmajid.dev\/posts\/2023-10-10-til-how-to-disable-linters-in-golangci-lint-for-test-files\/","pubDate":"Tue, 10 Oct 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-10-10-til-how-to-disable-linters-in-golangci-lint-for-test-files\/","description":"<p><strong>TIL: How to Disable Linters in Golangci Lint for Test Files<\/strong><\/p>\n<p>Today (for once), I ran <code>golangci-lint run<\/code> and it failed on CI with the following error:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">internal\/options\/parser_test.go:13: Function <span class=\"s1\">&#39;TestParse&#39;<\/span> is too long <span class=\"o\">(<\/span><span class=\"m\">69<\/span> &gt; 60<span class=\"o\">)<\/span> <span class=\"o\">(<\/span>funlen<span class=\"o\">)<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">func TestParse<span class=\"o\">(<\/span>t *testing.T<span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">task: Failed to run task <span class=\"s2\">&#34;lint&#34;<\/span>: <span class=\"nb\">exit<\/span> status <span class=\"m\">1<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Where my <code>.golangci.yml<\/code> file looked like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-yaml\" data-lang=\"yaml\"><span class=\"line\"><span class=\"cl\"><span class=\"nt\">run<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">timeout<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"l\">5m<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">skip-dirs<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">direnv<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\"><\/span><span class=\"nt\">linters<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">enable<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">bodyclose<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">dogsled<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">dupl<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">errcheck<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">exportloopref<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">funlen<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">gochecknoinits<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">goconst<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">gocritic<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">gocyclo<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">gofmt<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">goimports<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">gomnd<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">goprintffuncname<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">gosec<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">gosimple<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">govet<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">ineffassign<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">lll<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">misspell<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">nakedret<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">noctx<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">nolintlint<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">revive<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">staticcheck<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">stylecheck<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">typecheck<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">unconvert<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">unparam<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">unused<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">whitespace<\/span><span class=\"w\">\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>So basically we want the ability to turn off <code>funlen<\/code> for our tests (and other linters). Because we don&rsquo;t mind\nif some of our test functions get a big long with different sub-tests.<\/p>"},{"title":"How to Create Systemd Services in Nix Home Manager","link":"https:\/\/haseebmajid.dev\/posts\/2023-10-08-how-to-create-systemd-services-in-nix-home-manager\/","pubDate":"Sun, 08 Oct 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-10-08-how-to-create-systemd-services-in-nix-home-manager\/","description":"<p>I recently learnt in home-manager (Nix) you can run systemd services as your own user. This is nice because we don&rsquo;t need\n&ldquo;sudo&rdquo; permissions to do so. I also prefer to have as much of my config as possible in home-manager, again I don&rsquo;t\nneed to run &ldquo;sudo&rdquo;. Which is probably safer running apps in the least privileged mode.<\/p>\n<p>In my case, I wanted to run an <code>attic<\/code>, a binary cache, watch store command which uploads any changes to <code>\/nix\/store<\/code>\nto my binary cache. Previously I had this running as a systemd service running as root i.e. managed my NixOS.\nHowever, I wanted to run the same service, on my non-NixOS machine. So I decided to have a look and see if I could\nrun it in my home-manager config so I could run it the same way across all my machines. Whilst researching I came across\nthe <code>systemd.user.services<\/code> option which allows us to do exactly this.<\/p>"},{"title":"TIL: How to Colour Dap Breakpointed Line in Neovim","link":"https:\/\/haseebmajid.dev\/posts\/2023-10-07-til-how-to-colour-dap-breakpointed-line-in-neovim\/","pubDate":"Sat, 07 Oct 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-10-07-til-how-to-colour-dap-breakpointed-line-in-neovim\/","description":"<p><strong>TIL: How to Colour Dap Breakpointed Line in Neovim<\/strong><\/p>\n<p>I wanted to change the background colour of the line when it was stopped during debugging using DAP with neovim.\nTo make it easier to see where we are currently breakpointed.<\/p>\n<p>We already have a highlight group called <code>DapStopped<\/code>. Which in my case is defined as:\n<code>DapStopped = { bg = C.grey }<\/code>.<\/p>\n<p>Then we need to assign the custom highlight group, the key bit being <code>linehl<\/code> for our use case.<\/p>"},{"title":"TIL: How to Fix Package Binary Collisions on Nix","link":"https:\/\/haseebmajid.dev\/posts\/2023-10-02-til-how-to-fix-package-binary-collisions-on-nix\/","pubDate":"Mon, 02 Oct 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-10-02-til-how-to-fix-package-binary-collisions-on-nix\/","description":"<p><strong>TIL: How to Fix Package Binary Collisions on Nix<\/strong><\/p>\n<p>Recently I wanted to use <a href=\"https:\/\/www.gnu.org\/software\/parallel\/\">GNU parallel<\/a>, a nifty little tool we can use\nto run tasks in parallel, shock horror I know. I already have the <code>moreutils<\/code> package installed using nix (home-manager).<\/p>\n<p>So I added this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-nix\" data-lang=\"nix\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">home<\/span><span class=\"o\">.<\/span><span class=\"n\">packages<\/span> <span class=\"err\">=<\/span> <span class=\"k\">with<\/span> <span class=\"n\">pkgs<\/span><span class=\"p\">;<\/span> <span class=\"p\">[<\/span>\n<\/span><\/span><span class=\"line hl\"><span class=\"cl\">  <span class=\"n\">parallel<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">moreutils<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">]<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Then I ran the home manager switch like usual, I got the following error.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">error: builder <span class=\"k\">for<\/span> <span class=\"s1\">&#39;\/nix\/store\/vh6i81xhf6pvybdpall8z8l8y0i6mr8p-home-manager-path.drv&#39;<\/span> failed with <span class=\"nb\">exit<\/span> code 25<span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">       last <span class=\"m\">1<\/span> log lines:\n<\/span><\/span><span class=\"line\"><span class=\"cl\">       &gt; error: collision between <span class=\"sb\">`<\/span>\/nix\/store\/slkylri9sbn4w7paaixzc5wj6cwfk83m-moreutils-0.67\/bin\/parallel<span class=\"s1\">&#39; and `\/nix\/store\/fjpnw99zvx2f910s016jrmybc5jxirpn-parallel-20230822\/bin\/parallel&#39;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">       For full logs, run <span class=\"s1\">&#39;nix log \/nix\/store\/vh6i81xhf6pvybdpall8z8l8y0i6mr8p-home-manager-path.drv&#39;<\/span>.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">error: <span class=\"m\">1<\/span> dependencies of derivation <span class=\"s1\">&#39;\/nix\/store\/m4p56x5lgjfpvdy0xjrbk981sfchpl8c-home-manager-generation.drv&#39;<\/span> failed to build\n<\/span><\/span><\/code><\/pre><\/div><p>Because <code>moreutils<\/code> also have a binary called parallel. How do we tell Nix to overwrite the moreutils binary and use\nthe one in the <code>parallel<\/code> packages?  Simple by using <code>lib.hiPrio<\/code> like so:<\/p>"},{"title":"Setup Ventoy on Nixos","link":"https:\/\/haseebmajid.dev\/posts\/2023-09-29-setup-ventoy-on-nixos\/","pubDate":"Fri, 29 Sep 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-09-29-setup-ventoy-on-nixos\/","description":"<h2 id=\"introduction\">Introduction<\/h2>\n<p>Typically when we want to install a new OS we use an ISO to create a bootable USB drive. We can then plug this into\nour device, say laptop, and boot from that USB and install our OS. However, typically you can only put a single ISO on\na USB. So what if wanted a USB with say Window, Arch Linux, TailsOS and NixOS how could we do that?<\/p>"},{"title":"TIL: How to Use fzf.fish History Search","link":"https:\/\/haseebmajid.dev\/posts\/2023-09-19-til-how-to-use-fzf-fish-history-search\/","pubDate":"Tue, 19 Sep 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-09-19-til-how-to-use-fzf-fish-history-search\/","description":"<p><strong>TIL: How to Use fzf.fish History Search<\/strong><\/p>\n<p>I use Fish Shell with fzf and <a href=\"https:\/\/github.com\/PatrickF1\/fzf.fish\">fish fzf plugin<\/a>.\nI installed fzf using nix and home-manager:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-nix\" data-lang=\"nix\"><span class=\"line\"><span class=\"cl\"><span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">programs<\/span><span class=\"o\">.<\/span><span class=\"n\">fzf<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">enable<\/span> <span class=\"o\">=<\/span> <span class=\"no\">true<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">enableFishIntegration<\/span> <span class=\"o\">=<\/span> <span class=\"no\">false<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"p\">};<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">}<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>It adds <code>fzf-history-widget<\/code> script, which is bound to <code>ctrl+r<\/code>, shell reverse history search.\nWhich we can see when we run this: <code>bind | grep -e fzf-history-widget -e fzf-file-widget<\/code><\/p>\n<p>Whereas I wanted to use the <code>_fzf_search_history<\/code> which is made available by that fish fzf plugin.\nNow PatrickF1 recommends running the uninstaller script from fzf, but I found another way we can overwrite\nthe binding by adding the following lines to our <code>fish.config<\/code>:<\/p>"},{"title":"My NixOS Dotfiles Explained","link":"https:\/\/haseebmajid.dev\/posts\/2023-09-12-how-i-configure-nixos-as-part-of-my-development-workflow\/","pubDate":"Tue, 12 Sep 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-09-12-how-i-configure-nixos-as-part-of-my-development-workflow\/","description":"<p>In this post, we will just go over the basics of how we can configure our setup using a git repo, nix flakes and\nhome-manager. I will go over how I structured my nix config.<\/p>\n<details\n  class=\"notice Info\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Not an in-depth tutorial<\/summary>\n  \n  Note this will not be an in-depth guide into NixOS\/Home Manager itself. That could well be a series on its own.\nWe will just go over the main ways I configure NixOS\/Nix and why I do it the way I do. I recommend doing some reading\nand playing around and figuring out what works for you &#x1f604;\n<\/details>\n\n<h2 id=\"introduction\">Introduction<\/h2>\n<p>We will be using two different ways to configure our system, NixOS via a <code>configuration.nix<\/code> to configure the machine\nitself. Which includes partitions, backups, docker anything that needs to be run system-wide. Anything that\nneeds &ldquo;sudo&rdquo; permissions is configured via this expression. Note we will of course split our nix expressions into smaller\nmodules. That will be re-used between multiple hosts.<\/p>"},{"title":"TIL: How to Check if Another Option Is Set in Home Manager (Nix)","link":"https:\/\/haseebmajid.dev\/posts\/2023-09-10-til-how-to-check-if-another-option-is-set-in-home-manager-nix\/","pubDate":"Sun, 10 Sep 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-09-10-til-how-to-check-if-another-option-is-set-in-home-manager-nix\/","description":"<p><strong>TIL: How to Check if Another Option Is Set in Home Manager (Nix)<\/strong><\/p>\n<p>Recently I was adding sway to my nix config (setup via home-manager). I already had Hyprland config, I wanted both\nsway and Hyprland to use my waybar config with some slight differences. So basically I want to check if the current\nhost machine is using Sway or Hyprland (I am assuming we will only use one).<\/p>\n<blockquote>\n<p>The main reason for using Sway is my work laptop uses Ubuntu 22.04, It&rsquo;s not easy to run Hyprland on a &ldquo;stable&rdquo; distro like Ubuntu better suited to Arch or NixOS.<\/p>"},{"title":"TIL: How to Access System in Home Manager Using Flakes","link":"https:\/\/haseebmajid.dev\/posts\/2023-09-05-til-how-to-access-system-in-home-manager-using-flakes\/","pubDate":"Tue, 05 Sep 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-09-05-til-how-to-access-system-in-home-manager-using-flakes\/","description":"<p><strong>TIL: How to Access System in Home Manager Using Flakes<\/strong><\/p>\n<p>Recently I needed to install devenv using flakes in home-manager. One of the things I needed to pass to was the type\nof system to install on i.e. <code>&quot;x86_64-linux&quot;<\/code>.<\/p>\n<p>So as I temp hack I had something like: <code>inputs.devenv.packages.&quot;x86_64-linux&quot;.devenv<\/code>.<\/p>\n<p>However I was able to access the system using the <code>pkgs<\/code> attribute like so:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-nix\" data-lang=\"nix\"><span class=\"line\"><span class=\"cl\"><span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">inputs<\/span><span class=\"o\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">pkgs<\/span><span class=\"o\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"o\">...<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">}:<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"n\">home<\/span><span class=\"o\">.<\/span><span class=\"n\">packages<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"n\">inputs<\/span><span class=\"o\">.<\/span><span class=\"n\">devenv<\/span><span class=\"o\">.<\/span><span class=\"n\">packages<\/span><span class=\"o\">.<\/span><span class=\"s2\">&#34;<\/span><span class=\"si\">${<\/span><span class=\"n\">pkgs<\/span><span class=\"o\">.<\/span><span class=\"n\">system<\/span><span class=\"si\">}<\/span><span class=\"s2\">&#34;<\/span><span class=\"o\">.<\/span><span class=\"n\">devenv<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"p\">];<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">}<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Where my <code>flake.nix<\/code> looks something like:<\/p>"},{"title":"TIL: How to Fix tmux-resurrect on NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2023-09-01-til-how-to-fix-tmux-resurrect-on-nixos\/","pubDate":"Fri, 01 Sep 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-09-01-til-how-to-fix-tmux-resurrect-on-nixos\/","description":"<p><strong>TIL: How to Fix tmux-resurrect on NixOS<\/strong><\/p>\n<p>When I moved to NixOS I noticed that <a href=\"https:\/\/github.com\/tmux-plugins\/tmux-resurrect\"> tmux-resurrect <\/a> stop restoring\nsome applications such as <code>man<\/code> and <code>nvim<\/code>. Like it used to on my Arch machine. I recently found a solution to my\nproblem (thanks to a lovely chap on the nixos discourse).<\/p>\n<p>By adding the following lines to our tmux config:<\/p>\n<pre tabindex=\"0\"><code class=\"language-tmux\" data-lang=\"tmux\">resurrect_dir=&#34;$HOME\/.tmux\/resurrect&#34;\nset -g @resurrect-dir $resurrect_dir\nset -g @resurrect-hook-post-save-all &#39;target=$(readlink -f $resurrect_dir\/last); sed &#34;s| --cmd .*-vim-pack-dir||g; s|\/etc\/profiles\/per-user\/$USER\/bin\/||g; s|\/home\/$USER\/.nix-profile\/bin\/||g&#34; $target | sponge $target&#39;\n<\/code><\/pre><p>What this does is it edits the tmux-resurrect file from this:<\/p>"},{"title":"How to Use Cachix Devenv to Setup Developer Environments","link":"https:\/\/haseebmajid.dev\/posts\/2023-08-26-how-to-use-cachix-devenv-to-setup-developer-environments\/","pubDate":"Sat, 26 Aug 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-08-26-how-to-use-cachix-devenv-to-setup-developer-environments\/","description":"<p>In this post, I will go over how you can use Cachix&rsquo;s <a href=\"https:\/\/devenv.sh\/\">devenv<\/a> tool to help create\/set up consistent\nrepeatable developer environments. You could use nix flakes if you wanted to as well, without needing another tool.\nHowever, I like how devenv provides a few other &ldquo;tools&rdquo; within that we can set up from a single <code>devenv.nix<\/code> file. Such as\npre-commit hooks, container support etc.<\/p>\n<p>This blog leverages devenv to create\/set up its developer environment.<\/p>"},{"title":"TIL: How to Colour Neovim Line Numbers","link":"https:\/\/haseebmajid.dev\/posts\/2023-08-24-til-how-to-colour-neovim-line-numbers\/","pubDate":"Thu, 24 Aug 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-08-24-til-how-to-colour-neovim-line-numbers\/","description":"<p><strong>TIL: How to Colour Neovim Line Numbers<\/strong><\/p>\n<p>Recently I was trying to configure my own neovim config. I wanted the current line I was onto be coloured slighty\ndifferently and also the line number to be white. So it&rsquo;s easier to see the line number and which line I was on.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-08-24-til-how-to-colour-neovim-line-numbers\/images\/highlight.png\"\n        type=\"\"\n        alt=\"Highlight\"\n        \n      \/><\/p>\n<p>It was not immediately obvious how to do this and took me long to work out than I&rsquo;d like to admit \ud83d\ude05.<\/p>"},{"title":"How To Self Host Your Own Atuin Server","link":"https:\/\/haseebmajid.dev\/posts\/2023-08-16-how-self-host-your-own-atuin-server\/","pubDate":"Wed, 16 Aug 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-08-16-how-self-host-your-own-atuin-server\/","description":"<p>In this article, we will go over how we can <a href=\"https:\/\/atuin.sh\/docs\/self-hosting\/\">self-host<\/a> our instance of <a href=\"https:\/\/atuin.sh\/\">Atuin<\/a>.\nA tool we can use to sync our shell history across multiple devices. In the previous article, I showed how you can\nuse the official server. However you may want to run your self-hosted one, so no one can access even the\nencrypted version of your shell history.<\/p>\n<p>We will deploy our instance to fly.io. Why fly.io, its pretty easy to deploy they have a great CLI tool. Also\nwe can get a Postgres database deployed, which we need with <code>Atuin<\/code>.<\/p>"},{"title":"How Sync Your Shell History With Atuin in Nix","link":"https:\/\/haseebmajid.dev\/posts\/2023-08-12-how-sync-your-shell-history-with-atuin-in-nix\/","pubDate":"Sat, 12 Aug 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-08-12-how-sync-your-shell-history-with-atuin-in-nix\/","description":"<p><a href=\"https:\/\/atuin.sh\/docs\/\">Atuin<\/a> is a great tool I recently discovered that can be used to sync our shell history across\nmultiple machines. We can either self-host this or use the &ldquo;officially&rdquo; hosted one. In a future article, I will show\nyou how you can self-host your version of Atuin on fly.io. But for this article, I will assume you have a server\nsetup. Your history is end-to-end encrypted so the official server is safe to use and store your history on.<\/p>"},{"title":"TIL: How to Setup Neovim for Nixlang","link":"https:\/\/haseebmajid.dev\/posts\/2023-08-06-til-how-to-setup-neovim-for-nixlang\/","pubDate":"Sun, 06 Aug 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-08-06-til-how-to-setup-neovim-for-nixlang\/","description":"<p><strong>TIL: How to Setup Neovim for Nixlang<\/strong><\/p>\n<p>I have been recently using NixOS\/home-manager and I have been writing a lot of nixlang. To have my system state\ndeclaratively set up. I have been doing most of this editing in neovim. It took me a bit of time to work out how to get\nit set up so there is some basic LSP support and auto-formatting. I created a file called <code>nix.lua<\/code> and it looks like this:<\/p>"},{"title":"TIL: How to Fix VIA Permission Issues on Linux","link":"https:\/\/haseebmajid.dev\/posts\/2023-08-02-til-how-to-fix-via-permission-issues-on-linux\/","pubDate":"Wed, 02 Aug 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-08-02-til-how-to-fix-via-permission-issues-on-linux\/","description":"<p><strong>TIL: How to Fix VIA Permission Issues on Linux<\/strong><\/p>\n<p>Recently I have been trying to configure my newish Keychron keyboard using <a href=\"https:\/\/www.caniusevia.com\/\">VIA<\/a>.\nTo add a key to be able to take print screens, making use of the layers provided,\nas my Keychron Q1 PRO doesn&rsquo;t have a dedicated print key &#x1f613;.<\/p>\n<p>However, when I opened the app or the <a href=\"https:\/\/usevia.app\/\">website<\/a>, I would get\nthe following error.<\/p>\n<p>If we go to <code>chrome:\/\/device-log<\/code> you should be able to see something like this:\n<code>Failed to open '\/dev\/hidraw9': FILE_ERROR_ACCESS_DENIED<\/code>.<\/p>"},{"title":"How to Use Neotest Dap With Lazyvim for Golang Development","link":"https:\/\/haseebmajid.dev\/posts\/2023-07-31-how-to-use-neotest-dap-with-lazyvim-for-golang-development\/","pubDate":"Mon, 31 Jul 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-07-31-how-to-use-neotest-dap-with-lazyvim-for-golang-development\/","description":"<p>In this blog post, I will show you how you can easily setup Neotest to make testing easier in neovim and DAP to make\ndebugging your tests is a lot easier.<\/p>\n<p>I am using the <a href=\"https:\/\/www.lazyvim.org\/\">LazyVim<\/a> neovim distribution, where these two come as easily installed extra\nplugins. However, it should be easy enough for you to copy the config over to your neovim lua config.\nLazyVim even has the config available on its website, you don&rsquo;t even need to deep dive into the code &#x1f604;.<\/p>"},{"title":"TIL: How to get Kanshi to work on NixOS and Hyprland","link":"https:\/\/haseebmajid.dev\/posts\/2023-07-25-nixos-kanshi-and-hyprland\/","pubDate":"Tue, 25 Jul 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-07-25-nixos-kanshi-and-hyprland\/","description":"<p><strong>TIL: How to get Kanshi to work on NixOS and Hyprland<\/strong><\/p>\n<p>I have been using Kanshi to setup my monitor setups automagically depending on which monitors are plugged\ni.e. if my laptop is docked or not. If it is docked I want my laptop display to be off, when not docked I want\nit to be on. So my kanshi config file <code>~\/.config\/kanshi\/config<\/code> to look something like:<\/p>\n<p>I use the name of my monitors as the ports they are plugged into my vary.<\/p>"},{"title":"Part 1: NixOS as part of your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2023-07-20-nixos-as-part-of-your-development-workflow\/","pubDate":"Thu, 20 Jul 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-07-20-nixos-as-part-of-your-development-workflow\/","description":"<h2 id=\"introduction\">Introduction<\/h2>\n<details\n  class=\"notice info\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Dev Machine<\/summary>\n  \n  <p>My main machine for development at the moment is a 12th Generation Intel Framework Laptop.<\/p>\n<p><\/p>\n\n<\/details>\n\n<p>This series has been inspired by <a href=\"https:\/\/www.joshmedeski.com\/guides\/dev-workflow-intro\/\">Dev Workflow Intro by Josh Medeski<\/a>.<\/p>\n<p>In this series of posts, I will go over how I have set up my developer workflow\nand explain why I have made certain decisions and why I use certain tools. This series aim to make it less daunting for you to start your journey\non improving your developer workflow. Or share with you tools that you made not\nhave heard of. Most of the tools I used I discovered in videos\/blogs talking about\ndeveloper workflows.<\/p>"},{"title":"Part 0: Hardware as Part of Your Development Workflow","link":"https:\/\/haseebmajid.dev\/posts\/2023-07-18-my-hardware-as-part-of-my-development-workflow\/","pubDate":"Tue, 18 Jul 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-07-18-my-hardware-as-part-of-my-development-workflow\/","description":"<p>This series has been inspired by <a href=\"https:\/\/www.joshmedeski.com\/guides\/dev-workflow-intro\/\">Dev Workflow Intro by Josh Medeski<\/a>.<\/p>\n<p>This is sort of a precursor to my series about how I have set up my development workflow. Hopefully, you will be able to\npick a few tips and tricks you can add to your development workflow to make it more efficient. Or even give me tips\non how I can make my workflow more efficient.<\/p>\n<p>In this post we will go over arguably the least important, but at the same time quite important, part of our workflow.\nBecause in theory, we can run the same development workflow on lots of different types of hardware. I don&rsquo;t\nnecessarily need a mechanical keyboard or a monitor I can just use a keyboard.<\/p>"},{"title":"My Dotfiles III","link":"https:\/\/haseebmajid.dev\/posts\/2023-07-15-my-dotfiles-iii\/","pubDate":"Sat, 15 Jul 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-07-15-my-dotfiles-iii\/","description":"<p>My latest iteration of my dotfiles, where I am now using a Laptop as my main development machine (Framework).\nI&rsquo;m also using Hyprland as my window manager. Most importantly using NixOS and home-manager to declaratively define\nthe state of my machine i.e. what packages to install, dotfiles.<\/p>\n<p><strong>CURRENTLY A WIP<\/strong><\/p>\n<p>&#x1f3e0; My dotfiles repo, setup using nixos\/home-manager<\/p>\n<h2 id=\"install\">Install<\/h2>\n<blockquote>\n<p>&#x1f525; I wouldn&rsquo;t recommend just blinding using my dotfiles. They are setup for my specific use-case.\nI think you&rsquo;re off using this repo as reference to create your own dotfiles.<\/p>"},{"title":"Update Nix Packages Using update-nix-fetchgit","link":"https:\/\/haseebmajid.dev\/posts\/2023-07-13-updating-nix-packages-using-update-nix-fetchgit\/","pubDate":"Thu, 13 Jul 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-07-13-updating-nix-packages-using-update-nix-fetchgit\/","description":"<p>Recently I&rsquo;ve been trying to work out how to update packages that I define declaratively in my Nix config.\nI think I figured out how to do it using my Nix flake. By running <code>nix flake update<\/code> and then\n<code>sudo nixos-rebuild switch --flake ~\/dotfiles#framework<\/code> to update the packages.<\/p>\n<p>However, I have some plugins say for tmux which are defined like so:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-nix\" data-lang=\"nix\"><span class=\"line\"><span class=\"cl\">  <span class=\"n\">t-smart-manager<\/span> <span class=\"err\">=<\/span> <span class=\"n\">pkgs<\/span><span class=\"o\">.<\/span><span class=\"n\">tmuxPlugins<\/span><span class=\"o\">.<\/span><span class=\"n\">mkTmuxPlugin<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"n\">pluginName<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&#34;t-smart-tmux-session-manager&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"n\">version<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&#34;unstable-2023-06-05&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"n\">rtpFilePath<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&#34;t-smart-tmux-session-manager.tmux&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"n\">src<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pkgs<\/span><span class=\"o\">.<\/span><span class=\"n\">fetchFromGitHub<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        <span class=\"n\">owner<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&#34;joshmedeski&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        <span class=\"n\">repo<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&#34;t-smart-tmux-session-manager&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        <span class=\"n\">rev<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&#34;0a4c77c5c3858814621597a8d3997948b3cdd35d&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        <span class=\"n\">sha256<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">&#34;1dr5w02a0y84q2iw4jp1psxvkyj4g6pr87gc22syw1jd4ibkn925&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"p\">};<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">};<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>Note the <code>fetchFromGitHub<\/code> function, where we specify a specific git revision to get. I was looking at ways we could\nupdate this automatically. Then I came across this tool <a href=\"https:\/\/github.com\/expipiplus1\/update-nix-fetchgit\">update-nix-fetchgit<\/a>.\nWhen run it will update the <code>rev<\/code>, <code>sha256<\/code> and <code>version<\/code> for us.<\/p>"},{"title":"Setting Up Tmux With Nix Home Manager","link":"https:\/\/haseebmajid.dev\/posts\/2023-07-10-setting-up-tmux-with-nix-home-manager\/","pubDate":"Mon, 10 Jul 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-07-10-setting-up-tmux-with-nix-home-manager\/","description":"<h2 id=\"introduction\">Introduction<\/h2>\n<p>In this post I will show you how you can setup tmux (plugins) using the nix package manager, specifically using home-manager.\nI will also show you how you can avoid an issue I encountered where tmux resurrect wasn&rsquo;t working properly due to\nplugin ordering.<\/p>\n<p>Typically we use the <a href=\"https:\/\/github.com\/tmux-plugins\/tpm\">tmux plugin manager<\/a> to manage our tmux plugins.\nHowever, when I moved to NixOS, I wanted to move away from having lots of different ways of managing what is on my\nsystem. For example, on my Arch Linux machine I had:<\/p>"},{"title":"Why I moved to NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2023-06-25-why-i-moved-to-nixos\/","pubDate":"Sun, 25 Jun 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-06-25-why-i-moved-to-nixos\/","description":"<p>Recently I decided to move from Arch Linux to NixOS. Rather than doing what I should&rsquo;ve done which was\ntry to use NixOS in a VM first and learn Nix properly. I decided to jump into the deep end and completely delete my\ncurrent Arch Linux build with Nix. This included replacing my dotfiles setup using DotBot moving them to Nix flakes and\nhome-manager (more on this in a bit). In this post, I&rsquo;ll go over why I moved over to NixOS, and why I am staying put for now.\nWhat I like about it and some difficulties I have had.<\/p>"},{"title":"TIL: How to use NUR with Home-Manager & Nix Flakes","link":"https:\/\/haseebmajid.dev\/posts\/2023-06-22-til-use-nur-with-home-manager-flake\/","pubDate":"Thu, 22 Jun 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-06-22-til-use-nur-with-home-manager-flake\/","description":"<p><strong>TIL: How to use NUR with Home-Manager &amp; Nix Flakes<\/strong><\/p>\n<p>NUR is the Nix user repository like the Arch user repository (AUR). It exists so that:<\/p>\n<blockquote>\n<p>The NUR was created to share new packages from the community in a faster and more decentralized way. - <a href=\"https:\/\/github.com\/nix-community\/NUR\">https:\/\/github.com\/nix-community\/NUR<\/a><\/p>\n<\/blockquote>\n<p>If we want to install packages from NUR in our home manager config which is set up using Nix Flakes.\nAssuming you build your home manager like<\/p>"},{"title":"TIL: How to Declaratively Setup Mullvad VPN with NixOS","link":"https:\/\/haseebmajid.dev\/posts\/2023-06-20-til-how-to-declaratively-setup-mullvad-with-nixos\/","pubDate":"Tue, 20 Jun 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-06-20-til-how-to-declaratively-setup-mullvad-with-nixos\/","description":"<p><strong>TIL: How to Declaratively Setup Mullvad VPN with NixOS<\/strong><\/p>\n<p>I have recently moved to NixOS, one of the great features of NixOS is that you can set up your entire machine\nfrom a single git repo. We can do this declaratively, what we mean by this is we tell nix what we want the state to\nbe and nixos will work out how to get there.<\/p>\n<p>For example, we can install Mullvad set various options already. This means on a new machine we don&rsquo;t manually have to\nsetup these mullvad settings.<\/p>"},{"title":"TIL: How to Add Vim Navigation FZF","link":"https:\/\/haseebmajid.dev\/posts\/2023-05-30-til-how-to-vim-navigation-to-fzf\/","pubDate":"Tue, 30 May 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-05-30-til-how-to-vim-navigation-to-fzf\/","description":"<p><strong>TIL: How to Add Vim Navigation FZF<\/strong><\/p>\n<p><a href=\"https:\/\/github.com\/junegunn\/fzf\">FZF<\/a> is an amazing fuzzy finder tool, that is super flexible and you can create some\ncool cli one-liners with it. For example, I use it with the fish shell plugin to search through my command history (CTRL + R).<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-05-30-til-how-to-vim-navigation-to-fzf\/images\/fzf.jpg\"\n        type=\"\"\n        alt=\"FZF Example\"\n        \n      \/><\/p>\n<p>In this post, I will show you how vim style navigation to the FZF pop-up preview. All we need to do is add the following to the\nrelevant file i.e. <code>fish.config<\/code>, <code>.bashrc<\/code> or <code>.zshrc<\/code>.<\/p>"},{"title":"TIL: How to change the fish greeter","link":"https:\/\/haseebmajid.dev\/posts\/2023-05-25-til-how-to-change-fish-greeter\/","pubDate":"Thu, 25 May 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-05-25-til-how-to-change-fish-greeter\/","description":"<p><strong>TIL: How to change the fish greeter<\/strong><\/p>\n<p>In this post I will show you how you can change your fish shell greeter from the default<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">Welcome to fish, the friendly interactive shell\n<\/span><\/span><span class=\"line\"><span class=\"cl\">Type <span class=\"sb\">`<\/span><span class=\"nb\">help<\/span><span class=\"sb\">`<\/span> <span class=\"k\">for<\/span> instructions on how to use fish\n<\/span><\/span><\/code><\/pre><\/div><p>To something custom, this will run every time you open a new shell!<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-05-25-til-how-to-change-fish-greeter\/images\/greeting.png\"\n        type=\"\"\n        alt=\"Fish Greeting\"\n        \n      \/><\/p>\n<p>To do this, go to your <code>fish_greeter.fish<\/code> file which can usually be found at <code>~\/.config\/fish\/functions\/fish_greeting.fish<\/code>.\nWhere mine looks like:<\/p>"},{"title":"My Development Workflow With Linux","link":"https:\/\/haseebmajid.dev\/posts\/2023-05-08-my-development-workflow-with-linux\/","pubDate":"Mon, 08 May 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-05-08-my-development-workflow-with-linux\/","description":"<p>Following on from my previous post about dotfiles and my development workflow (WIP), in this post I will go over my\noperating system.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-05-08-my-development-workflow-with-linux\/images\/dev.png\"\n        type=\"\"\n        alt=\"Development Window\"\n        \n      \/>\n<img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-05-08-my-development-workflow-with-linux\/images\/fun.png\"\n        type=\"\"\n        alt=\"Fun Window\"\n        \n      \/><\/p>\n<h2 id=\"arch\">Arch<\/h2>\n<p>As the name implies I use Linux as my main operating system. I am a big fan of Linux because not only is free and\nopen-source, it provides a great developer experience where I find tools that just work on Linux. It also is a lot more\ncustomisable as compared with Windows or MacOS. Finally, I tend to find it more lightweight as well and takes fewer\nresources to run especially if you are using Docker.<\/p>"},{"title":"My Dotfiles II","link":"https:\/\/haseebmajid.dev\/posts\/2023-05-04-my-dotfiles-ii\/","pubDate":"Thu, 04 May 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-05-04-my-dotfiles-ii\/","description":"<p>I know I recently made a post about my dotfiles but I&rsquo;ve made a few changes since then, so here are my updated dotfiles.<\/p>\n<details\n  class=\"notice caution\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">out of date<\/summary>\n  \n  These dotfiles are out of date check out my updated ones <a href=\"https:\/\/haseebmajid.dev\/posts\/2023-07-15-my-dotfiles-iii\/\">here<\/a>\n<\/details>\n\n<h2 id=\"system-overview\">System Overview<\/h2>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-05-04-my-dotfiles-ii\/images\/dev.png\"\n        type=\"\"\n        alt=\"neovim\"\n        \n      \/>\n<img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-05-04-my-dotfiles-ii\/images\/fun.png\"\n        type=\"\"\n        alt=\"Tmux\"\n        \n      \/><\/p>\n<ul>\n<li>OS: Arch Linux<\/li>\n<li>DE: Gnome<\/li>\n<li>Shell: Fish\n<ul>\n<li>Prompt: <a href=\"https:\/\/starship.rs\/\">Starship<\/a><\/li>\n<\/ul>\n<\/li>\n<li>Terminal: Alacritty\n<ul>\n<li>Editor: Neovim (using <a href=\"https:\/\/www.lazyvim.org\">LazyVim<\/a> config)<\/li>\n<\/ul>\n<\/li>\n<li>Colorscheme: <a href=\"https:\/\/github.com\/catppuccin\">Catppuccin for EVERYTHING!!!<\/a><\/li>\n<li>Fonts: <a href=\"https:\/\/www.monolisa.dev\/\">Mono Lisa<\/a><\/li>\n<\/ul>\n<h3 id=\"extensions\">Extensions<\/h3>\n<p>I use the following Gnome extension. You can find the config for the extensions in this <a href=\"gnome\/settings.ini\">massive file here<\/a>.<\/p>"},{"title":"My Development Workflow With Alacritty Fish Tmux Nvim","link":"https:\/\/haseebmajid.dev\/posts\/2023-05-02-my-development-workflow-with-alacritty-fish-tmux-nvim\/","pubDate":"Tue, 02 May 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-05-02-my-development-workflow-with-alacritty-fish-tmux-nvim\/","description":"<details\n  class=\"notice info\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Workflows Change<\/summary>\n  \n  This post is accurate as of date of publish. But likely will go stale, if I update my workflows I will likely publish\nanother post.\n<\/details>\n\n<p>In this blog post, I will go over my current development workflow using the above tools namely, fish shell tmux and neovim.\nI&rsquo;ll be using the <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/tree\/8da9d515234d050dc34703e94f647fd9cb40c61a\">dotfiles<\/a>\nfound here.<\/p>\n<p>I aim to move away from using my mouse as much as possible as it just slows me down when my hands\nare away from my keyboard.<\/p>"},{"title":"My Dotfiles","link":"https:\/\/haseebmajid.dev\/posts\/2023-04-30-my-dotfiles\/","pubDate":"Sun, 30 Apr 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-04-30-my-dotfiles\/","description":"<p>This post is a quick introduction to\n<a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/tree\/af7ec81b7ad48af758f73233a7b2a0461f95e285\">dotfiles<\/a>, accurate as of 25th of April 2023.<\/p>\n<details\n  class=\"notice caution\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">out of date<\/summary>\n  \n  These dotfiles are out of date check out my updated ones <a href=\"https:\/\/haseebmajid.dev\/posts\/2023-05-04-my-dotfiles-ii\/\">here<\/a>\n<\/details>\n\n<h1 id=\"dotfiles\">Dotfiles<\/h1>\n<p>&#x1f3e0; My dotfiles setup using <a href=\"https:\/\/github.com\/anishathalye\/dotbot\/\">Dotbot<\/a>.<\/p>\n<h2 id=\"install\">Install<\/h2>\n<blockquote>\n<p>&#x1f525; I wouldn&rsquo;t recommend just blinding using my dotfiles. They are setup for my specific use-case. I think you&rsquo;re better picking and choosing what you like &#x1f604;.<\/p>\n<\/blockquote>\n<pre tabindex=\"0\"><code>git clone git@github.com:hmajid2301\/dotfiles.git\ncd dotfiles\nmake install profile=arch\n<\/code><\/pre><h2 id=\"system-overview\">System Overview<\/h2>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-04-30-my-dotfiles\/images\/quick_settings.png\"\n        type=\"\"\n        alt=\"Quick Settings\"\n        \n      \/>\n<img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-04-30-my-dotfiles\/images\/tmux.png\"\n        type=\"\"\n        alt=\"Tmux\"\n        \n      \/><\/p>"},{"title":"How to Get Code Coverage From Playwright Tests in a Sveltekit App","link":"https:\/\/haseebmajid.dev\/posts\/2023-04-15--how-to-get-code-coverage-from-playwright-tests-in-a-sveltekit-app-\/","pubDate":"Sat, 15 Apr 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-04-15--how-to-get-code-coverage-from-playwright-tests-in-a-sveltekit-app-\/","description":"<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-04-15--how-to-get-code-coverage-from-playwright-tests-in-a-sveltekit-app-\/images\/code_coverage.jpg\"\n        type=\"\"\n        alt=\"Code Coverage Meme\"\n        \n      \/><\/p>\n<p>In this post, I will show you how to get code coverage reports from your Playwright tests in your SvelteKit app.\nSo let&rsquo;s imagine we are starting with the basic SvelteKit template. First, we need to install:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">npm i -D vite-plugin-istanbul\n<\/span><\/span><\/code><\/pre><\/div><p>We need the vite plugin to instrument our code using Istanbul.\nIstanbul is a tool which allows us to instrument our code such that it can determine which lines were covered\nby our tests.<\/p>"},{"title":"TIL: How to Get VSCode ESLint to Sort Imports","link":"https:\/\/haseebmajid.dev\/posts\/2023-04-09--til-how-to-get-vscode-eslint-to-sort-imports-\/","pubDate":"Sun, 09 Apr 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-04-09--til-how-to-get-vscode-eslint-to-sort-imports-\/","description":"<p>I use VS Code as my text editor, one of the features I really like about VS Code is that it will format our file on save.\nWhich saves needing to run a CLI tool to do it. For example, running <code>prettier<\/code>. As part of the formatting on save you can\nset an option to organise your imports as well.<\/p>\n<p>If you open your <code>settings.json<\/code>, you can add a section like this:<\/p>"},{"title":"TIL: How to Deploy 'Multiple' Sites on One GitLab Page Site","link":"https:\/\/haseebmajid.dev\/posts\/2023-04-06-til-how-to-deploy-multiple-sites-on-one-gitlab-page-site\/","pubDate":"Thu, 06 Apr 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-04-06-til-how-to-deploy-multiple-sites-on-one-gitlab-page-site\/","description":"<p>I have a repo which I use to store all of my conference and similar talks. This repo includes any code examples\nand most importantly the slides.<\/p>\n<p>At the moment all the slides are RevealJS &ldquo;sites&rdquo;, which means it&rsquo;s a presentation built in HTML. Now I would like\nto have all my talks deployed to single GitLab pages site. For example something like:<\/p>\n<ul>\n<li><a href=\"https:\/\/hmajid2301.io\/talks\/an-intro-to-pocketbase\/\">https:\/\/hmajid2301.io\/talks\/an-intro-to-pocketbase\/<\/a><\/li>\n<li><a href=\"https:\/\/hmajid2301.io\/talks\/docker-as-a-dev-tool\/\">https:\/\/hmajid2301.io\/talks\/docker-as-a-dev-tool\/<\/a><\/li>\n<\/ul>\n<p>So how can we do this ? Simple! In our job to deploy the site we just need to add <code>public\/docker-as-a-dev-tool<\/code> and <code>public\/an-intro-to-pocketbase<\/code>\nrespectively. Which ever path we provide is that path we will be able to access those slides on.<\/p>"},{"title":"TIL: How to Mock Classes Using Vitest","link":"https:\/\/haseebmajid.dev\/posts\/2023-04-01--til-mock-classes-using-vitest-\/","pubDate":"Sat, 01 Apr 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-04-01--til-mock-classes-using-vitest-\/","description":"<p><strong>TIL: How to Mock Classes Using Vitest<\/strong><\/p>\n<p>Recently I have been creating a SvelteKit app, when creating a new SvelteKit app you get a choice\nof different things you can add. Such as using <code>vitest<\/code> for unit testing.<\/p>\n<p>I needed to spy on\/mock a method in a class, to see if it was called when a button was pressed and, it was called\nwith the correct arguments.<\/p>\n<p>Let&rsquo;s say we have a <code>Button<\/code> component which looks like this:<\/p>"},{"title":"TIL: How to Use Multiple Auth Files in Playwright","link":"https:\/\/haseebmajid.dev\/posts\/2023-03-22--til-how-to-use-multiple-auth-in-playwright-\/","pubDate":"Wed, 22 Mar 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-03-22--til-how-to-use-multiple-auth-in-playwright-\/","description":"<p><strong>TIL: How to Load Authenticate State in Playwright<\/strong><\/p>\n<p>In this post, I will quickly show you how you can reduce boilerplate code to log in to your app in Playwright tests.\nLog in to our app is a very common action that will likely be required in most of our tests.<\/p>\n<p>You can read this <a href=\"https:\/\/playwright.dev\/docs\/auth\">documentation here<\/a>, which will explain how you can set this up.\nHowever, what do you do if you want to say test the login flow or the register flow? You cannot use the same auth\nfile as all the other tests as you will already be logged in.<\/p>"},{"title":"How to Create New Posts on Hugo Using Archetypes","link":"https:\/\/haseebmajid.dev\/posts\/2023-03-20--how-to-create-new-posts-on-hugo-using-archetypes-\/","pubDate":"Mon, 20 Mar 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-03-20--how-to-create-new-posts-on-hugo-using-archetypes-\/","description":"<p>In this post, I will go over how you can use Hugo&rsquo;s archetypes to quickly create new posts.\nI have previously used NetlifyCMS to help create new posts, but recently I have found that to be\na bit overkill for my blog.<\/p>\n<p>So I decided to simplify my workflow by using Hugo&rsquo;s archetypes <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>. Archetypes allow us to create templates\nmarkdown files, which is then used to create our blog posts.<\/p>"},{"title":"TIL: How to Set a Relationship on Golang Pocketbase","link":"https:\/\/haseebmajid.dev\/posts\/2023-03-08--til-how-to-set-a-relationship-on-golang-pocketbase-\/","pubDate":"Wed, 08 Mar 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-03-08--til-how-to-set-a-relationship-on-golang-pocketbase-\/","description":"<p><strong>TIL: How to Set a Relationship on Golang Pocketbase<\/strong><\/p>\n<p><a href=\"https:\/\/pocketbase.io\/\">Pocketbase<\/a> is a backend as a service, it is very nice because it is written in Golang\nit can compile down to a single binary. It also allows us to extend it using Golang and use it as a framework.\nIn my case, I needed some extra logic before adding data to the database so I decided to extend Pocketbase\nand write some of my business logic.<\/p>"},{"title":"TIL: How to Run Parallel Jobs on Gitlab CI (Different Stages)","link":"https:\/\/haseebmajid.dev\/posts\/2023-03-03-til-how-to-run-parallel-jobs-on-gitlab-ci\/","pubDate":"Fri, 03 Mar 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-03-03-til-how-to-run-parallel-jobs-on-gitlab-ci\/","description":"<p><strong>TIL: How to Run Parallel Jobs on Gitlab CI (Different Stages)<\/strong><\/p>\n<p>If you are familiar with Gitlab CI you probably know that jobs in the same stages will run in parallel.\nHowever you can also run jobs in different stages at the same time. Let&rsquo;s see our <code>.gitlab-ci.yml<\/code> looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-yaml\" data-lang=\"yaml\"><span class=\"line\"><span class=\"cl\"><span class=\"nt\">stages<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span>- <span class=\"l\">test<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span>- <span class=\"l\">deploy<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\"><\/span><span class=\"nt\">format<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">stage<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"l\">test<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">script<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">task format<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\"><\/span><span class=\"nt\">lint<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">stage<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"l\">test<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">script<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">task lint<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\"><\/span><span class=\"nt\">deploy:preview<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">stage<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"l\">deploy<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">only<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">merge_request<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">image<\/span><span class=\"p\">:<\/span><span class=\"w\"> <\/span><span class=\"l\">docker<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">  <\/span><span class=\"nt\">script<\/span><span class=\"p\">:<\/span><span class=\"w\">\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"w\">    <\/span>- <span class=\"l\">task deploy<\/span><span class=\"w\">\n<\/span><\/span><\/span><\/code><\/pre><\/div><p>So for my use case when a user creates a merge request, I want to run some tests against the code,\nsuch as linting and formatting. But also deploy my app to a preview environment. Whilst these jobs\nbelong to different stages.<\/p>"},{"title":"How to Setup Netlify Deployment Notifications on Discord with Pipedream","link":"https:\/\/haseebmajid.dev\/posts\/2023-01-26-how-to-setup-netlify-deployment-notifications-on-discord-with-pipedream\/","pubDate":"Thu, 26 Jan 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-01-26-how-to-setup-netlify-deployment-notifications-on-discord-with-pipedream\/","description":"<p>Hi everyone, I recently went about setting up notifications about my Netlify deploys in Discord. Netlify does have an official way to do\nhowever, you cannot use it on the free tier.<\/p>\n<p>So I looked at other solutions, and I eventually discovered a SaaS product called <a href=\"pipedream.com\/\">PipeDream<\/a>. It is a website which allows\nus to connect different components without needing to write any code. Such as what to do when we receive a webhook. There are 100s\nof different apps, triggers and actions. What we want to end up with is something like this:<\/p>"},{"title":"TIL: How to fix `structuredClone` to work on Netlify SvelteKit Site","link":"https:\/\/haseebmajid.dev\/posts\/2023-01-23-til-how-to-fix-structuredclone-to-work-on-netlify-sveltekit-site\/","pubDate":"Mon, 23 Jan 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-01-23-til-how-to-fix-structuredclone-to-work-on-netlify-sveltekit-site\/","description":"<p><strong>TIL: How to fix <code>structuredClone<\/code> to work on Netlify SvelteKit Site<\/strong><\/p>\n<p>Recently I was working on my SvelteKit site and added some code like so to my <code>hook.server.ts<\/code>:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ts\" data-lang=\"ts\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">locals<\/span><span class=\"p\">.<\/span><span class=\"nx\">pb<\/span><span class=\"p\">.<\/span><span class=\"nx\">authStore<\/span><span class=\"p\">.<\/span><span class=\"nx\">isValid<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        <span class=\"k\">await<\/span> <span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">locals<\/span><span class=\"p\">.<\/span><span class=\"nx\">pb<\/span><span class=\"p\">.<\/span><span class=\"nx\">collection<\/span><span class=\"p\">(<\/span><span class=\"s2\">&#34;users&#34;<\/span><span class=\"p\">).<\/span><span class=\"nx\">authRefresh<\/span><span class=\"p\">();<\/span>\n<\/span><\/span><span class=\"line hl\"><span class=\"cl\">        <span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">locals<\/span><span class=\"p\">.<\/span><span class=\"nx\">user<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">structuredClone<\/span><span class=\"p\">(<\/span><span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">locals<\/span><span class=\"p\">.<\/span><span class=\"nx\">pb<\/span><span class=\"o\">?<\/span><span class=\"p\">.<\/span><span class=\"nx\">authStore<\/span><span class=\"p\">.<\/span><span class=\"nx\">model<\/span><span class=\"p\">);<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">}<\/span> <span class=\"k\">catch<\/span> <span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nx\">log<\/span><span class=\"p\">(<\/span><span class=\"s2\">&#34;failed to refresh auth&#34;<\/span><span class=\"p\">,<\/span> <span class=\"nx\">err<\/span><span class=\"p\">);<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">locals<\/span><span class=\"p\">.<\/span><span class=\"nx\">user<\/span> <span class=\"o\">=<\/span> <span class=\"kc\">undefined<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">locals<\/span><span class=\"p\">.<\/span><span class=\"nx\">pb<\/span><span class=\"p\">.<\/span><span class=\"nx\">authStore<\/span><span class=\"p\">.<\/span><span class=\"nx\">clear<\/span><span class=\"p\">();<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">}<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>I needed to add the <code>structuredClone<\/code> function so that only POJO (plain old javascript objects) would get stored in the <code>event.locals.users<\/code>\nvariable. However when I deployed this to production in Netlify. This broke my site! Specifically, it wouldn&rsquo;t let the user log in.<\/p>"},{"title":"TIL: How to Autofocus on Inputs in Svelte","link":"https:\/\/haseebmajid.dev\/posts\/2023-01-19-til-how-to-autofocus-on-inputs-in-svelte\/","pubDate":"Thu, 19 Jan 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-01-19-til-how-to-autofocus-on-inputs-in-svelte\/","description":"<p><strong>TIL: How to Autofocus on Inputs in Svelte<\/strong><\/p>\n<p>In this post, I will show you how you can autofocus on input that is in a child component.\nSo in my use case, I want the user to click a button to add a &ldquo;collection&rdquo; and then it will show the input\nand immediately focus on it. Which looks something like this:<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-01-19-til-how-to-autofocus-on-inputs-in-svelte\/images\/autofocus.gif\"\n        type=\"\"\n        alt=\"Autofocus Input\"\n        \n      \/><\/p>\n<p>So how can we do this?<\/p>"},{"title":"How Can We Update GitLab CI on the Status of the Netlify Deploy Part I","link":"https:\/\/haseebmajid.dev\/posts\/2023-01-17-how-can-we-update-gitlab-ci-on-the-status-of-the-netlify-deploy-part-i\/","pubDate":"Tue, 17 Jan 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-01-17-how-can-we-update-gitlab-ci-on-the-status-of-the-netlify-deploy-part-i\/","description":"<p>In this post, I will show you how you can update your GitLab CI pipeline with the status of your Netlify deploys.\nAs it is quite nice to have everything in one place if our CI pipeline passed or failed.<\/p>\n<p>I have spoken about this in a\n<a href=\"https:\/\/haseebmajid.dev\/posts\/2022-12-03-my-workflow-to-create-a-new-post-using-hugo,-netlifycms,-netlify-and-gitlab-together\">previous article<\/a>,\nhow you might go about setting up merge request preview environments with Netlify.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2023-01-17-how-can-we-update-gitlab-ci-on-the-status-of-the-netlify-deploy-part-i\/images\/netlify_mr_comment.png\"\n        type=\"\"\n        alt=\"Netlify MR comment\"\n        \n      \/><\/p>\n<p>This can be set up to also leave comments as shown above, and notify us if our website deployed successfully. Which will look like so:<\/p>"},{"title":"TIL: How Includes, Extends work with TS Config (with SvelteKit)","link":"https:\/\/haseebmajid.dev\/posts\/2023-01-14-til-how-includes-extends-work-with-ts-config-with-sveltekit\/","pubDate":"Sat, 14 Jan 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-01-14-til-how-includes-extends-work-with-ts-config-with-sveltekit\/","description":"<p><strong>TIL: How Includes, Extends work with TS Config (with SvelteKit)<\/strong><\/p>\n<p>I have recently been creating an app with SvelteKit and Typescript. I noticed all of a sudden Typescript and VS Code not playing\nnice with each other. It wouldn&rsquo;t show me the types of variables that I knew it was showing me before. So I started to investigate\nand work out what was wrong. I was getting <code>locals<\/code> with a type <code>any<\/code>:<\/p>"},{"title":"How to Autosort our SvelteKit Imports","link":"https:\/\/haseebmajid.dev\/posts\/2023-01-10-how-to-autosort-our-sveltekit-imports\/","pubDate":"Tue, 10 Jan 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-01-10-how-to-autosort-our-sveltekit-imports\/","description":"<p>In this post, we will go over how we can auto-sort our imports in our svelte files. To do this we will be using eslint and the\n<a href=\"https:\/\/github.com\/import-js\/eslint-plugin-import\/blob\/main\/docs\/rules\/order.md\"><code>eslint-import-plugin<\/code> plugin<\/a>.<\/p>\n<p>If you&rsquo;re anything like me you like have ordered imports, rather than random imports that can be hard to make sense of.\nIn Python we have <code>isort<\/code> in golang we have <code>goimports<\/code>. In JavaScript we can use eslint with the above plugin. However,\nwe need to set up some specific configuration.<\/p>"},{"title":"How to add Have I Been Pwned to Your Registration Flow in SvelteKit","link":"https:\/\/haseebmajid.dev\/posts\/2023-01-08-how-to-add-have-i-been-pwned-to-your-registration-flow-in-sveltekit\/","pubDate":"Sun, 08 Jan 2023 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2023-01-08-how-to-add-have-i-been-pwned-to-your-registration-flow-in-sveltekit\/","description":"<p>In this post, I will go over how you can use the have I been pwned (hibp) API to improve UX <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup> in our registration flow in our SvelteKit app.\nWhen the user signs up we can check if that password has been compromised in a previous data breach (on another site).\nThen we can prompt the user to enter another password. This will help avoid users using simple &amp; common passwords like <code>password11<\/code>.\nIdeally, our user would be using a password manager to generate secure and strong passwords. You can see us using the hibp website below,\nof course, in our case, we will want to use the API.<\/p>"},{"title":"How to Remote Debug your SvelteKit on an Android Device in Firefox","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-30-how-to-remote-debug-your-sveltekit-on-an-android-device-in-firefox\/","pubDate":"Fri, 30 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-30-how-to-remote-debug-your-sveltekit-on-an-android-device-in-firefox\/","description":"<p>In this post, we will go over how you can test your SvelteKit app on your Android device in Firefox.\nIf you&rsquo;re like me you are building an app that you want users to use on both normal PCs (laptops, Desktop) and\ntheir smartphones.<\/p>\n<p>But the question arises how can we debug our app on a smartphone?\nOne way to achieve this is to use Firefox and remote debugging, you will need to connect your\nsmartphone via USB to your device running the SvelteKit app i.e. your Laptop.<\/p>"},{"title":"TIL: How to Setup Netlify, Gitlab And Sentry","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-29-til-how-to-setup-netlify-gitlab-and-sentry\/","pubDate":"Thu, 29 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-29-til-how-to-setup-netlify-gitlab-and-sentry\/","description":"<p><strong>TIL: How to Setup Netlify, Gitlab And Sentry<\/strong><\/p>\n<p>I will show you in this post how you can integrate Gitlab, Netlify and Sentry. I may do a more\ndetailed post in the future.<\/p>\n<h2 id=\"gitlab---sentry\">GitLab -&gt; Sentry<\/h2>\n<p>To connect Gitlab and Sentry follow <a href=\"https:\/\/docs.sentry.io\/product\/integrations\/source-code-mgmt\/gitlab\/\">this guide<\/a>.\nThen add the repos you want to monitor in Sentry. In my case, it is the Bookmarkey GUI.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-12-29-til-how-to-setup-netlify-gitlab-and-sentry\/images\/sentry_repository.png\"\n        type=\"\"\n        alt=\"Sentry Repo List\"\n        \n      \/><\/p>\n<h2 id=\"netlify---gitlab\">Netlify -&gt; GitLab<\/h2>\n<p>This integration is pretty simple just go through the normal Netlify setup process to add a new site.\nYou can read more about that <a href=\"https:\/\/haseebmajid.dev\/posts\/2022-12-03-my-workflow-to-create-a-new-post-using-hugo,-netlifycms,-netlify-and-gitlab-together\">here<\/a>\nand <a href=\"https:\/\/docs.netlify.com\/welcome\/add-new-site\/\">here<\/a>.<\/p>"},{"title":"TIL: How To Add Custom Syntax Highlighting Rules in VS Code","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code\/","pubDate":"Tue, 27 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code\/","description":"<p><strong>TIL: How To Add Custom Syntax Highlighting Rules in VS Code<\/strong><\/p>\n<p>The other day (a few months ago) I was comparing Goland and VS Code for Golang development.\nI noticed Goland by default seemed to have nicer syntax highlighting, so I started looking at\nwhat I could do in VS Code to do this.<\/p>\n<blockquote>\n<p>Before<\/p>\n<\/blockquote>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code\/images\/before.png\"\n        type=\"\"\n        alt=\"Before\"\n        \n      \/><\/p>\n<blockquote>\n<p>After<\/p>\n<\/blockquote>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code\/images\/after.png\"\n        type=\"\"\n        alt=\"After\"\n        \n      \/><\/p>\n<p>It turns out we can do this with our own custom rules using <code>editor.tokenColorCustomizations<\/code>.\nTo do this go to our settings (<code>settings.json<\/code>) and add something like:<\/p>"},{"title":"TIL: How to Connect PocketBase and BackBlaze S3","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-26-til-how-to-connect-pocketbase-and-backblaze-s3\/","pubDate":"Mon, 26 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-26-til-how-to-connect-pocketbase-and-backblaze-s3\/","description":"<p><strong>TIL: How to Connect PocketBase and BackBlaze S3<\/strong><\/p>\n<blockquote>\n<p>By default PocketBase uses the local file system to store uploaded files. If you have limited disk space, you could optionally connect to a S3 compatible storage. - PocketBase<\/p>\n<\/blockquote>\n<h2 id=\"why-backblaze-\">Why BackBlaze ?<\/h2>\n<p>Simple the prices are generally cheaper as compared with other S3 compatible storage platforms.\nHow can we set up BackBlaze as our S3 bucket to store uploaded files such as user avatars?<\/p>"},{"title":"TIL: How to Use DinD, localhost & Gitlab CI","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-21-til-how-to-use-dind-localhost-gitlab-ci\/","pubDate":"Wed, 21 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-21-til-how-to-use-dind-localhost-gitlab-ci\/","description":"<p><strong>TIL: How to Use DinD, localhost &amp; Gitlab CI<\/strong><\/p>\n<p>In this post, I will go over how you can use docker-compose and Gitlab CI.\nIn this example, we will be running playwright tests directly on the Gitlab runner.\nThe tests will start a SvelteKit server also running on the Gitlab runner. The SvelteKit\nserver will connect to PocketBase (backend) running in docker-compose.<\/p>\n<p>So essentially we need a way for something running locally to connect to something running in\ndocker in Gitlab CI (on a runner). This is a pattern I am using in my new app <a href=\"https:\/\/bookmarkey.app\">Bookmarkey<\/a> <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>.<\/p>"},{"title":"How to Setup OAuth2 with SvelteKit and Pocketbase","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-20-how-to-setup-oauth2-with-sveltekit-and-pocketbase\/","pubDate":"Tue, 20 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-20-how-to-setup-oauth2-with-sveltekit-and-pocketbase\/","description":"<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Out of date<\/summary>\n  \n  This article maybe a bit out of date as PocketBase is adding new features and deprecating old functions. If you encounter\nan issue with the setup <a href=\"https:\/\/gitlab.com\/hmajid2301\/blog\/-\/issues\/108\">see this issue by Dominick<\/a>\n<\/details>\n\n<p>Hi everyone, I&rsquo;ve been building a new <a href=\"https:\/\/gitlab.com\/banter-bus\/bookmarkey\/gui\">bookmarking app<\/a>, using SvelteKit and\nPocketBase. <a href=\"https:\/\/pocketbase.io\/\">PocketBase<\/a>, is an open-source backend, that we need to self-host <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>. It is written\nin Golang, think of it similar to Firebase or Supabase.<\/p>\n<p>PocketBase will handle authentication for us, creating new users, and storing the password securely. You know things all apps\nneed, that we don&rsquo;t want to spend a lot of times building ourselces. To learn more about authentication with SvelteKit I recommend checking out the web\nthere are some fantastic tutorials available <sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2<\/a><\/sup>.<\/p>"},{"title":"How to use DotBot to personalise your VSCode Devcontainers","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-15-how-to-use-dotbot-to-personalise-your-vscode-devcontainers\/","pubDate":"Thu, 15 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-15-how-to-use-dotbot-to-personalise-your-vscode-devcontainers\/","description":"<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Devcontainers<\/summary>\n  \n  This article assumes you are already familiar with dev containers.\nYou can read more about <a href=\"https:\/\/code.visualstudio.com\/docs\/devcontainers\/containers\">devcontainers here<\/a>.\n<\/details>\n\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-12-15-how-to-use-dotbot-to-personalise-your-vscode-devcontainers\/images\/say-docker.jpeg\"\n        type=\"\"\n        alt=\"Docker Meme\"\n        \n      \/><\/p>\n<p>In this article, we will go over how you can personalise your dev containers. Devcontainers allow us to create consistent development environments. One of the main advantages of dev containers is we can provide a &ldquo;one button&rdquo; setup for new developers.\nWe do this by using a container (Docker), and we end up developing inside a container. Much like if we used <code>docker exec -it ubuntu \/bin\/bash<\/code>.\nExcept it provides a few nice conveniences such as copying (into the container) over the project files and our ssh keys.<\/p>"},{"title":"TIL: How to Use Prettier with Hugo\/Golang Templates","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-12-til-how-to-use-prettier-with-hugo-golang-templates\/","pubDate":"Mon, 12 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-12-til-how-to-use-prettier-with-hugo-golang-templates\/","description":"<p><strong>TIL: How to Use Prettier with Hugo\/Golang Templates<\/strong><\/p>\n<p>If you try to use prettier on a (Hugo) Golang HTML template you may get something that looks like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-go-html-template\" data-lang=\"go-html-template\"><span class=\"line\"><span class=\"cl\"><span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"k\">or<\/span><span class=\"w\"> <\/span><span class=\"na\">.Params.author<\/span><span class=\"w\"> <\/span><span class=\"nx\">site<\/span><span class=\"na\">.Params.author<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"nx\">$author<\/span><span class=\"w\"> <\/span><span class=\"o\">:=<\/span><span class=\"w\"> <\/span><span class=\"o\">(<\/span><span class=\"na\">.Params.author<\/span><span class=\"w\"> <\/span><span class=\"o\">|<\/span><span class=\"w\"> <\/span><span class=\"nx\">default<\/span><span class=\"w\"> <\/span><span class=\"nx\">site<\/span><span class=\"na\">.Params.author<\/span><span class=\"o\">)<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"nx\">$author_type<\/span><span class=\"w\"> <\/span><span class=\"o\">:=<\/span><span class=\"w\"> <\/span><span class=\"o\">(<\/span><span class=\"k\">printf<\/span><span class=\"w\"> <\/span><span class=\"s\">&#34;%T&#34;<\/span><span class=\"w\"> <\/span><span class=\"nx\">$author<\/span><span class=\"o\">)<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"o\">(<\/span><span class=\"k\">or<\/span><span class=\"w\"> <\/span><span class=\"o\">(<\/span><span class=\"k\">eq<\/span><span class=\"w\"> <\/span><span class=\"nx\">$author_type<\/span><span class=\"w\"> <\/span><span class=\"s\">&#34;[]string&#34;<\/span><span class=\"o\">)<\/span><span class=\"w\"> <\/span><span class=\"o\">(<\/span><span class=\"k\">eq<\/span><span class=\"w\"> <\/span><span class=\"nx\">$author_type<\/span><span class=\"w\"> <\/span><span class=\"s\">&#34;[]interface {}&#34;<\/span><span class=\"o\">))<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"o\">(<\/span><span class=\"nx\">delimit<\/span><span class=\"w\"> <\/span><span class=\"nx\">$author<\/span><span class=\"w\"> <\/span><span class=\"s\">&#34;, &#34;<\/span><span class=\"w\"> <\/span><span class=\"o\">)<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"k\">else<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"nx\">$author<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"k\">end<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"k\">end<\/span><span class=\"w\"> <\/span><span class=\"cp\">-}}<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>into this<\/p>"},{"title":"TIL: How to Deploy a SvelteKit site on Netlify","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-10-til-how-to-deploy-a-sveltekit-site-on-netlify\/","pubDate":"Sat, 10 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-10-til-how-to-deploy-a-sveltekit-site-on-netlify\/","description":"<p><strong>TIL: How to Deploy a SvelteKit site on Netlify<\/strong><\/p>\n<p>So you have a SvelteKit site you want to deploy to Netlify how can we do that? First, go about setting up a site like normal!\nIn my case, I am going to import an existing site from Gitlab.<\/p>\n<h2 id=\"netlify\">Netlify<\/h2>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-12-10-til-how-to-deploy-a-sveltekit-site-on-netlify\/images\/new_netlify_site.png\"\n        type=\"\"\n        alt=\"New Netlify Site\"\n        \n      \/><\/p>\n<p>In the build settings we want the following settings:<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-12-10-til-how-to-deploy-a-sveltekit-site-on-netlify\/images\/import_site.png\"\n        type=\"\"\n        alt=\"Import from git\"\n        \n      \/><\/p>\n<details\n  class=\"notice tip\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Branch<\/summary>\n  \n  Adjust the branch to whatever your main branch is i.e. the branch you want to deploy from.\n<\/details>\n\n<p>That&rsquo;s it now our site should start deploying, and it should also set up deploy previews for MRs automatically\n<a href=\"https:\/\/haseebmajid.dev\/posts\/2022-12-03-my-workflow-to-create-a-new-post-using-hugo-netlifycms-netlify-and-gitlab-together\/#netlify-preview\">More about that here<\/a>.<\/p>"},{"title":"How to Update a Project using a Copier Template","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-09-how-to-update-a-project-using-a-copier-template\/","pubDate":"Thu, 08 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-09-how-to-update-a-project-using-a-copier-template\/","description":"<p>In this article, I will show you how you can update a project, that was created from a copier template.\nIn my <a href=\"https:\/\/haseebmajid.dev\/posts\/2022-12-01-how-to-use-copier-to-create-project-templates\/\">previous article<\/a>, we learnt how we can create\na project template. I listed the only reason I choose to use copier over say cookiecutter was that it provided an\n&ldquo;easy&rdquo; way to update downstream projects.<\/p>\n<details\n  class=\"notice tip\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Existing Repository<\/summary>\n  \n  From here on out we will assume you have a template repository that uses <code>copier<\/code>.\nHere is an <a href=\"https:\/\/gitlab.com\/banter-bus\/fastapi-template\">example repository<\/a>.\n<\/details>\n\n<h2 id=\"update\">Update<\/h2>\n<details\n  class=\"notice tip\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Terminology<\/summary>\n  \n  <p>Some terminology:<\/p>"},{"title":"TIL: How to Separate our Golang Tests","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-04-til-how-to-separate-our-golang-tests\/","pubDate":"Sun, 04 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-04-til-how-to-separate-our-golang-tests\/","description":"<p><strong>TIL: How to Separate our Golang Tests<\/strong><\/p>\n<p>Sometimes we want to be able to run our unit tests and integration tests separately.\nIn Golang we can do this using build tags, build tags are used to tell the compiler\nimportant information when we run <code>go build<\/code> <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>.<\/p>\n<p>Let say we have a file called <code>package_test.go<\/code>. By adding <code>\/\/ +build integration<\/code> to the top of the file\nwithout any whitespace. This test file will only be run when we specify the tags in our\ntest command <code>go test --tags=integration<\/code>.<\/p>"},{"title":"My Workflow To Create a New Post Using Hugo, NetlifyCMS, Netlify and Gitlab Together","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-03-my-workflow-to-create-a-new-post-using-hugo-netlifycms-netlify-and-gitlab-together\/","pubDate":"Sat, 03 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-03-my-workflow-to-create-a-new-post-using-hugo-netlifycms-netlify-and-gitlab-together\/","description":"<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Netlify CMS Deprecated<\/summary>\n  \n  <p>Since I have written this post Netlify CMS has been deprecated in favour of decap-cms.\nThanks to @roneo for raising this <a href=\"https:\/\/gitlab.com\/hmajid2301\/blog\/-\/issues\/101\">issue<\/a>.<\/p>\n<p>So the Netlify CMS part of this article is no longer relevant. I also no longer use this\nworkflow, I instead just create articles locally using a script now!!!<\/p>\n\n<\/details>\n\n<p>In this post, I will go over my new workflow for creating articles\/posts that I now use with\nmy new (Hugo) blog. Though I&rsquo;m sure much of this will apply to other JAM stack sites as well.<\/p>"},{"title":"My Useful Vim Commands (with VS Code)","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-02-my-useful-vim-commands-with-vs-code\/","pubDate":"Fri, 02 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-02-my-useful-vim-commands-with-vs-code\/","description":"<p>In this post, I will show you some useful and perhaps not as well-known Vim commands I use with VS Code.\nAs per <a href=\"https:\/\/haseebmajid.dev\/2022-10-16-my-current-vscode-setup-extensions-and-settings\/\">this previous post<\/a>, I use\n<a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=vscodevim.vim\">this extension<\/a> for Vim emulation in VS Code.<\/p>\n<p>My <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/blob\/6b83e990861654506e8ecc756af75cf431438a4a\/vscode\/linux\/keybindings.json\">keybindings.json<\/a> file.<\/p>\n<p>I will repeat some of the settings I showed there for posterity.<\/p>\n<h2 id=\"useful-commands\">Useful Commands<\/h2>\n<ul>\n<li><code>xp<\/code>: To swap two characters around  i.e. <code>ab<\/code> -&gt; <code>ba<\/code> (cursor on <code>a<\/code>)<\/li>\n<li><code>ctrl + enter<\/code>: Creates a new line below and stays in <code>NORMAL<\/code>\n<ul>\n<li><code>o<\/code>: Will do the same but put you in insert mode<\/li>\n<\/ul>\n<\/li>\n<li><code>ctrl + shift + enter<\/code>: Creates a new line above and stays in <code>NORMAL<\/code>\n<ul>\n<li><code>O<\/code>: Will do the same but put you in insert mode<\/li>\n<\/ul>\n<\/li>\n<li><code>dtx<\/code>: Deletes everything up to <code>x<\/code> character<\/li>\n<li><code>dfx<\/code>: Delete everything including <code>x<\/code> character<\/li>\n<li><code>yi&quot;<\/code>: Yank everything between quotes <code>&quot;<\/code><\/li>\n<li><code>vi&quot;&quot;+p<\/code>: Replace everything between quotes with what is yanked<\/li>\n<li><code>va{Vy<\/code> <sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1<\/a><\/sup>: Yank the entire function assuming the language uses braces like <code>golang<\/code> or <code>C<\/code><\/li>\n<li><code>&quot;_dd<\/code> <sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2<\/a><\/sup>: Delete without adding to register<\/li>\n<li><code>&quot;aY<\/code> <sup id=\"fnref1:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2<\/a><\/sup>: Yank into named register <code>a<\/code><\/li>\n<li><code>&quot;ap<\/code> <sup id=\"fnref2:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2<\/a><\/sup>: Paste from named register <code>a<\/code><\/li>\n<li><code>%x``df(<\/code> <sup id=\"fnref:3\"><a href=\"#fn:3\" class=\"footnote-ref\" role=\"doc-noteref\">3<\/a><\/sup>: Deletes surrounding function i.e. <code>func(arg)<\/code> -&gt; <code>arg<\/code><\/li>\n<\/ul>\n<h3 id=\"commands-as-settings\">Commands as settings<\/h3>\n<p>To make some of these commands easier to use we can do something like:<\/p>"},{"title":"How to use copier to create project templates","link":"https:\/\/haseebmajid.dev\/posts\/2022-12-01-how-to-use-copier-to-create-project-templates\/","pubDate":"Thu, 01 Dec 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-12-01-how-to-use-copier-to-create-project-templates\/","description":"<p>Hi &#x1f44b; everyone, in this blog post I&rsquo;m going to over how we can use <code>Copier<\/code> to create templates for our repositories.<\/p>\n<h2 id=\"why-create-a-template-repo-\">Why create a template repo ?<\/h2>\n<p>I&rsquo;m sure some of you are wondering why do we even need templates ? Well for a few reasons, one it gives you a consistent way to create\nnew services from a repository. For my personal project Banter Bus I have a <a href=\"https:\/\/gitlab.com\/banter-bus\/fastapi-template\">FastAPI Template<\/a>,\nwhich I use to create new FastAPI services from. It creates a lot of boilerplate which I don&rsquo;t have to worry about. It provides consistency\nso makes it easier to jump between my FastAPI services in Banter Bus.<\/p>"},{"title":"TIL: How you can Verify Your Hugo Blog on Mastodon","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-30-til-how-you-can-verify-your-hugo-blog-on-mastodon\/","pubDate":"Wed, 30 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-30-til-how-you-can-verify-your-hugo-blog-on-mastodon\/","description":"<p><strong>TIL: How you can Verify Your Hugo Blog on Mastodon<\/strong><\/p>\n<p>Mastodon is an open-source social media website gaining a lot of traction at the moment, thanks in part to what is happening at Twitter.\nOn Mastodon, we can verify a link on our profile is owned by us by linking back to Mastodon with a <code>rel=&quot;me&quot;<\/code>.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-11-30-til-how-you-can-verify-your-hugo-blog-on-mastodon\/images\/mastodon_settings.png\"\n        type=\"\"\n        alt=\"Settings\"\n        \n      \/><\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-11-30-til-how-you-can-verify-your-hugo-blog-on-mastodon\/images\/verification.png\"\n        type=\"\"\n        alt=\"Verification\"\n        \n      \/><\/p>\n<ul>\n<li>\n<ol>\n<li>Go to settings\/profile<\/li>\n<\/ol>\n<ul>\n<li>In my case, it is this, <a href=\"https:\/\/hachyderm.io\/settings\/profile\">https:\/\/hachyderm.io\/settings\/profile<\/a><\/li>\n<\/ul>\n<\/li>\n<li>\n<ol>\n<li>Find the verification link<\/li>\n<\/ol>\n<ul>\n<li>It will look something like <code>&lt;a rel=&quot;me&quot; href=&quot;https:\/\/hachyderm.io\/@majiy00&quot;&gt;Mastodon&lt;\/a&gt;<\/code>\n<ul>\n<li>Yours may look different if you are on a different Mastodon instance<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Copy this into our site\n<ul>\n<li>For example, in your footer <code>footer.html<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-go-html-template\" data-lang=\"go-html-template\"><span class=\"line\"><span class=\"cl\">  <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span> <span class=\"na\">style<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;display: inline-block; margin-left: 1em;&#34;<\/span><span class=\"p\">&gt;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    Powered by\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span> <span class=\"na\">href<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;https:\/\/gohugo.io\/&#34;<\/span> <span class=\"na\">rel<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;noopener noreferrer&#34;<\/span> <span class=\"na\">target<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;_blank&#34;<\/span><span class=\"p\">&gt;<\/span>Hugo<span class=\"p\">&lt;\/<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span> <span class=\"err\">&amp;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span> <span class=\"na\">href<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;https:\/\/github.com\/reorx\/hugo-PaperModX\/&#34;<\/span> <span class=\"na\">rel<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;noopener&#34;<\/span> <span class=\"na\">target<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;_blank&#34;<\/span><span class=\"p\">&gt;<\/span>PaperModX<span class=\"p\">&lt;\/<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>.\n<\/span><\/span><span class=\"line hl\"><span class=\"cl\">    <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span> <span class=\"na\">rel<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;me&#34;<\/span> <span class=\"na\">href<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;https:\/\/hachyderm.io\/@majiy00&#34;<\/span><span class=\"p\">&gt;<\/span>Mastodon<span class=\"p\">&lt;\/<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"k\">if<\/span><span class=\"w\"> <\/span><span class=\"na\">.Site.Params.goatcounter<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">        Analytics by <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span> <span class=\"na\">href<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;https:\/\/<\/span><span class=\"cp\">{{<\/span><span class=\"w\"> <\/span><span class=\"na\">.Site.Params.goatcounter<\/span><span class=\"w\"> <\/span><span class=\"cp\">}}<\/span><span class=\"s\">.goatcounter.com&#34;<\/span><span class=\"p\">&gt;<\/span>Goatcounter<span class=\"p\">&lt;\/<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"cp\">{{-<\/span><span class=\"w\"> <\/span><span class=\"k\">end<\/span><span class=\"cp\">}}<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"p\">&lt;\/<\/span><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"papermod\">PaperMod<\/h2>\n<p>If you are using the <a href=\"https:\/\/adityatelange.github.io\/hugo-PaperMod\/\">PaperMod<\/a> theme or similar.\nYou can make this change to the <code>config.yml<\/code>:<\/p>"},{"title":"TIL: How to Fix \"Overflowing\" Highlights in Hugo Code Blocks","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-27-til-how-to-fix-overflowing-highlights-in-hugo-code-blocks\/","pubDate":"Sun, 27 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-27-til-how-to-fix-overflowing-highlights-in-hugo-code-blocks\/","description":"<p><strong>TIL: How to Fix &ldquo;Overflowing&rdquo; Highlights in Hugo Code Blocks<\/strong><\/p>\n<p>I am using the <a href=\"https:\/\/reorx.github.io\/hugo-PaperModX\/\">PaperModX<\/a> theme, or at least a theme that is very close to that theme.\nI noticed an issue when I would try to highlight my code in code blocks. For example, if we had the following:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-markdown\" data-lang=\"markdown\"><span class=\"line\"><span class=\"cl\">```js {hl_lines=[1]}\n<\/span><\/span><span class=\"line\"><span class=\"cl\">const images = Array.from(document.querySelectorAll(&#34;.post-content img&#34;));\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\\```\n<\/span><\/span><\/code><\/pre><\/div><p>It would highlight line number the first line in the code block but just up to the width of the code block.\nSo if you scrolled to the right to see the rest of the code it would not be highlighted.<\/p>"},{"title":"TIL: How to Add Hugo Shortcode Snippets in VSCode","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-26-til-how-to-add-hugo-shortcode-snippets-in-vscode\/","pubDate":"Sat, 26 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-26-til-how-to-add-hugo-shortcode-snippets-in-vscode\/","description":"<p><strong>TIL: How to Add Hugo Shortcode Snippets in VSCode<\/strong><\/p>\n<p>Hugo <a href=\"https:\/\/gohugo.io\/content-management\/shortcodes\/\">shortcodes<\/a> are a great way to add functionality to our Hugo blog.\nHowever, I find them fiddly to add.<\/p>\n<p>So let&rsquo;s see how we can leverage VSCode snippets to make it easier to add shortcodes to our markdown files.\nFirst, open the command palette, then select <code>Snippets: Configure User Snippets<\/code>. In my case, I want to add snippets\nspecific to this project so I select <code>New snippets file for '&lt;project&gt;'<\/code>. Give it a name like <code>shortcodes<\/code>.<\/p>"},{"title":"How to Add Page Views to your Hugo Blog Posts Using Goatcounter","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-25-how-to-add-page-views-to-your-hugo-blog-posts-using-goatcounter\/","pubDate":"Fri, 25 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-25-how-to-add-page-views-to-your-hugo-blog-posts-using-goatcounter\/","description":"<p>In this post, we will go over how we can add a page view &ldquo;counter&rdquo; \ud83d\udc40 to our Hugo blog, so we can see how many views each of our posts\nhave had. We will do this using <a href=\"https:\/\/www.goatcounter.com\/\">Goatcounter Analytics<\/a>.<\/p>\n<p>Here is an example of what it may look like:<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-11-25-how-to-add-page-views-to-your-hugo-blog-posts-using-goatcounter\/images\/page_views.png\"\n        type=\"\"\n        alt=\"Page Views Example\"\n        \n      \/><\/p>\n<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Goatcounter Set Up<\/summary>\n  \n  This post assumes you have already created a Goatcounter account, <a href=\"https:\/\/www.goatcounter.com\/\">more information here<\/a>.\nAnd you have added Goatcounter analytics to your blog, <a href=\"https:\/\/haseebmajid.dev\/posts\/2022-11-20-til-how-you-can-add-goatcounter-to-your-hugo-blog\/\">see this post for more information<\/a>\n<\/details>\n\n<h2 id=\"page-views-partial\">Page Views Partial<\/h2>\n<p>First, create a new file in your partial folder, in my case, it will be <code>layouts\/partials\/page_views.html<\/code><\/p>"},{"title":"TIL: You Can Schedule Posts on Your Hugo Blog using Netlify and Gitlab CI","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-23-til-you-can-schedule-posts-on-your-hugo-blog-using-netlify-and-gitlab-ci\/","pubDate":"Wed, 23 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-23-til-you-can-schedule-posts-on-your-hugo-blog-using-netlify-and-gitlab-ci\/","description":"<p><strong>TIL: You Can Schedule Posts on Your Hugo Blog using Netlify and Gitlab CI<\/strong><\/p>\n<p>This post in fact will be a scheduled post I&rsquo;m writing it on the 20th of November but it will be published on the 23rd of November.\nAssuming we are using Netlify to deploy our website, what we will need to do is trigger a rebuild of our site every day using Gitlab CI.\nSince Hugo builds a static site to publish our content after a set date we will need to rebuild our site. So let&rsquo;s see how we can automate\nthat. Else the post won&rsquo;t be visible until I next make a commit to my main branch.<\/p>"},{"title":"TIL: You can add a custom domain to your Goatcounter site","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-22-til-you-can-add-a-custom-domain-to-your-goatcounter-site\/","pubDate":"Tue, 22 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-22-til-you-can-add-a-custom-domain-to-your-goatcounter-site\/","description":"<p><strong>TIL: You can add a custom domain to your Goatcounter site<\/strong><\/p>\n<p>When you create an account on Goatcounter and add a new site, you can view the analytics by going to <code>[sitecode].goatcounter.com<\/code>.\nFor example, <a href=\"https:\/\/haseebmajid.goatcounter.com\"><code>haseebmajid.goatcounter.com<\/code><\/a>. However, we can use a custom domain, to view your analytics.<\/p>\n<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Custom Domain<\/summary>\n  \n  You will need a domain, that you can control the DNS of to do the following!\n<\/details>\n\n<h2 id=\"goatcounter\">Goatcounter<\/h2>\n<p>We can do this by:<\/p>\n<ul>\n<li>First go to your Goatcounter site\n<ul>\n<li>i.e. <code>haseebmajid.goatcounter.com<\/code><\/li>\n<\/ul>\n<\/li>\n<li>Then go to <code>Settings<\/code><\/li>\n<li>Then <code>Domain settings<\/code> &gt; <code>Custom domain<\/code>\n<ul>\n<li>Add your domain\n<ul>\n<li>i.e. <code>stats.haseebmajid.dev<\/code><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>Press the <code>Save<\/code> button on the bottom left<\/li>\n<\/ul>\n<div style=\"position:relative;padding-bottom:calc(100% \/ 1.78)\">\n  <iframe\n    src=\"https:\/\/gfycat.com\/ifr\/InsignificantMemorableGreathornedowl\"\n    frameborder=\"0\"\n    scrolling=\"no\"\n    width=\"100%\"\n    height=\"100%\"\n    style=\"position:absolute;top:0;left:0;\"\n    allowfullscreen\n  ><\/iframe>\n<\/div>\n\n<h2 id=\"domain\">Domain<\/h2>\n<p>Finally, we need to go to our domain management tool, such as <code>namecheap<\/code> and add a new entry:<\/p>"},{"title":"TIL: How You Can Zoom in on Photos in your Hugo Posts","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-21-til-how-you-can-zoom-in-on-photos-in-your-hugo-posts\/","pubDate":"Mon, 21 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-21-til-how-you-can-zoom-in-on-photos-in-your-hugo-posts\/","description":"<p><strong>TIL: How You Can Zoom in on Photos in your Hugo Posts<\/strong><\/p>\n<p>You can see what we want to achieve in the GIF below:<\/p>\n<div style=\"position:relative;padding-bottom:calc(100% \/ 1.78)\">\n  <iframe\n    src=\"https:\/\/gfycat.com\/ifr\/MisguidedFondDingo\"\n    frameborder=\"0\"\n    scrolling=\"no\"\n    width=\"100%\"\n    height=\"100%\"\n    style=\"position:absolute;top:0;left:0;\"\n    allowfullscreen\n  ><\/iframe>\n<\/div>\n\n<h2 id=\"how\">How?<\/h2>\n<p>Add the following code to your Hugo blog in my case using the Papermod theme I add it to the <code>layouts\/partials\/extend_footer.html<\/code>.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-html\" data-lang=\"html\"><span class=\"line\"><span class=\"cl\"><span class=\"p\">&lt;<\/span><span class=\"nt\">script<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"na\">src<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/medium-zoom\/1.0.6\/medium-zoom.min.js&#34;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"na\">integrity<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;sha512-N9IJRoc3LaP3NDoiGkcPa4gG94kapGpaA5Zq9\/Dr04uf5TbLFU5q0o8AbRhLKUUlp8QFS2u7S+Yti0U7QtuZvQ==&#34;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"na\">crossorigin<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;anonymous&#34;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"na\">referrerpolicy<\/span><span class=\"o\">=<\/span><span class=\"s\">&#34;no-referrer&#34;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">&gt;&lt;\/<\/span><span class=\"nt\">script<\/span><span class=\"p\">&gt;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">&lt;<\/span><span class=\"nt\">script<\/span><span class=\"p\">&gt;<\/span>\n<\/span><\/span><span class=\"line hl\"><span class=\"cl\">  <span class=\"kr\">const<\/span> <span class=\"nx\">images<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Array<\/span><span class=\"p\">.<\/span><span class=\"nx\">from<\/span><span class=\"p\">(<\/span><span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">querySelectorAll<\/span><span class=\"p\">(<\/span><span class=\"s2\">&#34;.post-content img&#34;<\/span><span class=\"p\">));<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"nx\">images<\/span><span class=\"p\">.<\/span><span class=\"nx\">forEach<\/span><span class=\"p\">((<\/span><span class=\"nx\">img<\/span><span class=\"p\">)<\/span> <span class=\"p\">=&gt;<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"nx\">mediumZoom<\/span><span class=\"p\">(<\/span><span class=\"nx\">img<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nx\">margin<\/span><span class=\"o\">:<\/span> <span class=\"mi\">0<\/span> <span class=\"cm\">\/* The space outside the zoomed image *\/<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nx\">scrollOffset<\/span><span class=\"o\">:<\/span> <span class=\"mi\">40<\/span> <span class=\"cm\">\/* The number of pixels to scroll to close the zoom *\/<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nx\">container<\/span><span class=\"o\">:<\/span> <span class=\"kc\">null<\/span> <span class=\"cm\">\/* The viewport to render the zoom in *\/<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nx\">template<\/span><span class=\"o\">:<\/span> <span class=\"kc\">null<\/span> <span class=\"cm\">\/* The template element to display on zoom *\/<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">      <span class=\"nx\">background<\/span><span class=\"o\">:<\/span> <span class=\"s2\">&#34;rgba(0, 0, 0, 0.8)&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">    <span class=\"p\">});<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"p\">});<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">&lt;\/<\/span><span class=\"nt\">script<\/span><span class=\"p\">&gt;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>The highlighted line may need to change depending on how your blog is setup. For my blog using the\n<a href=\"https:\/\/github.com\/adityatelange\/hugo-PaperMod\">PaperMod<\/a> theme. This gets all the images on the page\n<code>.post-content img<\/code>.<\/p>"},{"title":"TIL: How you can add goatcounter to your Hugo blog","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-20-til-how-you-can-add-goatcounter-to-your-hugo-blog\/","pubDate":"Sun, 20 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-20-til-how-you-can-add-goatcounter-to-your-hugo-blog\/","description":"<p><strong>TIL: How you can add goatcounter to your Hugo blog<\/strong><\/p>\n<p>In this TIL post, we will go over how you can add Goatcounter to your Hugo Blog.\nGoatcounter is an open-source privacy-friendly analytics tool, an alternative\nto Google Analytics.<\/p>\n<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Goatcounter Account<\/summary>\n  \n  This post assumes you have already created a Goatcounter account,\n<a href=\"https:\/\/www.goatcounter.com\/\">more information here<\/a>.\n<\/details>\n\n<p>Luckily it is very easy to add Goatcounter to our blog. First, create a new <code>partial<\/code> HTML file. In my example, it will be at <code>layouts\/partial\/analytics.html<\/code>. However, you can call and place your file where ever you want, just remember it for later.<\/p>"},{"title":"TIL: You can use Use `yq` to Mass Edit Markdown Files","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-17-til-you-can-use-yq-to-mass-edit-markdown-files\/","pubDate":"Thu, 17 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-17-til-you-can-use-yq-to-mass-edit-markdown-files\/","description":"<p><strong>TIL you can use <code>yq<\/code> to mass edit markdown files<\/strong><\/p>\n<details\n  class=\"notice tip\"\n  open=\"false\"\n>\n    <summary class=\"notice-title\">yq<\/summary>\n  \n  <code>yq<\/code> is a tool similar to <code>jq<\/code> except it allows you to edit, JSON, XML and YAML.\nIt has a very similar syntax to parse and edit files as <code>jq<\/code> does.\n<\/details>\n\n<p>I was recently adding new open graph images to all of my blog posts. After creating these images and storing them\nnext to the post, where the structure looks like:<\/p>"},{"title":"Why I moved from Gatsby to Hugo for this blog?","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-17-why-i-moved-from-gatsby-to-hugo-for-this-blog\/","pubDate":"Thu, 17 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-17-why-i-moved-from-gatsby-to-hugo-for-this-blog\/","description":"<h1 id=\"about-this-site\">About This Site<\/h1>\n<p>This site was built with <a href=\"https:\/\/gohugo.io\/\">hugo<\/a> and the <a href=\"https:\/\/github.com\/hmajid2301\/hugo-PaperModX\">PaperModX Theme<\/a> (using a fork of a fork at the moment).<\/p>\n<p>I decided to go with an existing theme rather than creating my own this time, to one save time but also to give the\nsite a more consistent feel. I am no designer and I felt my last website (v3), really felt like a bunch of different\nwebsites thrown together. It was a great way to learn React, TailwindCSS and a bunch of other technologies.<\/p>"},{"title":"TIL: You can Hash `None` in Python? What?","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-15-til-you-can-hash-none-in-python-what\/","pubDate":"Tue, 15 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-15-til-you-can-hash-none-in-python-what\/","description":"<p><strong>TIL you can hash <code>None<\/code> in Python<\/strong><\/p>\n<p>Recently I saw some Python code which looked something like:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-python\" data-lang=\"python\"><span class=\"line\"><span class=\"cl\"><span class=\"n\">d<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"kc\">None<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;value&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"s2\">&#34;another_key&#34;<\/span><span class=\"p\">:<\/span> <span class=\"s2\">&#34;another_value&#34;<\/span><span class=\"p\">,<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"p\">}<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>It had never really occurred to me you could use <code>None<\/code> (null) as a key to a dictionary before.\nWhat this also meant is that <code>None<\/code> must be hashable as only hashable objects can be keys in a dictionary.\nThese objects include <code>strings<\/code>, <code>tuples<\/code>, <code>sets<\/code> but don&rsquo;t include <code>lists<\/code> as they are mutable and not\nhashable.<\/p>"},{"title":"TIL: About Conditional Gitconfigs","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-12-til-about-conditional-gitconfigs\/","pubDate":"Sat, 12 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-12-til-about-conditional-gitconfigs\/","description":"<p><strong>TIL you can have conditional sections in your <code>.gitconfig<\/code><\/strong><\/p>\n<p>As some of you may know, I keep my <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\">dotfiles<\/a> in a git repo.\nThe problem with this approach is that my email in my <code>.gitconfig<\/code> is set to <code>hello@haseebmajid.dev<\/code>.<\/p>\n<p>Where my config looks something like this:<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-ini\" data-lang=\"ini\"><span class=\"line\"><span class=\"cl\"><span class=\"k\">[user]<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">  <span class=\"na\">email<\/span> <span class=\"o\">=<\/span> <span class=\"s\">hello@haseebmajid.dev\n<\/span><\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"s\">  name = Haseeb Majid<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"c1\"># ...<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>However, when I am at work I need to use a different email to commit i.e. work email <code>haseeb@work.com<\/code> not my personal\nemail. So I was wondering how could I do that; one way would be to change the file locally and just not commit it.\nBut of course, that is not ideal.<\/p>"},{"title":"What is a TIL Post?","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-11-what-is-a-til-post\/","pubDate":"Fri, 11 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-11-what-is-a-til-post\/","description":"<h1 id=\"what-is-a-til-post\">What is a TIL post?<\/h1>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-11-11-what-is-a-til-post\/images\/til.jpg\"\n        type=\"\"\n        alt=\"TIL\"\n        \n      \/><\/p>\n<p>TIL - Stands for today I learnt. These posts will be shorts summaries of something I learnt &ldquo;today&rdquo;.<\/p>\n<p>The TIL posts have a low barrier to entry and are a lot easier to write. Therefore they should encourage me\nto post more often. In all my blog posts I try to post about things that I struggled to do. If I struggled\nto implement a feature or build something. It shows that there wasn&rsquo;t a tutorial or an easy example I could follow.\nSo then I usually decide to write my own, to make it easier for others. It also has a nice side effect of helping me remember the topic\nbetter.<\/p>"},{"title":"Using Dotbot with plugins","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-08-using-dotbot-with-plugins\/","pubDate":"Tue, 08 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-08-using-dotbot-with-plugins\/","description":"<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Previous article<\/summary>\n  \n  This article assumes you are familiar with dotfiles and Dobot.\nIf you want to know more about Dotbot <a href=\"https:\/\/haseebmajid.dev\/posts\/2022-10-15-how-to-manage-your-dotfiles-with-dotbot\">click here<\/a>\n<\/details>\n\n<p>In this article I will show you how you can use Dotbot plugins. We can use Dotbot plugins to run new directives such as <code>apt<\/code>.\nSo we can use the apt package manager, so install packages.<\/p>\n<details\n  class=\"notice note\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Tip<\/summary>\n  \n  One useful use case is when we setup on a new system we may want to make we have some packages installed like <code>vim<\/code> or <code>make<\/code>.\nWe can automate some of this with Dotbot and its plugins.\n<\/details>\n\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-11-08-using-dotbot-with-plugins\/images\/automate.png\"\n        type=\"\"\n        alt=\"Automate Meme\"\n        \n      \/><\/p>"},{"title":"How to Manage your Dotfiles with DotBot across Devices","link":"https:\/\/haseebmajid.dev\/posts\/2022-11-01-how-to-manage-dotfiles-with-dotbot-across-devices\/","pubDate":"Tue, 01 Nov 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-11-01-how-to-manage-dotfiles-with-dotbot-across-devices\/","description":"<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Previous article<\/summary>\n  \n  This article assumes you are familiar with dotfiles and Dobot.\nIf you want to know more about Dotbot <a href=\"https:\/\/haseebmajid.dev\/posts\/2022-10-15-how-to-manage-your-dotfiles-with-dotbot\">click here<\/a>\n<\/details>\n\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-11-01-how-to-manage-dotfiles-with-dotbot-across-devices\/images\/meme.png\"\n        type=\"\"\n        alt=\"Dotfiles backup meme\"\n        \n      \/>\nIf you are like me you have devices, such as personal desktop and a work laptop. These devices share some dotfiles but also have specific program and applications.<\/p>\n<p>For example:<\/p>\n<ul>\n<li>Personal Desktop: Linux<\/li>\n<li>Work Laptop: Windows (WSL)<\/li>\n<\/ul>\n<p>On Linux I use alacritty and in Windows I use Windows terminal I could copy all my dotfiles over and not worry\nabout which programs exist on which systems.<\/p>"},{"title":"My current VSCode Setup (Extensions and Settings)","link":"https:\/\/haseebmajid.dev\/posts\/2022-10-16-my-current-vscode-setup-extensions-and-settings\/","pubDate":"Sun, 16 Oct 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-10-16-my-current-vscode-setup-extensions-and-settings\/","description":"<p>Today I will go over my current VSCode setup covering both extensions and settings.<\/p>\n<details\n  class=\"notice warning\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">Out of date<\/summary>\n  \n  This article may be out of date, by the time you are reading this. It is accurate as of\n16th October 2022.\n<\/details>\n\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-10-16-my-current-vscode-setup-extensions-and-settings\/images\/vscode-meme.png\"\n        type=\"\"\n        alt=\"vscode meme\"\n        \n      \/><\/p>\n<h2 id=\"extensions\">Extensions<\/h2>\n<p>Here we will go over some extensions I find very useful:<\/p>\n<ul>\n<li>Full list of my <a href=\"https:\/\/gitlab.com\/hmajid2301\/dotfiles\/-\/blob\/6b83e990861654506e8ecc756af75cf431438a4a\/vscode\/extensions.txt\">plugins here<\/a><\/li>\n<\/ul>\n<h3 id=\"better-comments\">Better Comments<\/h3>\n<ul>\n<li>Link: <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=aaron-bond.better-comments\">Better Comments<\/a><\/li>\n<\/ul>\n<p>As the name implies it improves your comments. Makes them look nicer if you add certain annotations.\nSuch as adding <code>TODO<\/code> to the comment will turn the comment orange. See the image below:<\/p>"},{"title":"How to Manage Your Dotfiles With Dotbot","link":"https:\/\/haseebmajid.dev\/posts\/2022-10-15-how-to-manage-your-dotfiles-with-dotbot\/","pubDate":"Sat, 15 Oct 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-10-15-how-to-manage-your-dotfiles-with-dotbot\/","description":"<p>If you&rsquo;re like me you find yourself moving between multiple systems. Whether that be between my personal\ndesktop and my work laptop or distro hopping on Linux. See relevant meme below:<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2022-10-15-how-to-manage-your-dotfiles-with-dotbot\/images\/distro_hopping.jpg\"\n        type=\"\"\n        alt=\"Distro Hopping Meme\"\n        \n      \/><\/p>\n<details\n  class=\"notice info\"\n  open=\"true\"\n>\n    <summary class=\"notice-title\">What are dotfiles?<\/summary>\n  \n  <p>Many tools\/program store their configuration files as files on your machine.\nOn Linux you will often find these in <code>~\/.config<\/code> directory.<\/p>\n<p>Some common examples of dotfiles:<\/p>\n<pre><code>- .vimrc\n- .bashrc\n- .gitconfig\n<\/code><\/pre>\n\n<\/details>\n\n<p>I wanted to find an easy way to manage my dotfiles and share them between mutiple systems.\nI also wanted a easy way to install software\/tools I used between my systems.\nIntroducing <a href=\"https:\/\/github.com\/anishathalye\/dotbot\">DotBot<\/a>, a tool that provides an easy\nway to manage our dotfiles using VCS (git).<\/p>"},{"title":"Running Gitlab CI jobs in Docker using docker-compose","link":"https:\/\/haseebmajid.dev\/posts\/2022-08-08-running-gitlab-ci-jobs-in-docker-using-docker-compose\/","pubDate":"Mon, 08 Aug 2022 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2022-08-08-running-gitlab-ci-jobs-in-docker-using-docker-compose\/","description":"<p>Shameless plug: This is related to a EuroPython 2022 talk I am giving, <a href=\"https:\/\/haseebmajid.dev\/talks\/my-journey-using-docker-as-a-developer-tool\">My Journey Using Docker as a Development Tool<\/a>.<\/p>\n<p>For most of my common dev tasks, I&rsquo;ve started to rely on <code>docker<\/code>\/<code>docker compose<\/code> to run commands locally. I have also\nstarted using vscode&rsquo;s <code>.devcontainers<\/code>, to provide a consistent environment for all developers using a project.<\/p>\n<p>The main reason for this is to avoid needing to install dependencies on my host machine. In theory, all I\nshould need is a Docker daemon and a CLI (docker CLI) to interact with that Daemon. This also makes it\nfar easier for any new developer to start working on my project and get set up.<\/p>"},{"title":"Separate function handler modules when using Python Socketio","link":"https:\/\/haseebmajid.dev\/posts\/2021-12-31-separate-function-handler-modules-when-using-python-socketio\/","pubDate":"Fri, 31 Dec 2021 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2021-12-31-separate-function-handler-modules-when-using-python-socketio\/","description":"<p>In this article I will show you how you can have separate modules for your Socketio event handlers.\nRather than keeping them all in the same file.<\/p>\n<p>Hopefully this should be a relatively short article, lets get into it<\/p>\n<h2 id=\"main\">Main<\/h2>\n<p>In this example I will be using SocketIO alongside FastAPI, but you can easily change this code to be SocketIO\nonly. I also will be using a uvicorn to run the server.<\/p>"},{"title":"E2E tests with Gitlab CI services","link":"https:\/\/haseebmajid.dev\/posts\/2021-12-25-e2e-tests-with-gitlab-ci-services\/","pubDate":"Sat, 25 Dec 2021 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2021-12-25-e2e-tests-with-gitlab-ci-services\/","description":"<h2 id=\"background\">Background<\/h2>\n<p>This will be a slightly shorter article. In this article I will show you how I&rsquo;ve managed to do some\nend-to-end testing with Gitlab CI services.<\/p>\n<p>I&rsquo;m building a browser-based multiplayer game called Banter Bus. Banter Bus consists of three main components,<\/p>\n<ul>\n<li>gui: A SvelteKit based frontend the user will interact with to play the game<\/li>\n<li>core-api: A Socketio API written in Python<\/li>\n<li>management-api: A simple RESTful API written in Python (FastAPI)<\/li>\n<\/ul>\n<p>Now say I want to write some e2e Cypress tests, that will test all of these components interacting with each other.\nWhich mainly will look something like <code>gui -&gt; core-api -&gt; management-api<\/code>.<\/p>"},{"title":"Testing a socketio Web App written in Python","link":"https:\/\/haseebmajid.dev\/posts\/2021-12-23-testing-a-socketio-web-app-written-in-python\/","pubDate":"Thu, 23 Dec 2021 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2021-12-23-testing-a-socketio-web-app-written-in-python\/","description":"<p>In this article I will show you how you can test an async Socketio application in Python, where the ASGI server we are running is uvicorn.\nI will be referring to these tests as integration tests, though depending on who you ask they could be called E2E tests, system tests, slow test etc.\nWhat I am referring to is simply testing out the entire &ldquo;flow&rdquo; of a socketio event i.e. emitting an event from a client, then receiving it on the web service\nand for my actual projects interacting with an actual database.<\/p>"},{"title":"Testing a Gatsby application with Cypress on Gitlab CI","link":"https:\/\/haseebmajid.dev\/posts\/2021-03-22-testing-a-gatsby-application-with-cypress-on-gitlab-ci\/","pubDate":"Mon, 22 Mar 2021 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2021-03-22-testing-a-gatsby-application-with-cypress-on-gitlab-ci\/","description":"<p>In this blog post, we will go over how we can automatically test a Gatsby site end-to-end (e2e), using Cypress on Gitlab CI.<\/p>\n<h1 id=\"introduction\">Introduction<\/h1>\n<h2 id=\"gatsby\">Gatsby<\/h2>\n<p><a href=\"https:\/\/www.gatsbyjs.com\">Gatsby<\/a> is a static site generator (SSG) built upon React. It allows us to create &ldquo;blazing&rdquo; fast websites.\nIn this example, we will use a simple blog starter template available and add a Cypress test.<\/p>\n<h2 id=\"cypress\">Cypress<\/h2>\n<blockquote>\n<p>Fast, easy and reliable testing for anything that runs in a browser. - Cypress README<\/p>"},{"title":"How to create a Golang Web Application using Fizz","link":"https:\/\/haseebmajid.dev\/posts\/2021-01-19-how-to-create-a-golang-web-application-using-fizz\/","pubDate":"Tue, 19 Jan 2021 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2021-01-19-how-to-create-a-golang-web-application-using-fizz\/","description":"<h1 id=\"background\">Background<\/h1>\n<p>A bit of background before we start the article. When I develop a Python web service I use the\n<a href=\"https:\/\/github.com\/zalando\/connexion\">Connexion library created by Zalando<\/a>. It&rsquo;s a great library which is built on top of\nFlask. It uses an OpenAPI Specification (OAS) file to handle input validation and routing for you. Therefore reducing the boilerplate code you need to write.<\/p>\n<p>The main advantage of this is that we have a design-first approach to developing our API. We fully define the\nOAS then develop the code\/web service. This also keeps the OAS up to date, helping to mitigate the issue of the\ncode\/documentation getting out of date. Especially when you share the OAS with other people (clients) to use. The last\nthing you want to do is give them an out-of-date file.<\/p>"},{"title":"Golang & MongoDB with \"Polymorphism\" and BSON Unmarshal","link":"https:\/\/haseebmajid.dev\/posts\/2020-12-20-golang-mongodb-with-polymorphism-and-bson-unmarshal\/","pubDate":"Sun, 20 Dec 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-12-20-golang-mongodb-with-polymorphism-and-bson-unmarshal\/","description":"<p>Recently I&rsquo;ve been working on a new personal project called Banter Bus, a browser-based multiplayer game.\nI&rsquo;ve been working on a REST API to add new questions to the game. The API is built in Golang and uses\nMongoDB as the database. Since Golang is a strongly typed language, we will need to specify the structure of\nthe data we expect from the database. This can get tricky if the data varies, such as one field changing.<\/p>"},{"title":"What does yield do in Python","link":"https:\/\/haseebmajid.dev\/posts\/2020-11-30-what-does-yield-do-in-python\/","pubDate":"Mon, 30 Nov 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-11-30-what-does-yield-do-in-python\/","description":"<p>In this article, we will go over what the <code>yield<\/code> keyword is used for. We will also cover how you can use a <code>yield<\/code>\nwith a pytest fixture to allow us to &ldquo;teardown&rdquo; tests, after all of our tests have run. A common job being removing\ntest data from the database, so that next time your run the tests your tests won&rsquo;t fail. Due to the database being\nin a different (unexpected) state.<\/p>"},{"title":"How to add a ToC in Gatsby","link":"https:\/\/haseebmajid.dev\/posts\/2020-11-11-how-to-add-a-toc-in-gatsby\/","pubDate":"Wed, 11 Nov 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-11-11-how-to-add-a-toc-in-gatsby\/","description":"<p>A lot of people, I included, are using Gatsby to build their own blogs. One of the things I wanted to add to my blog\nwas a table of contents (ToC) \ud83d\udcdd. A ToC will show you all the headings of an article and when you click on a heading it&rsquo;ll\ntake you directly to that heading.\nIt&rsquo;s a nice little feature to have on your blog, which makes it easier for users to navigate and find the information\nthey are looking for.<\/p>"},{"title":"How DNS works with Docker","link":"https:\/\/haseebmajid.dev\/posts\/2020-10-27-how-dns-works-with-docker\/","pubDate":"Tue, 27 Oct 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-10-27-how-dns-works-with-docker\/","description":"<p>In this article, we will briefly go over what DNS (domain name system) is and explain how it is used in conjunction\nwith Docker \ud83d\udc33.<\/p>\n<h2 id=\"dns\">DNS<\/h2>\n<p>You can think of DNS like a phonebook, except instead of people&rsquo;s name and phone numbers, it stores domains names and\nIP addresses (this can be either IPv4 or IPv6). Where a domain name is used to identify resources i.e. <code>google.com<\/code> is a\ndomain name. This is how DNS works:<\/p>"},{"title":"How SOCKS proxies work and using ProxyChains","link":"https:\/\/haseebmajid.dev\/posts\/2020-10-10-how-socks-proxies-work-and-using-proxychains\/","pubDate":"Sat, 10 Oct 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-10-10-how-socks-proxies-work-and-using-proxychains\/","description":"<p>In this article, we will go over how you can use <code>proxychains<\/code> to proxy our traffic through a socks proxy.<\/p>\n<h2 id=\"background\">Background<\/h2>\n<p>Recently, like everyone else, I&rsquo;ve been working from home a lot more often. This means to access resources at work\nI need to use a VPN. However, to access some resources, such as production servers from my local machine, I need to\nuse a SOCKS5 proxy. Without using a SOCKS proxy, I would need to do something shown in the diagram below.<\/p>"},{"title":"How to source your Gatsby posts from another repo","link":"https:\/\/haseebmajid.dev\/posts\/2020-09-18-how-to-source-your-gatsby-posts-from-another-repo\/","pubDate":"Fri, 18 Sep 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-09-18-how-to-source-your-gatsby-posts-from-another-repo\/","description":"<p>In this article, we will go over how you can manage your markdown blog posts from another git repository (repo). Separate to the git repository for your Gatsby site.\nThis is the same process that I use to manage <a href=\"https:\/\/gitlab.com\/hmajid2301\/articles\">this repo<\/a>.<\/p>\n<p>So what this entails is the source code for my Gatsby site is in a repo called <code>portfolio-site<\/code> on Gitlab.\nThen I have another repo for all of my blog posts (in markdown) called <code>articles<\/code>. During build time of the\nGatsby blog, we will import the markdown files from our <code>articles<\/code> git repo and use it as a source of data for\nour Gatsby blog.<\/p>"},{"title":"Add an 'edit post' button to your Gatsby blog","link":"https:\/\/haseebmajid.dev\/posts\/2020-09-07-add-an-edit-post-button-to-your-gatsby-blog\/","pubDate":"Mon, 07 Sep 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-09-07-add-an-edit-post-button-to-your-gatsby-blog\/","description":"<p>In this article, we will look at how we can add an &ldquo;edit post&rdquo; button, to your Gatsby blog. When this button is clicked it will take the user to your markdown file, on github\/gitlab that was used to generate the blog post they are currently viewing.<\/p>\n<div style=\"position:relative;padding-bottom:56.25%;height:0;overflow:hidden\">\n  <iframe src=\"https:\/\/yewtu.be\/embed\/rALo_BzGKs8\"\n    style=\"position:absolute;top:0;left:0;width:100%;height:100%;border:0\" allowfullscreen><\/iframe>\n<\/div>\n\n<h2 id=\"setup\">Setup<\/h2>\n<p>Before we add the edit button to a Gatsby blog, let&rsquo;s set up a simple Gatsby site using the <code>Gatsby blog starter<\/code>.\nYou can skip this step and add the button to an existing site.<\/p>"},{"title":"How to auto create MRs in Gitlab","link":"https:\/\/haseebmajid.dev\/posts\/2020-08-31-how-to-auto-create-mrs-in-gitlab\/","pubDate":"Mon, 31 Aug 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-08-31-how-to-auto-create-mrs-in-gitlab\/","description":"<p>In this article, we will go over how we can use the <code>gitlab-auto-mr<\/code> CLI script I wrote to help automate your Gitlab\nworkflow. This is a very simple script you can use with Gitlab which will auto-create merge requests (MRs) every time you\ncreate a new branch on a project in Gitlab.<\/p>\n<h2 id=\"optional-git-feature-branches\">(Optional) Git Feature Branches<\/h2>\n<blockquote>\n<p>Feel free to skip this section if you are already familar with feature branch, skip to the <code>Gitlab Auto MR<\/code> section<\/p>"},{"title":"How to add offline search to a Gatsby blog","link":"https:\/\/haseebmajid.dev\/posts\/2020-08-20-how-to-add-offline-search-to-a-gatsby-blog\/","pubDate":"Thu, 20 Aug 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-08-20-how-to-add-offline-search-to-a-gatsby-blog\/","description":"<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2020-08-20-how-to-add-offline-search-to-a-gatsby-blog\/images\/main.gif\"\n        type=\"\"\n        alt=\"Search Gif\"\n        \n      \/><\/p>\n<p>Let&rsquo;s take a look at how we can add offline local search \ud83d\udd0d to a Gatsby blog. There are two main types of search we can\nuse an offline search like <code>elasticlunr<\/code> and external API search engines like <code>ElasticSearch<\/code>. These are typically more\nscalable but also more expensive.<\/p>\n<blockquote>\n<p>You can find more info <a href=\"https:\/\/www.gatsbyjs.com\/docs\/adding-search\/#reach-skip-nav\">here<\/a>.<\/p>\n<\/blockquote>\n<p>In this article, I will show you how to add offline search to your Gatsby blog using <code>elasticlunr<\/code>. This means your\nwebsite needs to be indexed locally and will increase the bundle size as this index needs to be loaded by the client but\nwith the scale and size of personal blogs (100s, not 1000s of blog post) this shouldn&rsquo;t make a massive difference.\nWe will also look at how we can add highlighting to our search results.<\/p>"},{"title":"TailwindCSS with CSS variables","link":"https:\/\/haseebmajid.dev\/posts\/2020-08-05-tailwindcss-with-css-variables\/","pubDate":"Wed, 05 Aug 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-08-05-tailwindcss-with-css-variables\/","description":"<p>TailwindCSS allows us to use pre-defined classes instead of defining our CSS styles. In this article, we will go over\nhow we can use Custom properties (sometimes referred to as CSS variables or cascading variables) with TailwindCSS.<\/p>\n<h2 id=\"setup\">Setup<\/h2>\n<p>First, follow the installation guide found <a href=\"https:\/\/tailwindcss.com\/docs\/installation\/#2-add-tailwind-to-your-css\">here<\/a>.\nThis will show you how you can add TailwindCSS to your current project. For part 2 I will assume you called your CSS\nfile <code>global.css<\/code>. This is the file that contains <code>@tailwind base;<\/code> etc.<\/p>"},{"title":"How to use Storybooks with MDX","link":"https:\/\/haseebmajid.dev\/posts\/2020-07-20-how-to-use-storybooks-with-mdx\/","pubDate":"Mon, 20 Jul 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-07-20-how-to-use-storybooks-with-mdx\/","description":"<p>This article (sort of) continues on from my previous article\n<a href=\"https:\/\/haseebmajid.dev\/posts\/2020-06-29-how-to-use-storybooks-gatsby-babel-tailwind-typescript-together\/\">How to use Storybooks, Gatsby, Babel, Tailwind, Typescript together<\/a>.\nIn this article, we will document our React components using Storybook with MDX.<\/p>\n<p>You can find an example project using this <a href=\"https:\/\/gitlab.com\/hmajid2301\/personal-site\/-\/tree\/e415420744b2a8f49eddaf2d3058b23c70f46638\/.storybook\">here<\/a>,\nyou can also find a <a href=\"https:\/\/storybook.haseebmajid.dev\/\">demo site<\/a> for said project.<\/p>\n<h2 id=\"prerequisite\">Prerequisite<\/h2>\n<p>Just to make sure everyone&rsquo;s on the same page let&rsquo;s follow the same steps to setup Storybook as we had in the last article.\nWe will use the latest versions of Storybook (v6) so we can access the latest features. We will go over how we can use\nthese features in the next article.<\/p>"},{"title":"How to use Storybooks, Gatsby, Babel, Tailwind, Typescript together","link":"https:\/\/haseebmajid.dev\/posts\/2020-06-29-how-to-use-storybooks-gatsby-babel-tailwind-typescript-together\/","pubDate":"Mon, 29 Jun 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-06-29-how-to-use-storybooks-gatsby-babel-tailwind-typescript-together\/","description":"<p>Recently I started to re-design my website, I decided to use this as an opportunity to learn some new technologies\nsuch as Gatsby, Tailwind. I also decided to try using Storybook. For this said project I used MDX to create my\nStorybook stories. In this article, I will show you how you can create Storybooks stories, for a Gatsby project\nwith TailwindCSS, Typescript using MDX.<\/p>\n<p>You can find an example project using this <a href=\"https:\/\/gitlab.com\/hmajid2301\/personal-site\/-\/tree\/e415420744b2a8f49eddaf2d3058b23c70f46638\/.storybook\">here<\/a>.\nYou can also find a <a href=\"https:\/\/storybook.haseebmajid.dev\/\">demo site<\/a> for said project.<\/p>"},{"title":"How to use Gitlab CI, Pytest and docker-compose together","link":"https:\/\/haseebmajid.dev\/posts\/2020-06-22-how-to-use-gitlab-ci-pytest-and-docker-compose-together\/","pubDate":"Mon, 22 Jun 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-06-22-how-to-use-gitlab-ci-pytest-and-docker-compose-together\/","description":"<p>On a recent project, I was working on, I wanted to test my web service using docker-compose where I can run and kill\nDocker containers used by the application and see how my web application reacts to that. In this article, we will\ngo over how you start docker containers using docker-compose from within Gitlab CI.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2020-06-22-how-to-use-gitlab-ci-pytest-and-docker-compose-together\/images\/main.png\"\n        type=\"\"\n        alt=\"main\"\n        \n      \/><\/p>\n<p>The diagram above is a visualisation of what we are trying to achieve. We want to spawn Docker containers using docker-compose\nfrom within our job. The spawning and destruction of these Docker containers will be done via our Python code. We can achieve\nthis by using dind (Docker in Docker). I have written a previous article on this topic which you can read more about\n<a href=\"https:\/\/haseebmajid.dev\/posts\/2020-05-01-how-to-use-dind-with-gitlab-ci\/\">here<\/a>. This article assumes you already somewhat familiar\nwith Docker, docker-compose and Pytest.<\/p>"},{"title":"Testing a Connexion\/Flask Application with Pytest","link":"https:\/\/haseebmajid.dev\/posts\/2020-06-09-testing-a-connexion-flask-application-with-pytest\/","pubDate":"Tue, 09 Jun 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-06-09-testing-a-connexion-flask-application-with-pytest\/","description":"<p>In this article, I will show you how you can test a Python web service that was built using <a href=\"https:\/\/github.com\/zalando\/connexion\/\">Connexion<\/a>\n(a wrapper library around Flask). We will go over how you can mock functions and how you can test\nyour endpoints. There are two related articles I have written in the past listed below. In the first\none we go over how to create a web service using Connexions, the same web service we will in this article.\nIn the second article I introduce how you can use <code>pytest-mock<\/code> and <code>pytest-flask<\/code> to test a Flask web\nservice.<\/p>"},{"title":"An example React Native Project Structure","link":"https:\/\/haseebmajid.dev\/posts\/2020-05-31-an-example-react-native-project-structure\/","pubDate":"Sun, 31 May 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-05-31-an-example-react-native-project-structure\/","description":"<p>In this article, I will go over an example project structure you can use for your React Native projects.\nThis of couse my opinion so feel free to tweak the structure to your needs\/preferences.<\/p>\n<ul>\n<li><a href=\"https:\/\/gitlab.com\/hmajid2301\/stegappasaurus\/\">Link to project<\/a><\/li>\n<li><a href=\"stegappasaurus.haseebmajid.dev\/\">Link to Docz Website<\/a><\/li>\n<\/ul>\n<h2 id=\"project-structure\">Project Structure<\/h2>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"cl\">.\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 android\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 app.json\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 App.tsx\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 babel.config.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 .buckconfig\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 CHANGELOG.md\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 CODE_OF_CONDUCT.md\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 CONTRIBUTING.md\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 docs\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 doczrc.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 .eslintrc.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 gatsby-node.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 .gitignore\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 .gitlab\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 .gitlab-ci.yml\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 .history\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 images\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 index.d.ts\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 index.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 ios\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 jest.config.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 LICENSE\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 metro.config.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 __mocks__\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 node_modules\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 package.json\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 prettier.config.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 public\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 react-native.config.js\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 README.md\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 src\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 __tests__\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 tsconfig.json\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 util\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u251c\u2500\u2500 .watchmanconfig\n<\/span><\/span><span class=\"line\"><span class=\"cl\">\u2514\u2500\u2500 yarn.lock\n<\/span><\/span><\/code><\/pre><\/div><h2 id=\"configs\">Configs<\/h2>\n<p>Let&rsquo;s briefly go over the various config files used in this project.<\/p>"},{"title":"How to make PrismJS code blocks editable","link":"https:\/\/haseebmajid.dev\/posts\/2020-05-10-how-to-make-prismjs-code-blocks-editable\/","pubDate":"Sun, 10 May 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-05-10-how-to-make-prismjs-code-blocks-editable\/","description":"<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2020-05-10-how-to-make-prismjs-code-blocks-editable\/images\/main.gif\"\n        type=\"\"\n        alt=\"demo\"\n        \n      \/><\/p>\n<p>In this article, we will go over how you can make PrismJS (syntax highlighted) code blocks editable.<\/p>\n<h2 id=\"introduction\">Introduction<\/h2>\n<p><a href=\"https:\/\/prismjs.com\/\">PrismJS<\/a> can be used to add syntax highlighting to code blocks on our website. For a persona\nproject of mine, <a href=\"composerisation.haseebmajid.dev\/\">composersiation<\/a> #ShamelessPlug :plug:, I needed to allow the user\nto paste in their own (docker-compose) yaml files. So let&rsquo;s take a look how we can let a user to first edit a code block\nand then re-run PrismJS to add syntax highlighting.<\/p>"},{"title":"How to use DinD with Gitlab CI","link":"https:\/\/haseebmajid.dev\/posts\/2020-05-01-how-to-use-dind-with-gitlab-ci\/","pubDate":"Fri, 01 May 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-05-01-how-to-use-dind-with-gitlab-ci\/","description":"<p>Like most developers, we want to be able to automate as many and as much of processes as possible. Pushing Docker\nimages to a registry is a task that can easily be automated. In this article, we will cover how you can use\nGitlab CI to build and publish your Docker images, to the Gitlab registry. However, you can also very easily\nedit this to push your images to DockerHub as well.<\/p>"},{"title":"Using React Hooks, Context & Local Storage","link":"https:\/\/haseebmajid.dev\/posts\/2020-04-05-using-react-hooks-context-local-storage\/","pubDate":"Sun, 05 Apr 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-04-05-using-react-hooks-context-local-storage\/","description":"<p>In this article, I will show how you can use React Context with React Hooks to store global state across a React app,\nthen store that state in local storage. This can be used for example to store light vs dark theme, then whenever the\nuser visits your website again they will have the same theme they last selected. Which leads to an improved experience.<\/p>\n<h2 id=\"structure\">Structure<\/h2>\n<blockquote>\n<p>Note: We will be using typescript<\/p>"},{"title":"How to Deploy Docz on Gitlab Pages","link":"https:\/\/haseebmajid.dev\/posts\/2020-03-28-how-to-deploy-docz-on-gitlab-pages\/","pubDate":"Sat, 28 Mar 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-03-28-how-to-deploy-docz-on-gitlab-pages\/","description":"<p>In this article I will show you how you can deploy a Docz website on Gitlab pages, using <code>.gitlab-ci.yml<\/code>.\nMost of this article should be applicable to Github pages as well.<\/p>\n<h2 id=\"docz\">Docz<\/h2>\n<p><a href=\"https:\/\/www.Docz.site\/\">Docz<\/a> is a tool powered by Gatsby, it aims to make it easier to document your project.\nIt uses a language called <code>mdx<\/code> which is like normal markdown with some extra features, i.e. <code>md + jsx<\/code>. The main\nadvantage of using Docz is you can render components &ldquo;live&rdquo;, if you put them with the <code>&lt;playground&gt;<\/code> tags. A basic\nexample may look like this:<\/p>"},{"title":"An Example Gitlab CI file for React Native Apps","link":"https:\/\/haseebmajid.dev\/posts\/2020-02-23-an-example-gitlab-ci-file-for-react-native-apps\/","pubDate":"Sun, 23 Feb 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-02-23-an-example-gitlab-ci-file-for-react-native-apps\/","description":"<p>A bit of backstory when I first started developing React Native apps, I found there weren&rsquo;t\nany good example of Gitlab CI files. So in this article, I will show you an example <code>.gitlab-ci.yml<\/code>\nfile you can use with your React Native app. You can of course tweak and makes changes as required by your\nproject.<\/p>\n<h2 id=\"cicd\">CI\/CD<\/h2>\n<blockquote>\n<p>Before we dive straight into the CI file itself, let&rsquo;s do a quicker refresher on some basic concepts. Feel free to skip this section if you are already familiar with CI\/CD, Git and Gitlab CI.<\/p>"},{"title":"Using React Native with Firebase Cloud Functions and Gitlab CI","link":"https:\/\/haseebmajid.dev\/posts\/2020-02-22-using-react-native-with-firebase-cloud-functions-and-gitlab-ci\/","pubDate":"Sat, 22 Feb 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-02-22-using-react-native-with-firebase-cloud-functions-and-gitlab-ci\/","description":"<p>In this article, we will talk about how you can use React Native with <a href=\"https:\/\/firebase.google.com\/docs\/functions\">Firebase Cloud Functions<\/a>.\nWe will also go over how we can automate the process of updating the cloud functions using <a href=\"https:\/\/docs.gitlab.com\/ee\/ci\/\">Gitlab CI<\/a>.<\/p>\n<p><a href=\"https:\/\/firebase.google.com\/\">Firebase<\/a> is a cloud-based platform developed by Google to aid in the development of Web and Mobile applications. It is tightly\ncoupled with the <a href=\"https:\/\/cloud.google.com\/\">Google Cloud Platform (GCP)<\/a>, so much so that there are certain actions you can\nonly do using the GCP GUI, such as increasing the RAM of your cloud function &ldquo;containers&rdquo;.<\/p>"},{"title":"Auto Toggle Dark Theme on your React Native App","link":"https:\/\/haseebmajid.dev\/posts\/2020-01-25-auto-toggle-dark-theme-on-your-react-native-app\/","pubDate":"Sat, 25 Jan 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-01-25-auto-toggle-dark-theme-on-your-react-native-app\/","description":"<p>In this article, I will show you how you can change the theme of your app depending on\nthe time of the day. We will change the theme of the app depending on if the sun has set or risen.<\/p>\n<h2 id=\"our-application\">Our Application<\/h2>\n<p>To get started we will create a new React Native app by running the following command,\n<code>react-native init ExampleApp --template typescript<\/code>.<\/p>\n<p><em>Note<\/em>: We are using path aliases so <code>~<\/code> is the same as saying <code>src\/<\/code>, this keeps the\nimport paths cleaner. More information <a href=\"https:\/\/haseebmajid.dev\/posts\/2019-12-01-better-imports-with-typescript-aliases-babel-and-tspath\/\">here<\/a> #ShamelessPlug.<\/p>"},{"title":"Using Tox with a Makefile to Automate Python related tasks","link":"https:\/\/haseebmajid.dev\/posts\/2020-01-13-using-tox-with-a-makefile-to-automate-python-related-tasks\/","pubDate":"Mon, 13 Jan 2020 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2020-01-13-using-tox-with-a-makefile-to-automate-python-related-tasks\/","description":"<p>In this article, we will go over how we can use a makefile and tox to automate various Python related tools.\nThis article assumes you are running bash (or equivalent).<\/p>\n<h2 id=\"tox\">Tox<\/h2>\n<p><a href=\"https:\/\/tox.readthedocs.io\/en\/latest\/\">Tox<\/a> is an automation tool used primarily to add in testing.\nOn the Tox website, it describes itself as<\/p>\n<blockquote>\n<p>tox aims to automate and standardize testing in Python. It is part of a larger vision of easing the packaging, testing and release process of Python software.<\/p>"},{"title":"Better Imports with Typescript Aliases, Babel and TSPath","link":"https:\/\/haseebmajid.dev\/posts\/2019-12-01-better-imports-with-typescript-aliases-babel-and-tspath\/","pubDate":"Sun, 01 Dec 2019 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2019-12-01-better-imports-with-typescript-aliases-babel-and-tspath\/","description":"<p>In this article, I will explain how you can use typescript aliases with Babel or TSPath.\nIf you have been using TypeScript\/JavaScript (TS\/JS) and have a nested folder structure,\nyou may well be used to seeing imports like so (using es6 style imports). This is sometimes\nreferred to as <strong>path hell<\/strong> and is a very common occurrence as your project grows in size.<\/p>\n<div class=\"highlight\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-js\" data-lang=\"js\"><span class=\"line\"><span class=\"cl\"><span class=\"kr\">import<\/span> <span class=\"nx\">moduleA<\/span> <span class=\"nx\">from<\/span> <span class=\"s2\">&#34;..\/..\/..\/moduleA&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><span class=\"line\"><span class=\"cl\"><span class=\"kr\">import<\/span> <span class=\"nx\">moduleB<\/span> <span class=\"nx\">from<\/span> <span class=\"s2\">&#34;..\/moduleB&#34;<\/span><span class=\"p\">;<\/span>\n<\/span><\/span><\/code><\/pre><\/div><p>These are called relative imports, as we are importing modules using paths relative\nto our current module\/file. As you can see, they can sometimes be very ugly and hard to work out\nwhere the module is we are importing. So sometimes you will use the wrong number of &ldquo;..\/&rdquo; etc.\nThere are a few tools we can use to help solve our problem.<\/p>"},{"title":"Add adaptive icons to your Android app","link":"https:\/\/haseebmajid.dev\/posts\/2019-11-09-add-adaptive-icons-to-your-android-app\/","pubDate":"Sat, 09 Nov 2019 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2019-11-09-add-adaptive-icons-to-your-android-app\/","description":"<p>In this article, we will go over how you can use add the new adaptive app icons to your Android app.\nIn his article I will be using a React Native project, so the structure of your Android app may vary.<\/p>\n<p>\n  <img\n    loading=\"lazy\"\n    src=\"https:\/\/developer.android.com\/guide\/practices\/ui_guidelines\/images\/NB_Icon_Mask_Shapes_Ext_02.gif\"\n    alt=\"Mask\"\n    \n  \/><\/p>\n<h2 id=\"adaptive-icons\">Adaptive Icons<\/h2>\n<p>Adaptive icons are a new feature introduced in Android 8.0 (API level 26). It allows your app icon\nto be displayed using multiple shapes across different devices and launchers, more\ninformation available <a href=\"https:\/\/developer.android.com\/guide\/practices\/ui_guidelines\/icon_design_adaptive\">here<\/a>.\nThe main advantage of using adaptive icons is so that we don&rsquo;t have to have to create multiple icons, i.e. round and square\nversions of your app icon. You provide two layers, a foreground and the background which is usually just a colour.<\/p>"},{"title":"Auto Publish React Native App to Android Play Store using GitLab CI","link":"https:\/\/haseebmajid.dev\/posts\/2019-10-09-auto-publish-react-native-app-to-android-play-store-using-gitlab-ci\/","pubDate":"Wed, 09 Oct 2019 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2019-10-09-auto-publish-react-native-app-to-android-play-store-using-gitlab-ci\/","description":"<p>In this article, I will show you how can automate the publishing of your AAB\/APK to the <code>Google Play Console<\/code>.\nWe will be using the <a href=\"https:\/\/github.com\/Triple-T\/gradle-play-publisher\">Gradle Play Publisher<\/a> (GPP) plugin to do\nautomate this process for us. Using this plugin we cannot only automate the publishing and release of our app,\nwe can also update the release notes, store listing (including photos) all from GitLab CI.<\/p>\n<p><strong>Note:<\/strong> In this article I will assume that you are using Linux and React Native version &gt;= 0.60.<\/p>"},{"title":"Using Gitlab CI to Publish an Android React Native App","link":"https:\/\/haseebmajid.dev\/posts\/2019-09-23-using-gitlab-ci-to-publish-an-android-react-native-app\/","pubDate":"Mon, 23 Sep 2019 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2019-09-23-using-gitlab-ci-to-publish-an-android-react-native-app\/","description":"<p>In this article I will show how you can use the GitLab CI with React Native to create a binary which can be published to the\nGoogle Play Store.<\/p>\n<h2 id=\"prerequisites\">Prerequisites<\/h2>\n<ul>\n<li><a href=\"https:\/\/play.google.com\/apps\/publish\/signup\/#EnterDetailsPlace\">Google Developers Account<\/a><\/li>\n<li>A working React Native Android project<\/li>\n<\/ul>\n<hr>\n<h2 id=\"keystore\">Keystore<\/h2>\n<p>First, we have to generate a keystore which we will use to sign our APK. To do this run the commands below,\nfollow all the instructions and keep the file safe.<\/p>"},{"title":"Creating a Simple RESTful App using OpenAPI, Flask & Connexions","link":"https:\/\/haseebmajid.dev\/posts\/2019-08-16-creating-a-simple-restful-app-using-openapi-flask-connexions\/","pubDate":"Fri, 16 Aug 2019 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2019-08-16-creating-a-simple-restful-app-using-openapi-flask-connexions\/","description":"<p>RESTful APIs are very popular at the moment and Python is a great language to develop\nweb APIs with. In this article we will go over a documentation first approach to building APIs.\nWe will be using Flask, Swagger Code-Gen (OpenAPI) and Connexions.\nI will go over an API\/documentation first approach to building a RESTful API in\nPython. Which will try to minimise the differences between what&rsquo;s defined in the API\nspecification and the actual API logic\nitself.<\/p>"},{"title":"How to add your own type definitions to DefinitelyTyped","link":"https:\/\/haseebmajid.dev\/posts\/2019-04-19-how-to-add-your-own-type-definitions-to-definitelytyped\/","pubDate":"Fri, 19 Apr 2019 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2019-04-19-how-to-add-your-own-type-definitions-to-definitelytyped\/","description":"<p>Recently I started using TypeScript (TS) with React Native. Now I won&rsquo;t be going over the benefits of\ntypescript in this article there are plenty for other articles that will explain the benefits (and drawbacks).<\/p>\n<p>TS is a superset of JavaScript (JS) so anything JS can do TS can do (and more). One of the main advantages of TS is\nit&rsquo;s strict type checking. JS is weakly typed which means variable and parameters can be of any type. One of the\nmajor downsides of this approach is in larger projects it can make code harder to follow and more bug prune. For\nexample, if you&rsquo;re expecting a variable to be an integer but turns out to be a string. Typescript makes bugs like\nthis much easier to catch because it is strongly typed and each variable and parameter is given a type.\nLets say you have the following function.<\/p>"},{"title":"DrawerNavigator, TabNavigator and StackNavigator with React Navigation","link":"https:\/\/haseebmajid.dev\/posts\/2019-03-04-drawernavigator-tabnavigator-and-stacknavigator-with-react-navigation\/","pubDate":"Mon, 04 Mar 2019 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2019-03-04-drawernavigator-tabnavigator-and-stacknavigator-with-react-navigation\/","description":"<p>In this article, we will create a simple React Native (with <a href=\"https:\/\/expo.io\/\">Expo<\/a>) application using React\nNavigation, for moving between screens\/pages within our app. We will create an app which had a Stack Navigator\nnested in a Tab Navigator, nested within a Drawer Navigator.<\/p>\n<p>This might sound a bit complicated so let&rsquo;s take a look gif below.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2019-03-04-drawernavigator-tabnavigator-and-stacknavigator-with-react-navigation\/images\/app.gif\"\n        type=\"\"\n        alt=\"GIF of App\"\n        \n      \/><\/p>\n<p>We have three main pages in the Drawer Navigator Home (purple), Settings (red) and About (blue) pages. Inside\nthe Home page, we have a Tab Navigator which has two pages, PageA (purple) and PageB (green). Within PageA we have a\nStack Navigator with two pages Main (purple) and Secondary (yellow).<\/p>"},{"title":"Theme your Expo\/React Native App with Redux and React Navigation","link":"https:\/\/haseebmajid.dev\/posts\/2018-12-23-theme-your-expo-react-native-app-with-redux-and-react-navigation\/","pubDate":"Sun, 23 Dec 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-12-23-theme-your-expo-react-native-app-with-redux-and-react-navigation\/","description":"<p>Recently whilst developing a React Native app (with Expo),\nI built a simple tab navigator using React Navigation library.\nI wanted to theme the app so that the header would change colour depending on which page you&rsquo;re on.\nFor example on the primary page it would be red and on the secondary page, when you change tabs, the\nheader would become blue.<\/p>\n<p>I ended up being able to do it using Redux. In this article, I will show you how you can theme your Expo\napp using Redux with React Navigation.<\/p>"},{"title":"Testing a Flask App with pytest-mock and pytest-flask","link":"https:\/\/haseebmajid.dev\/posts\/2018-12-15-testing-a-flask-app-with-pytest-mock-and-pytest-flask\/","pubDate":"Sat, 15 Dec 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-12-15-testing-a-flask-app-with-pytest-mock-and-pytest-flask\/","description":"<p>Pytest is a popular Python library used for testing. It is my preferred testing library because it requires less boilerplate code than the alternatives such as (the builtin) unittest, the built in testing library.\nIn this article, I will show you how you can use <code>pytest-flask<\/code> and <code>pytest-mock<\/code> to test your Flask app. These two\nlibraries are plugins for Pytest which build upon some of the features that Pytest provides us.<\/p>"},{"title":"Building A Simple Flask App with SQLalchemy and Docker","link":"https:\/\/haseebmajid.dev\/posts\/2018-11-24-building-a-simple-flask-app-with-sqlalchemy-and-docker\/","pubDate":"Sat, 24 Nov 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-11-24-building-a-simple-flask-app-with-sqlalchemy-and-docker\/","description":"<p>SQLAlchemy is an object-relational mapper (ORM), it allow us to interact with a database using Python functions and objects. For example, if we have a table called\n<code>Cats<\/code> we could retrieve every row with a command like <code>Cats.query.all()<\/code>. The main advantage of this is that it allows us to abstract away the SQL.<\/p>\n<p>Docker &#x1f433; allows us to quickly bring up a database within a Docker container, this means we don&rsquo;t have to set up and configure a database on our local machine. We can simply kill the Docker container when we are done with the database. In this article, I will show you how you can create a very simple RESTful API using Flask and SQLAlchemy, which will connect to a database running in a Docker container.<\/p>"},{"title":"Using Multiple Docker Containers to Setup Nginx, Flask and Postgres","link":"https:\/\/haseebmajid.dev\/posts\/2018-11-19-using-multiple-docker-containers-to-setup-nginx-flask-and-postgres\/","pubDate":"Mon, 19 Nov 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-11-19-using-multiple-docker-containers-to-setup-nginx-flask-and-postgres\/","description":"<h2 id=\"terminology\">Terminology<\/h2>\n<ul>\n<li>Docker Image: Is a file used to execute code in a Docker container, built from a set of instructions.<\/li>\n<li>Docker Container: Is a Docker image that is being executed or run.<\/li>\n<\/ul>\n<p>Docker &#x1f433; is a relatively new and exciting technology, Docker is a containerisation tool. The main benefits of using Docker is that you can\nuse the same environment for development, testing and production. Since Docker environments are consistent this means if the application works\nin the testing environment it will also work in production.<\/p>"},{"title":"Pytest with Background Thread Fixtures","link":"https:\/\/haseebmajid.dev\/posts\/2018-11-05-pytest-with-background-thread-fixtures\/","pubDate":"Mon, 05 Nov 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-11-05-pytest-with-background-thread-fixtures\/","description":"<p>Recently I had to test some of my Python &#x1f40d; &#x1f40d; &#x1f40d; code which required an external dependency and communicating by using TCP sockets &#x1f50c; . You can think of this dependency as essentially a database because it stored information. However, when testing my Python code, I couldn&rsquo;t rely on there always being a TCP server to send messages to.<\/p>\n<p>So I ended up creating a simplified mocked version in Python. This way I could run automated tests on my code without needing to either install\/rely on this server already existing there. Essentially I ended up creating a TCP server in Python, which would receive some input and respond how I would expect the real TCP server too.<\/p>"},{"title":"Running Expo\/React Native in Docker","link":"https:\/\/haseebmajid.dev\/posts\/2018-10-31-running-expo-react-native-in-docker\/","pubDate":"Wed, 31 Oct 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-10-31-running-expo-react-native-in-docker\/","description":"<p>Running Expo\/React Native in a Docker container can sometimes cause issues. In this example, I will be running\nDocker \ud83d\udc33 within a guest VM (Ubuntu) which will run on my host machine (Windows). My host machine will also\nbe running another VM as the Android emulator (Genymotion) for Expo to connect to. You can get a more\ndetailed post about how to connect two VMs together\n<a href=\"https:\/\/haseebmajid.dev\/posts\/react-native-with-virtualbox\/\">here<\/a>,\n#Plug \ud83d\udd0c\ud83d\udd0c\ud83d\udd0c. Since I&rsquo;ve set up networking on those two VMs already as far as Expo is concerned\nit might as well be running on the host machine (Windows). Also in this example, I will be testing\nthis on an Android device.<\/p>"},{"title":"Debugging A React Native WebView","link":"https:\/\/haseebmajid.dev\/posts\/2018-10-27-debugging-a-react-native-webview\/","pubDate":"Sat, 27 Oct 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-10-27-debugging-a-react-native-webview\/","description":"<p>The <em>core<\/em> logic of my React Native app involves using WebViews because I need to access the HTML5 canvas. Whilst\ndeveloping this code there are bound to be errors and issues with the WebView code. Figuring out how to debug\ncode within the WebView isn&rsquo;t so obvious.<\/p>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2018-10-27-debugging-a-react-native-webview\/images\/webview-dev-tools.png\"\n        type=\"\"\n        alt=\"Figure 1: Chrome Inspect for the WebView\"\n        \n      \/><\/p>\n<h2 id=\"option-1-chrome-inspect\">Option 1: Chrome Inspect<\/h2>\n<ul>\n<li>Start your Expo\/React Native app*.<\/li>\n<li>Open and chrome and then go to the following URL, <a href=\"chrome:\/\/inspect\">chrome:\/\/inspect<\/a>.<\/li>\n<li>Then click on the <em>inspect<\/em> button, click the top link to open the latest WebView, you should see something similar to Figure 2.<\/li>\n<li>You should see something similar to Figure 1. Now you explore the WebView like a normal web page.<\/li>\n<\/ul>\n<p><img\n        loading=\"lazy\"\n        src=\"https:\/\/haseebmajid.dev\/posts\/2018-10-27-debugging-a-react-native-webview\/images\/chrome-inspect.png\"\n        type=\"\"\n        alt=\"Figure 2: List of WebView\"\n        \n      \/><\/p>"},{"title":"Inheritance in SQLAlchemy (with Flask)","link":"https:\/\/haseebmajid.dev\/posts\/2018-10-18-inheritance-in-sqlalchemy-with-flask\/","pubDate":"Thu, 18 Oct 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-10-18-inheritance-in-sqlalchemy-with-flask\/","description":"<p>SQLAlchemy is an Object-relational mapping (ORM) made for the Python programming language. ORMs in theory allow\nprogrammers to abstract away SQL. In simple terms they allow us to interact with a database using purely Python\n(objects\/functions). I will be using the flask-SQLAlchemy extension for my examples.<\/p>\n<p>Each table is referred to as a model, each model is simply just a python class and each attribute of that class\nbecomes a column in an SQL table. The database is made up of multiple models. Just like with normal Python models\ncan inherit from other models and share attributes with the parent model. This is very useful if you going to\nhave models that will store similar types of data.<\/p>"},{"title":"Debugging React Native apps in WebStorm and Visual Studio Code","link":"https:\/\/haseebmajid.dev\/posts\/2018-09-07-debugging-react-native-apps-in-webstorm-and-visual-studio-code\/","pubDate":"Fri, 07 Sep 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-09-07-debugging-react-native-apps-in-webstorm-and-visual-studio-code\/","description":"<p>Visual Studio Code and WebStorm are two popular editors for developing React Native\/Expo apps. These editors have lots\nof useful features, such as syntax highlighting, git integration and auto completion. However working out to debug\nExpo apps can be a bit confusing.<\/p>\n<p>One of the main advantages of working in an editor\/IDE (let us be honest Visual Studio Code is pretty close to an IDE)\nis being able to use a debugger (and breakpoints) to go through your code line by line and see which part of your code\nis not running as expected. Debuggers can be a powerful tool when trying to remove bugs from your software, being able\nto stop your code at any point and check the state, analyse variables etc.<\/p>"},{"title":"React Native\/Expo with VirtualBox and Genymotion","link":"https:\/\/haseebmajid.dev\/posts\/2018-09-03-react-native-expo-with-virtualbox-and-genymotion\/","pubDate":"Mon, 03 Sep 2018 00:00:00 +0000","guid":"https:\/\/haseebmajid.dev\/posts\/2018-09-03-react-native-expo-with-virtualbox-and-genymotion\/","description":"<p>My home PC runs Windows for various conveniences, such as gaming. However, for development, I run an Ubuntu virtual\nmachine (VM) and Genymotion (on Windows) for testing my app. Genymotion also uses VirtualBox to run its Android\nemulators. So we work out how to let two VMs running on the same host communicate with each other\n(Ubuntu and Android Emulator).<\/p>\n<p><strong>Please Note:<\/strong> This will also work for VMWare Player.<\/p>\n<h2 id=\"solution\">Solution<\/h2>\n<p>There are a few networking options we can choose from when setting up a VM.<\/p>"}]}}