RSSAmplifier

Blog

Mahmud Ridwan (hjr265) on hjr265.me

Recent content in Mahmud Ridwan (hjr265) on hjr265.me

hjr265.meRSS feed ↗142 posts

Latest posts

Now

Software Engineer in Dhaka, Bangladesh 🇧🇩 Family Software Engineer / CEO at Furqan Software — Sep ‘15 - present Spending as much time as I can crafting Toph , the premier Bangladeshi sport programming platform Freelance software engineer Networks: Toptal and Upwork Strong Suits: Go, TypeScript, JavaScript, Node.js, Rust, Python, React, Svelte, PostgreSQL, MongoDB, Redis, RabbitMQ, Docker,…

Can AI Take a Software Engineer's Job?

I had an interesting exchange with a coding agent this evening. Are coding agents useful? Absolutely. But can it take a software engineer’s job? You tell me. Me: In .gitlab-ci.yml , can we set the workflow name only if the PLAYBOOK variable is set? AI: 1 2 3 4 5 workflow : name : 'Playbook ${PLAYBOOK}' rules : - if : $PLAYBOOK != '' - when : always The workflow.name only takes effect when…

My First Fully Agentic Coding Project: GitTop

I have been running Toph for over ten years. Somewhere along the way, I started wondering: what hours of the day do I actually work on it? Commit timestamps felt like the right place to look. A quick one-off script could answer the question, and there are Git stats tools that spit out HTML reports. But I thought: this could be a good excuse to build a TUI application. Something like htop, but for…

Resurrecting a 12-Year-Old Node.js Project With Claude Code

This weekend, I set out to get some high-resolution screenshots of zebra-algo (you may remember it as the now-defunct CodeMarshal or algo.codemarshal.org). My motivation was to document its design and features, as zebra-algo is a competitive programming contest platform I built back in 2014. The plan was straightforward: run it locally, open it in a browser, take the screenshots, and be done.…

Ditching MongoDB Text Indexes for Edge N-Grams

I like software that just works. If I type “North South” into a search box, I expect to find “North South University”. But if I type “North So”, I should still find it. Maybe not at the top, but it should be there. For a while, Toph’s institution search did not work that way. The Problem With MongoDB Text Indexes The original implementation used a MongoDB…

GitTop

GitTop is an htop-like TUI dashboard for Git repositories. It provides seven pages of insights: summary with braille charts, activity heatmaps, contributor rankings, branch comparisons, file statistics, release timelines, and a scrollable commit log with diff viewer and fuzzy search. It also includes a filter DSL for structured queries like author:"alice" and path:*.go .

Strangest AMD Ryzen 7950x Bug

I upgraded my primary computer to the AMD AM5 platform sometime in mid-2023. Before the upgrade, I had been using an Intel Core i7 4790 with 32 GB of RAM for about a decade. For the upgrade, I went with an AMD Ryzen 7950x with 128 GB of RAM. Given that my work lately has started to involve a lot of virtual machines, this upgrade was worth every bit. However, the upgrade came with a few annoyances.…

Trace

Trace is an interactive algorithm visualizer. It provides step-by-step animated visualizations for algorithms and data structures across graph theory, number theory, search, and sorting, with annotated source code that highlights in sync with each execution step.

μTools

μTools is a developer utility suite built with Rust and GPUI. It provides quick access to commonly needed conversion and formatting tools, including Base64 and HTML encoding/decoding, Unix timestamp conversion, JSON formatting, text diffing, and more.

All Our Customer Care Agents Are Busy at This Moment

It was the second week of August 2024. We realized that the television in our family space had suddenly stopped working. It would start, flash blue for a moment, and restart. If we left it running for a while, the boot logo would appear with parts of the panel garbled. This was no cheap, no-name, no-brand “smart” TV—at least that is what the salesperson told us when we bought it. It…

How Hard Can It Be: Use JavaScript to Close Web Browser Window After Print

So here is a simple JavaScript task I had to tackle for Toph : When a user clicks the Print button, open a new tab/window and activate the print dialog. Close the window when the user confirms the print or cancels the dialog. Attempt 1: Call window.close() Immediately After window.print() I used the onclick attribute on the Print button to open the page to be printed on a new tab/window.

Remmina SPICE SSH Tunnel Bug and a Workaround

I seem to come across the strangest of bugs. Bug Remmina SPICE over an SSH tunnel fails to handle keyboard-mouse interactions. I have set up several virtual machines with desktop operating systems using Libvirt on my primary computer. I can access these virtual machines over the network using Libvirt on my laptop. However, I wanted to use Remmina as the SPICE client since it is more configurable.…

#100DaysToOffload Milestone: The 100th Blog Post

And one hundred. I have posted 100 blog posts in the last 365 days. Why? Because I took on this #100DaysToOffload Internet challenge. My brain, trained on decades of video games, is tuned to enjoy challenges, no questions asked. But this challenge is very different from those social media challenges that die as fast as they become popular. How? First, the #100DaysToOffload challenge is not as…

Android Emulator Slow As a Snail; Reason BTRFS

I have been writing software professionally for over a decade. I have been writing software for even longer than that. This week was the first time I wrote an Android program. Some journey it was. But that is a story for another day. Today, in this blog post, I want to share a strange issue I encountered with Android Emulator and a fix. If you are using BTRFS, you probably have copy-on-write (COW)…

Check If a WireGuard Connection Is Up

I have several scripts and automation on my primary computer at home that can run when connected to the local area network of my workspace through a WireGuard connection. These scripts are for routine tasks for my servers at my workspace, like backing them up to remote storage. When the WireGuard connection is not running, the scripts fail at different points. I wanted the scripts to fail right…

Scanning a Website for Broken Links in Go

Yes, I know there are paid and free tools for doing this. And yes, I know there are tools for this that I can run locally. But this exercise allowed me to try out the well-designed Go package github.com/gocolly/colly . Colly is a web scraping framework for Go. Here is how I used it to quickly scan my website (the one you are on right now) for broken links. First I defined a type for links to check…

When Was the Last Time Technology Blew Your Mind?

I read a blog post by Kev Quirk this morning. When Was the Last Time Tech Blew Your Mind? It was a refreshing read. The world has come a long way as far as technology is concerned. But I think somewhere along the lines, the definition of innovation changed. I upgraded my desktop computer a couple of months ago. Before the upgrade, I used an Intel CPU from 2014 with as much RAM as the platform…

Go Web Server for Remotely Powering on a Desktop Computer With a Raspberry Pi

Last month, I wrote a blog post on how to use a Raspberry Pi and a 5V 2-channel relay to remotely power on or reset a desktop computer. Powering on a Desktop Computer Remotely With a Raspberry Pi To keep the blog post simple, I used the gpio command to interact with the GPIO pins on the Raspberry Pi. That works well. But by deploying a little web server you can have an easier user interface to…

7 Useful io.Reader and io.Writer Wrappers in Go

Whenever I think about Go in comparison to other programming languages, the first thing that comes to my mind is how Go simplifies the concepts around concurrency and writing concurrent programs. After all, concurrency is one of the features touted on the homepage: Built-in concurrency and a robust standard library But there is something else that Go simplifies and makes it very easy to wrap…

Forwarding a Port Over SSH in Go

In the day and age where Kubernetes is the go-to tool for orchestrating your applications on the cloud, I have been spending time building Bullet . I enjoy working on this tool, building out features for it little by little. And it also allows me to learn so many details. For example I just added the ability to forward ports from the remote server to the local over SSH. Bullet, being built using…

Strange Hugo Bug and How to Work Around It

I was about to deploy my site with the latest blog post this morning and found Hugo broken. Or, my Hugo config.toml is broken. It depends on how you want to look at it. I ran hugo deploy and bam! I see an internal template error. ERROR render of 'taxonomy' failed: template: _internal/_default/rss.xml:3:9: executing '_internal/_default/rss.xml' at <site>: can't evaluate field email in type string…

Serving JSON in Go with http.ServeContent

I know many will start with something like Gin whenever they are working on a JSON/HTTP-based backend in Go. I, not entirely sure if the minority, try to stick to Go&rsquo;s built-in net/http package and, at most, use Gorilla Mux in most of my Go projects. And so serving something simple like JSON is no different from the package&rsquo;s point of view as any other content type: whatever it is,…

Editing an SVG Icon to Be Resize-friendly

This blog post is about something that I think I have absolutely no expertise in: graphics. But that also makes exploring this field and the aha moments much more rewarding. A few weeks ago, I was working on adding an icon to the Toph Printd executable. I started to look for a suitable vector image on a paid vector icon and sticker repository I subscribe to. I found one that I liked.

Testing a Go Package That Depends on Redis

Redsync, one of my open-source Go packages, implements a distributed lock using Redis. It is an implementation of the Redlock algorithm . This Go package has tests that run against multiple real Redis servers. And it is an example of how you can use the TestMain function to customize your Go tests. The TestMain function , if defined in your Go tests, will allow you to run the Go code before and…

Tracking io.Copy Progress in Go

If you are writing Go code for any period, you must have used the io.Copy function. It takes an io.Writer and an io.Reader and copies everything from the reader to the writer until it reaches the end of file (EOF). The function returns the number of bytes copied and an error (if any, other than io.EOF ). But this function blocks until the copy completes. How do you track the progress of io.Copy ?

Responsive Activity Chart With Chart.js

A few weeks ago I worked on improving the activity chart shown on Toph profiles . Among adding legends and tweaking the look and feel of the chart, I paid some attention to how the chart behaves in terms of responsiveness. Chart.js has built-in responsive features. But in this case, it meant the chart would scale as a whole. What I wanted instead is for the number of columns to increase/decrease…

Multi-threaded Downloads in Go

The word multi-threaded here is an artifact of how download managers in the past worked. The idea is to download a large file in parts, in parallel, over multiple TCP streams at once. In certain circumstances this can speed up the download significantly. Let&rsquo;s start with a naive way of downloading a file in Go: 1 2 3 4 5 6 7 8 9 10 11 12 // Error handling omitted for brevity. // Perform a…

Building Advanced Search With Go and MongoDB

I like software that allows advanced search. Advanced search is where you can use flags to indicate what you want. Take email software as an example. It may allow you to enter from:Bloo to:Mac subject:Imagination and find all emails that were sent from Bloo to Mac and has the word &ldquo;Imagination&rdquo; in the subject line. But how do you implement something like this in Go? That is what this…

Backing up Self-hosted GitLab With Ansible

I have been making software for over a decade now. And one thing I have learned to love through this is automation. After all, it is only a programmer who will spend hours automating a task that takes a few minutes to do. There are good reasons for this. I have a self-hosted GitLab instance for Furqan Software . And if you are self-hosting tools and services, the critical thing to do after…

JavaScript window.close Won't Close the Window

I learned something new today. In JavaScript within the web browser, window.close will not close the window if it was not opened using window.open or is a top-level window (or tab) with at one history entry. That is what the documentation of window.close says. It got in the way. I was adding a page endpoint that I would link to. The link would open the page in a new tab with target="_blank" . And…

Adding Anchor Links Next to Headings in Hugo

I like that the Markdown renderer in Hugo automatically adds an id attribute to the headings in the content. This allows you to link to a specific section in a long article. But, I wanted to make it easy for people to get that link. Hugo doesn&rsquo;t do that by default, but makes it very easy to do with Markdown render hooks. By using the following as the render hook for headings, I am able to…

Setting Up Prometheus DNS-SRV Discovery with Terraform and DNSimple

If you are using Prometheus to collect metrics from your server, and you don&rsquo;t have a static set of servers, then you should set up automated discovery. There are many ways you can set up automated discovery in Prometheus. However, one of my preferred vendor-agnostic ways of doing this is to use DNS-SRV records. How does it work? Let&rsquo;s say you are using Terraform to manage your…

Waiting for an HTTP Service in GitLab CI/CD

Last weekend, I was setting up a Cypress test pipeline in GitLab for Toph for the 5th time. I have no idea why this pipeline keeps breaking over time. It&rsquo;s like bread left in the open. Cypress is such a fantastic end-to-end testing tool. But it seems to need a lot of extra love . Something that I needed to do was, in the CI/CD script, wait for Toph to start handling HTTP requests before…

SOCKS Proxy Over SSH

To test some of Toph&rsquo;s IP-based access control features, I needed to access it from a few different IP addresses than mine. I thought I finally needed to get one of those VPN subscriptions YouTube content creators keep rambling about. Fortunately, I remembered an easier way to do this. You see, it is possible to run a SOCKS proxy that tunnels your connection over SSH. And it is built right…

Are There Three Types of #100DaysToOffload Challengers?

A couple of weeks ago, I wrote my second #100DaysToOffload milestone blog post . I mentioned how I feel like a remnant characteristic of my days in the university has played a role in taking this challenge. I have been writing more frequently as I am nearing the end of the challenge. It got me wondering: are there three types of #100DaysToOffload challengers? I took a quick look at some of the…

Uploading Files Over SSH in Go

If you access servers remotely over SSH connections, you are bound to have come across scp . It is what you use to upload files to these remote servers. If you want to programmatically upload files like scp over an SSH connection to a remote server using Go, then you can use an ssh.Client : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // Error handling omitted for brevity. func…

Steam Link Black Screen on a Retro Pie Raspberry Pi 4

Last night, I encountered a strange issue setting up Steam Link on a Raspberry Pi running Retro Pie. Here is my attempt at a proper description of what I was seeing. After installing Steam Link using Retro Pie&rsquo;s package manager and rebooting the Raspberry Pi, I could see &ldquo;Ports&rdquo; show up on the Emulation Station. Inside was &ldquo;Steam Link&rdquo;. I could start Steam Link just…

Synchronization Constructs in the Go Standard Library

Go provides sync.Mutex as its implementation of a mutual exclusion lock. However, it is not the only synchronization construct that is a part of the standard library. This blog post will look at four synchronization constructs that we can use instead of a sync.Mutex . Counter You may often see code using a sync.Mutex to synchronize access to a counter variable from multiple goroutines. Like this:…

Powering on a Desktop Computer Remotely With a Raspberry Pi

I access my primary computer remotely for various reasons. Take playing video games using Steam Remote Play, for example. I have a Windows virtual machine with a GPU passed through. With Steam running on it, I can connect from my phone, my laptop, or any device with the Steam Link app and play remotely. For games that are not on Steam, I can use Moonlight. But imagine the frustration when the…

Serving hjr265.me From an S3-like Bucket Using a Caddy Module

I serve hjr265.me from an S3-like bucket hosted on Linode Object Storage. I have a Caddy instance that serves some of my Hugo-built websites, including this one. I use Hugo&rsquo;s deployment function and s3cmd to deploy these websites. Why Both? Hugo&rsquo;s deployment function uses the blob package from the Go Cloud Development Kit . This package comes with a limitation by design. It cannot set…

Switch Monitor Input from Linux Command Line

For the longest time, I have looked at computer monitors as these dumb devices. All they do is turn video signals into colours on the screen. I was out of touch with the progress. Most modern computer monitors come with what is known as DDC/CI. It may be disabled by default, so you need to enable it using the monitor&rsquo;s on-screen display (OSD) settings. Then, use a tool like ddcutil to switch…

Making a Real-time "Last N Days" Leaderboard with MongoDB Aggregation Framework

On Toph, there is a leaderboard of top solvers . Without any filters, this leaderboard shows the list of programmers who solved the most programming problems in the last seven days. Toph updates the leaderboard in real-time. There are a few ways to build a leaderboard like this one. The Naive Way The easy way is to run a daily or hourly cron that aggregates all the solutions submitted over the…

Windows Is Weird

I know we could list a thousand reasons why Windows is weird. But this particular reason is my favourite. Here are the N steps to my favourite Windows 10 weirdness: Copy the URL to this blog post. https://hjr265.me/blog/windows-is-weird/ Paste the URL in a Notepad window. You see the entire URL to this blog post. Good. Open File Explorer. Right-click on an empty area in the window. Click on New ›…

Show a Log Throbber in Terminal with Go

Show a Log Throbber in the Terminal with Go A long-running program made to run in a terminal window should indicate what it is doing. Judicious logging is the first step. While developing Printd for Toph, we needed a way to indicate the program status without outputting loglines repeatedly. Printd, a print server daemon, waits for print requests from Toph and prints out the contents of the request…

Not a "High-rated" Person

I came across a post in a competitive programming community. The post read: Always felt like [competitive programming] is no different from any other sport. Trying to get to the top in any sport requires the ability to keep being persistent in your work irrespective of the situation and what people say. [&hellip;] I personally have trained myself so far so that I do the work irrespective of any…

Gnome Not Reporting Bluetooth Earbuds Battery? Enable the D-Bus Interface

I use one of these true wireless Edifier earbuds. I noticed how Android reports the battery level of these earphones. But Gnome doesn&rsquo;t. Turns out, you need to enable the experimental D-Bus interface in the Bluetooth daemon on Linux for Gnome to know the battery level of the connected wireless earbuds. On Arch Linux (which I use, btw), I had to modify /etc/bluetooth/main.conf and set:…

#100DaysToOffload Milestone: The 67th Blog Post

It is my second milestone blog post of the #100DaysToOffload challenge. I posted my first milestone blog post on September 3, 2023. I will keep this one short. But I will say that I have posted as many #100DaysToOffload blog posts in the last 43 days as I have since I started the challenge. It is probably a remnant characteristic of my days in the university. Something I should work on changing.…

10 Forms of Bash Shell Parameter Expansion

If I look at my search history with the word &ldquo;bash&rdquo; in it, the most frequently searched phrases turn out to be like &ldquo;trim suffix bash&rdquo; and &ldquo;set bash variable if empty&rdquo;. It seems I write Bash scripts frequently enough to need these, but not frequently enough to remember these simple Bash shell parameter expansion forms. In this blog post I am going to keep a list…

Parsing Social Media URLs in Go With Slinky

Toph now allows programmers to show up to 5 social media URLs on their profile pages. Instead of showing the entire URL, I wanted to show the important bits from the URL. Screenshot of a profile panel from Toph To do that, I had to parse the social media URLs and extract information like the username or profile ID (when it is a GitHub, Twitter, LinkedIn, Facebook, etc. profile URL) or the instance…

Fixing Creality CR-10 Smart Touch Screen Orientation Issue

The Creality CR-10 Smart is a very sensitive 3D printer, especially when updating firmware. Are you using an SD card that is too small? The printer won&rsquo;t update. Too large? Again, the printer won&rsquo;t update. You formatted it to FAT32 but used an allocation size that isn&rsquo;t exactly 4096 KB. Tough luck: the printer won&rsquo;t update. You successfully updated the firmware to CR-10…