Hi! I am James

Below are some musings on

  1. programming
  2. photography
  3. projects
  4. typescript
  5. terraform
  6. docker
  7. android
  8. cloud
  9. DNS
  10. bash

I also occassionally take some photos

    Learning to train a LoRA for SDXL

    I wanted to learn about the new wave of "AI" image generation, particularly Stable Diffusion and how to create a LoRA (low-ranking adaptation) which would allow me to add training data to the model. I thought an excellent approach to this would be to train a LoRA based on my face in order to generate a professional looking headshot of myself for use on LinkedIn etc.

    Using ffmpeg to capture a timelapse

    I recently needed to capture a 24 hour timelapse video of my back garden in order to plot the sun and resulting shade throughout the day in order to inform a decision on how best to landscape the garden.

    Brooklands

    16KP Lens

    I bought a lens made in the USSR for a projector and attached it to my camera.

    Street Photography Around London Bridge

    Today, I walked around London Bridge area, and attempted a style of photography I haven't tried before: street photography.

    M42 Lens Mount Adapter

    Today I bought an M42 to e-mount (Sony) adapter and took out an old Prinzflex 200mm lens for some test shots.

    Blacksmithing

    Two hand forged knives Today, I went to the Firebird Forge for the day and (under the excellent tuition of Mort, the Blacksmith) learnt a small part of what it means to do blacksmithing. Apart from a couple of blisters on my hammer-wielding hand, I also walked away with the above 2 knives I made.

    Creating a photo album using 11ty

    This blog is created using the wonderful static site generator 11ty. I wanted to add a single page which would show a gallery of all the photos posted in all of the posts on the site.

    Quick note entry (MacOSx & Android)

    I keep daily notes in a Markdown file, and I need to make sure I can add entries to those notes as quickly as possible in order to avoid disturbing the flow of the task I am working on.

    Train Textures

    IKEA Pax Hack

    Bognor Regis Photos

    Simple Daily Notes

    It is very popular at the moment in some circles online to show off one's personal note-taking process/system. This generally revolves around Obsidian and a very convoluted set of plugins and/or templates.

    What if Web Browsers were able to send emails?

    If a Web Browser was aware of it's user's email account (and how to use the account to send email), then contact forms on the internet would be lot better.

    Does AI conform to the laws of thermodynamics?

    I have started down a thought experiment, comparing "AI" systems to physical engines like the internal combustion engine, fusion/fission reactors, and eventually to perpetual motion machines.

    Using Application Passwords with Wordpress Docker

    I want to be able to use Application Passwords with my local network Wordpress installation that was using the official Docker image. There doesn't seem to be a huge amount online about how to do this so I thought I would post the solution that worked for me:

    WhatsApp ChatGPT Auto-Reply

    Wouldn't it be great to have ChatGPT auto-reply to some of your WhatsApp messages on your behalf? Well with a combination of the (unofficial) WhatsApp client library and OpenAI client library we can.

    Using `for_each` in Terraform's `dynamic` blocks

    The for_each instruction in Terraform allows you to loop a resource or module over a set to create multiple instances. For instance, if you were to do:

    Pair Programming is difficult

    Pair programming is difficult to practice effectively. Unfortunately, the inverse is also true: pair programming is easy to practice ineffectively. It is a learnt skill which is hard to pick up. I have tried to articulate some advice below for both the Driver and Navigator roles:

    Using GCP free tier VM for uptime and health checks

    What's in the (domain) name?

    I find myself periodically going on the hunt for a new domain name every few years, and having just completed that same search again, I thought I would write up some thoughts about the process.

    Crontab-as-code

    There are various tools that either wrap crontab, or offer alternatives to it. All I wanted though, was a simple solution to have my scheduled tasks defined as code (checked into a git repo) so that the tasks are reproducible and idempotent, just as Terraform is for IaaS.

    Run All Docker Compose stacks in sub-directories

    For my home server, I have a number of docker-compose.yml files, one for each application I run, in a sub-directory. I wanted a way to automatically do a docker-compose up -d for all of the applications at once, so that I don't have to cd into each directory in turn.

    Protecting endpoints with Typescript Method Decorators

    Typescript allows for an excellent language feature called Method Decorators. They are similar to annotations in Java and can be used to wrap or edit existing methods with new functionality. Below is an example of using Decorators to add some common functionality to endpoints, including authentication, validation and error handling.

    Low-code Telegram bot for baby sleep and feed tracking

    My wife and I wanted to start tracking and visualising our baby's sleeping and feeding schedule to help us understand the rhythms from a day-to-day basis. There are multiple apps to do that and seemingly the most popular one is Huckleberry but at $15 per month, I thought I could make something quick and simple to allow us to get the data we needed.

    Using Azure as a Dynamic DNS provider for your home server

    When hosting services from your home, you will want to use a Dynamic DNS (DDNS) entry in order to map your ever-changing IP address to a hostname you can use to access those services. For instance, home-server.mydomain.com will point to your IPv4 (or IPv6) address. There are providers noip and Duck DNS, but below is a method to use an Azure DNS zone and a script to update the IP on a regular basis. We will do this using Terraform and Docker containers.

    First Drone FPV flight

    This is my first attempt at flying my Beta85X V2 with an action cam strapped on top. It involves no small amount of crashing as well as almost getting stuck in a very tall tree, but it survived and made it home to fly another day.

    Using Azure, Terraform and GitHub Actions to host an (almost) free static site

    Let's start this post by saying that everything below is unnecessary. The outcome from this is exactly what GitHub Pages gives you for (completely) free. Hosting in Azure comes with a very small cost (pricing explained below), but the point of this is to learn about Azure, Terraform and GitHub Actions in the process of hosting a small, static website whilst keeping the costs very low.

    3D printed stand for Pirate Audio

    As a gift, I received a Raspberry Pi Zero Pirate AudioMini HAT. I got it all set up with Mopidy but I wanted to have it displayed nicely on my desk so that I could easily glance over and see the current song/artists, as well as easily access the next/previous buttons.

    Raspberry Pi bedside Lamp with Spotify and NodeRed

    Because why wouldn't you want an MQTT controlled, automated lamp with the ability to play music? I can see I don't need to sell you on this idea any more, so let's get right in with what you need:

    Typescript File Inheritance

    I am not sure how useful this pattern is, but it has some interesting effects, especially when sharing code between projects. So let me give you a brief description of it and you can see where to apply it.

    Using BitWarden and Chezmoi to manage SSH keys

    I have recently started using Chezmoi to manage my dotfiles (and various other pieces software config) across multiple machines. The distribution is done via a git repo and therefore we should not check in secrets such as the private part of the SSH key. Using Bitwarden, we can store the key in a Secure Note and retrieve on the other machines.

    Typescript Multi Async Interface

    I recently had to write a Javascript library which was going to be used in multiple different contexts by lots of different people. The purpose of the library was to supply a stream of updating values. Internally to the library, RxJS is used as it excellently models streams of updating values. However, the interface to the library should not expose the inner workings.

    Typescript `import * as ...`

    There is a very easy to use and simple pattern that can be used whilst importing files in Typescript. The main advantage of using this pattern is to increase the readability and scan-ability of code. And that pattern is import * as ...

    3D modelled and printed roof

    As part of renovations on our house, we wanted to explore the possibility of extending into the loft. Unfortunately the roof on our house was an odd shape with many different parts and ridges.

    Color Explosion Unity game

    2 very early Material Design Android apps

    In 2014, Google announced a new design language, called Material Design, which it put forward as the newest iteration of standard for interaction on mobile devices. At the time, it was in a very early form, the details were quite sparse and there were no apps "in the wild" which used it. My plan was to follow the standards and rules as closely as possible and create some very basic apps and release them. The 2 apps that I ended up creating are detailed below:

    My first web site in 2001

    Back in 2001, when I was 11 years old, my dad bought a website domain for me to use.