My new availability page using the status tool

TL;DR: I wrote a simple tool to publish my availability status on my website. You can find it here, or check the source code here.

I built a self-hosted backend service to automatically sync my GitHub profile status with a calendar. As I was working on it, I decided to also use it to publish my availability on this site based on my personal calendar.

I wanted to use this as an opportunity to experiment with LLM-driven development and see how it fares in production. In fact, to me, this was the highlight of the project.

I used copilot CLI, gemini CLI, codex CLI and opencode to write all of the code.

The first prompt

For the tech-stack, I chose Go as the programming language, and pebble as the datastore. This made sense to me because I set some tight constraints early on:

I wrote a prompt and let copilot bootstrap something I could run end-to-end. I specified the tech stack including the specific libraries I wanted to use and the above constraints and let it figure out the rest including architecture.

Deploying the app

The next step was to make sure I could actually run the app and deploy it to my personal single-node k3s cluster. content/posts/2026-05-10-the-status-tool.md I packaged the application as a docker image, wrapped it in a helm chart, and setup CI to build these artifacts via GitHub actions.

With the above in place, deploying the workload to my cluster was super simple since I already had an existing flux CD setup.

O(1) R/W operations

Like I mentioned at the start, the tool has two features:

  1. status: use my “status” calendar to update my status on GitHub
  2. availability: use my personal calendar to publish my availability to this site.

The status feature is very simple and sits between the “status” calendar and GitHub.

  flowchart LR
    App["status app"] -->|poll| iCal[Status iCal]
    App               -->|update status| GitHub

The availability feature has more going on and sits between my personal calendar feed and my static website’s build step.

  flowchart LR
    App      --> Holidays[gov.uk holiday API]
    App["status app"] -->|poll| PersonalICal["Personal iCal"]
    App      --> API["/api/availability"]
    App      --> CFDeploy[Cloudflare Deploy]
    CFDeploy --> Hugo[Hugo build]
    Hugo     --> API
    Hugo     --> CFPages[Cloudflare Pages] 

Like you can see, both use-cases essentially have two loops. One to fetch data from sources, and another to publish to targets.

  flowchart LR
    SourceLoop["Source Loop"] -->|raw-data| PebbleRaw["pebble_raw"]
    PebbleRaw -->|compute| PebbleComputed["pebble_computed"]
    TargetLoop["Target Loop"] --> PebbleComputed 

I ended up implementing O(1) reads and writes by pre-computing the data needed for the read-path.

Since I just need to store the latest data, implementing O(1) reads and writes was trivial and an embedded key-value database like pebble was all I needed.

Real-time syncing

You could argue that aiming for O(1) R/W is overkill for something of such a low scale, but I wanted to architect it this way just because I could. And I saw no downsides to doing it.

You could also argue that a better approach would be to listen to events on the Google Calendar API and respond to them in realtime. I considered this and felt like setting up the Google API integration (which requires a Google Cloud Project) and then maintaining it was just not worth it.

Given that this is just a personal project that doesn’t really benefit anyone including me, I figured my GitHub status and my published availability being a little out of date should be acceptable.

Config driven behavior

I’ve also built the entire app to be config-driven, to make it easy to tweak without any code changes.

For example, I can configure my working hours, availability blocks, and bank holidays and it’ll deduce my availability automatically.

 1# sample config
 2availability:
 3
 4  # Ordered availability windows
 5  blocks:
 6    - name:  All day
 7      start: "10:00"
 8      end:   "20:00"
 9    - name:  First half
10      start: "09:00"
11      end:   "15:00"
12    - name:  Second half
13      start: "14:00"
14      end:   "20:00"
15    - name:  Evening
16      start: "17:30"
17      end:   "22:00"
18
19  suppressions:
20    # Suppress availability during working hours
21    working_hours:
22      start: "09:00"
23      end:   "17:50"
24    # Lift working hours suppression on bank holidays
25    exclude_england_bank_holidays: true

ChatGPT figured out the initial draft of the algorithm and the config for me, and I refined the entire thing by asking it questions and making change requests while I was on my commute.

How LLMs influenced the way I worked

I’ve used LLMs quite a bit at work most of this year, but being able to do it outside the constraints of usual work was nice.

LLM-driven development meant I could fix bugs after a long workday. As an example, whenever I noticed a bug, I just had to start by asking the LLM to reproduce that bug using a test case and take it from there. This seems like the natural next step for TDD.

I feel like LLMs are going to make me code more often.

One of my main concerns about using LLMs is whether they’re merely making me think differently or if they’re encouraging me to not think enough. This bothers me because the last thing I want is to delegate thinking.

Perhaps it could be argued that Software Engineers delegating thinking to LLMs is, at least to some degree, a moral question.

Closing

This is currently running on my personal Kubernetes cluster, which means my GitHub Status and the availability page are both LIVE!

The only thing yet to be seen is if I will regret publishing my availability publicly!


Comments

Reply on Bluesky to comment

<< Previous Post

|

Next Post >>