A Look Back on 7 Years of Automating Stuff
Tags: tinyproject, productivity
Published: 2023-12-12 07:53:41

---
title: A Look Back on 7 Years of Automating Stuff
published: true
date: 2023-12-04 00:00:34 UTC
tags: TinyProject,Productivity
canonical_url: https://jerrynsh.com/a-look-back-on-7-years-of-automating-stuff/
---

 ![A Look Back on 7 Years of Automating Stuff](https://images.unsplash.com/photo-1515162816999-a0c47dc192f7?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3wxMTc3M3wwfDF8c2VhcmNofDF8fHJlZmxlY3Rpb258ZW58MHx8fHwxNzAwMTg2Mzk2fDA&ixlib=rb-4.0.3&q=80&w=2000)

A little bit more than 7 years into my career, I thought it would be fun to pen down a summary post about my adventure in automating various tiny aspects of my life. Most if not all of the stuff here sprouted from my own problems and itches I needed to scratch.

This post will probably read more like a personal diary of the minor nuances that I encountered and the sweet minutes/hours that I managed to snatch back through automation.

On to the first one –

## Six Percent: Automating ASNB Purchases

_2018 – 2022_

![A Look Back on 7 Years of Automating Stuff](https://camo.githubusercontent.com/4e72c85701e6ebb6493f5b3465a850b4515f9695ccc2f940ef1ad32135e7ada7/68747470733a2f2f696d6775722e636f6d2f4959474d6f556f2e706e67)
_The startup window of the bot. This was the first thing that I've made that people actually use._

It all started with this Python script called "[six-percent](https://github.com/ngshiheng/six-percent)", a seemingly dumb bot to click buttons for some investment.

For context, ASNB a unit trust management company offers a [fixed-price fund](https://www.asnb.com.my/asnbv2_2funds_EN.php#hargatetap) (i.e. it can never go up or down!) that promised a sweet **6%** p.a. dividend back then. It’s virtually risk-free.

Well, there was a catch. The limited funds pool meant that it was selling like hotcakes — you had to keep retrying to snag those units. So, what did I do? I wrote this.

### Cost

As this turns out to be a tiny Windows executable, it didn’t really cost me any money to host or anything.

### Free lunch, literally

Beyond saving me countless mindless hours clicking like a headless chicken, I got a free thank-you meal out of it.

Fast forward to today, and I'm no longer actively using or maintaining the project. Over the years, there have been a few minor bug fixes here and there, but it's essentially retired. I can't guarantee that it still works, but man, it saved me so many hours.

### What did I learn

Today, I’ve become quite comfortable with any form of browser automation. If I can interact with it on the web, I can automate it. The script opened doors for tackling repetitive/mundane tasks, aiding in integration testing, etc.

> 💡 Years later, I stumbled upon [go-rod](https://github.com/go-rod/rod) which is significantly better in terms of ease of use and developer experience.

That aside, I did also learn other cool tricks like how to solve a CAPTCHA using [OCR](https://en.wikipedia.org/wiki/Optical_character_recognition) and [how to package a Python app using PyInstaller](https://jerrynsh.com/how-to-package-python-selenium-applications-with-pyinstaller/)!

## Todoleet: Daily Leetcode Questions in Todoist

_2021 – Present_

Back in early 2021, I started to solve the LeetCode Daily challenge as part of my morning routine. Quite frankly, it wasn’t exactly fun for me; it was necessary.

![A Look Back on 7 Years of Automating Stuff](https://jerrynsh.com/content/images/2023/11/image.png)
_My personal Todolist. Nope, I'm not attempting this one._

### How it works

Even though I've ditched my morning LeetCode routine, Todoleet is still up and running today.

Under the hood, it’s merely [a simple JS script](https://github.com/ngshiheng/todoleet/blob/main/index.js) that talks to the undocumented LeetCode API and then creates a new to-do task using the Todoist API.

If you're looking for the nitty-gritty, I've spilled the beans on [how I sync the Daily Leetcode Challenge to my Todoist](https://jerrynsh.com/how-i-sync-daily-leetcoding-challenge-to-todoist/).

### Cost

$0. The free Cloudflare Worker tier has got me covered! This solution costs 1 request per day and I didn’t need to store anything.

### Time saved

I did manage to save a few clicks (seconds) every day. _They all add up, I guess?_

### Any learnings?

This was my introduction to Cloudflare Worker. It paved the road for all the [other projects](https://jerrynsh.com/tag/cloudflare-worker/) I've tinkered with in my free time!

### Future plans

I did consider taking this to another level and listing it as a [Todoist integration](https://todoist.com/integrations). But, to be honest, I didn't care enough to make it happen.

## Burplist: Sipping on Craft Beer Savings

_2021 – Present_

Craft beers are delicious. There was just one hiccup — the price. Then I figured, wouldn’t it be great if I could have current and historical prices of all craft beers in Singapore, all in a place?

Now, instead of wrestling with 10+ websites for the best deals, a quick search from my database would do the trick. This saves me time and sanity.

![A Look Back on 7 Years of Automating Stuff](https://jerrynsh.com/content/images/2023/11/image-8.png)
_I was looking for some Dark Ale as I was writing this_

### How it works

Burplist is essentially a [web scraper built using Scrapy](https://github.com/ngshiheng/burplist/). It scours over 10 local online stores and e-commerce sites every morning (Singapore time), fetching craft beer prices and storing them in a Postgres database. As a result, I've amassed two years of historical craft beer price data in Singapore.

### Cost

Other than the ~$10/year for the domain name, [running Burplist has always been free](https://jerrynsh.com/how-i-built-burplist-for-free/). After Heroku phased out of its free tier plan:

1. The scraper Cron job was moved to [Northflank](https://northflank.com/)
2. The Postgres database is hosted on [Railway](https://railway.app/?referralCode=jerrynsh)
3. The website was moved to [Koyeb](https://www.koyeb.com/)

### Free beer for that Christmas

So, initially, I gave it a shot to make some money out of this. All I did was put it up for sale on Gumroad, but it didn't really catch on.

I also tried reaching out to a few companies through cold emails to see if they'd be interested in partnering up with some affiliate links, but only one replied — well, it didn’t work out either.

But hey, no big deal! It's all good because something awesome still came out of it! [Thirsty](https://www.thirsty.com.sg/), this local craft beer company, actually surprised me with this amazing package of craft beer for Christmas that year! I was over the moon.

![A Look Back on 7 Years of Automating Stuff](https://jerrynsh.com/content/images/2023/11/image-1.png)
_I got a box of delicious craft beers for Christmas that year_

### Any lesson learned?

This was quite a big one. I’ve had so much fun and learned so much from making this project. Burplist is the _fanciest_ web scraper that I’ve built thus far. I’ve written down some of the learnings in a [blog post](https://jerrynsh.com/5-useful-tips-while-working-with-python-scrapy/).

> 😂 Oh, and here's a quirky side effect: I’m now able to figure out whether a mega-sale/promotion is the real deal or just a clever markup with a discount disguise.

### Looking ahead

Future plans? Maybe migrate from Postgres to SQLite. Then, update the daily job to push the SQLite file directly to GitHub and present the data through something like [this nifty method](https://phiresky.github.io/blog/2021/hosting-sqlite-databases-on-github-pages/). Expected result? One less webserver to babysit. If this ever happens, I’ll probably write about it somewhere.

## Wraith: Automating Ghost Blog Backup

_2022 – Present_

![A Look Back on 7 Years of Automating Stuff](https://jerrynsh.com/content/images/2023/11/image-4.png)
_A screenshot of my terminal emulator_

At the start of my blogging journey, I didn’t really think too much about what would happen if this $6/month Droplet crashed. I mean, I had all my blog entries in Notion, so I figured "Meh, it wouldn’t hurt to copy-paste ~10 of them back if anything bad happens".

As time went on, the realization hit — losing all my data and whatnot now would really suck. So, the solution? Automate the backup. With the blog serving around 10k views monthly, any downtime or a prolonged `404` or `500` is something I'd rather avoid.

### What’s underneath

It’s a [pretty simple Bash script](https://github.com/ngshiheng/wraith/blob/ebefb095fa14ef4d5a5611a1eb3e6c4f70f559d3/backup.sh#L85) that does three things:

1. `ghost backup`
2. `mysqldump`
3. `rclone` to a remote drive (e.g. Dropbox, Google Drive, etc.)

This Bash script gets a weekly run in a Cron job, and it's as easy as that.

### Cost

$0. I didn’t have to pay for Dropbox; the free tier fits my needs just fine.

### Time saved

I mean, the alternative would be manually SSH-ing into my Droplet, running backup steps one by one — a process taking roughly about 5 minutes or less. So, that's the weekly saving of ~5 minutes.

### What did I learn

Picked up a few best practices for writing Bash script along the way. Besides that, I did learn about new tools like `expect`, `rclone`, and `pass` (the [Linux password manager](https://wiki.archlinux.org/title/Pass)).

### Future plans

Not a whole lot to be honest. Perhaps a backup restore script could be handy. Thought about moving passwords from plain text to using `pass`. But, that means users dealing with GPG + Pass CLI setup — an extra hurdle.

## Tournacat: Sync Esports Schedules to Google Calendar

_Started 2023_

I got tired of missing highly anticipated Dota 2 Esports matches, dealing with wonky time zones, and the mental gymnastics of remembering it all. Since Google Calendar is practically my second brain, I figured, why not sync upcoming matches straight into it?

![A Look Back on 7 Years of Automating Stuff](https://jerrynsh.com/content/images/2023/12/image-1.png)
_Month view of Google Calendar_

### Turning it into a micro SaaS

I started by sharing the Dota 2 calendar with friends. Then, a lightbulb moment — if it's handy for them, _maybe_ others would pay for it. And so, [D2GCal was born](https://jerrynsh.com/sync-dota-2-esports-matches-to-your-google-calendar/). Pay, and get a public link to the Google Calendar. Simple.

But wait — people are picky about their calendars. Some find it “noisy”, and some want a customized experience. Enter [Tournacat](https://workspace.google.com/marketplace/app/tournacat/1041160187344), supporting 10+ Esports titles (not just limited to Dota 2!), giving users the power to own and customize their calendars.

### Cost

~$10/year for now for the domain name.

Firstly, the website ([tournacat.com](https://tournacat.com/)) operates as a static site built using [Hugo](https://gohugo.io/). It's currently hosted using Cloudflare Pages which is free.

The [Google Workspace add-on](https://workspace.google.com/marketplace/app/tournacat/1041160187344) is built and runs on Google Apps Script (GAS) for free.

Lastly, Tournacat has an API server running on Cloudflare Worker. It fetches the upcoming Esports events from a data source. Running on Cloudflare Worker is currently still within the free tier limit but it won't be so for long.

The neat part? Tournacat doesn't store any user info. No names, no emails — nothing at all. This means that no database is needed.

### Revenue

![A Look Back on 7 Years of Automating Stuff](https://jerrynsh.com/content/images/2023/11/image-10.png)
_Lemon Squeezy payout page_

Today, Tournacat has about 90 users. In terms of paid subscriptions, it's made a tiny profit of _$40.23 in 11 months_.

Honestly, I never expected to rake in big bucks anyway. The goal was to cover growing worker usage costs. Any surplus? Well, that's coffee money.

### Lessons learned

The journey with Tournacat has been a blast. The realization that a handful of people want and use what you built yourself is an indescribable feeling.

This tiny venture has taught me [many valuable lessons](https://jerrynsh.com/i-built-a-google-calendar-add-on-heres-what-i-learnt/):

1. Developing on the GAS platform
2. Publishing of a Google Calendar add-on to Workspace
3. Working with payments and subscriptions
4. Crafting a micro SaaS

Besides, the journey also introduced me to the mundane world of social media marketing, which, isn't my cup of tea. On the flip side, I had an amazing time speaking to people about their feedback (feel free to ask me anything)!

Overall, I feel like the Esports landscape is shaped by a generation accustomed to abundant free entertainment and tools. Convincing people to spend money can be a tough sell.

### Any future plans?

There are plenty of tasks/tickets on the project board, but I'm taking it slow. The plan? I’ll just be working on minor improvements here and there unless specific user requests pop up.

Being a solo developer has its perks — the turnaround time for new requests is pretty quick. I've been able to incorporate feedback almost immediately (as long as it's somewhat reasonable).

Overall, the product feels pretty complete as it is.

## SGS Issuance Calendar: Automated T-Bill Tracking

_Started 2023_

Feeling the manual-checking fatigue for the Singapore MAS T-bill issuance calendar, I decided, "Why not automate this?" So, I crafted a schedule to run every month using Google Apps Script (GAS) and detailed the process in [this blog post](https://jerrynsh.com/creating-a-mas-t-bill-calendar/).

![A Look Back on 7 Years of Automating Stuff](https://jerrynsh.com/content/images/2023/11/image-6.png)
_T-bill announcement and auction dates are on my calendar!_

### How it Works

Under the hood, it's a small [GAS project written in TypeScript](https://github.com/ngshiheng/sgs-issuance-calendar). The script gets triggered every month; pings the MAS API, and then creates important dates (e.g. announcement/auction date) as Google Calendar events. Simple as that!

### Cost

$0. The best part about using GAS is that I don’t need to be bothered by the underlying infrastructure hassle. No fretting over scaling, upgrades, backups, availability — none of that. It just does its thing.

### Some lessons learned

This project brought some learnings to the table. I am now able to build GAS projects in TypeScript and delved into the world of writing unit tests for GAS. This newfound skillset later found a home in Tournacat's add-on UI codebase, which is also written in GAS.

### What's next?

I've added support for SGS and SSB calendars as well! For now, no concrete plans unless user feedback or GitHub issues come knocking. Two months in, and it's been serving me well.

## Closing Thoughts

The journey has been nothing short of fun. My approach to automating/building usually unfolds like this:

1. Identify my own pain point or problem (note it down immediately!); however small it may be. Look for quick wins!
2. Prefer leveraging what's already out there. Check if there's something in the market for it, like Zapier or IFTTT
3. If not, then roll up my sleeves and code/build
4. See if I can generalize the solution or approach
5. Write down the process somewhere
6. Rinse and repeat

### “Aren’t some of these side projects?"

Well, I guess. I just think the term feels so worn out at this point. It's like, they're more about automating some parts of my life. Sure, one of them is making coffee money monthly, a bit laughable. The whole idea of “hustling” just doesn't quite vibe with me. I've realized I just want to do things [just for fun. No, really](https://justforfunnoreally.dev/).

Thanks for sticking around! 🍻 Here's to more automation to come!