Sign in

Aaron Christiansen

@aaronc.cc
98 followers 260 following 83 posts

Software Engineer in Leeds, UK. Web, Ruby, Rust, and electronics. he/him Cross-posting to Mastodon: @aaronc81@ruby.social

PostsRepliesMedia
Aaron Christiansen @aaronc.cc · 16/09/2026
Great example SVGs over on MDN
Screenshot of MDN, showing a documentation example for the SVG "text" tag. It reads "My cat is grumpy!", with "cat" in large bold text, and "Grumpy" in very large red text.
000
Aaron Christiansen @aaronc.cc · 15/09/2026
Working on this modelling tool again - now you can define *recursive* operators, which lets you construct complex layouts of children based on each of their geometries. Here's a `stack` operator which arranges all children next to each other, even of different sizes, with a gap between each.
A code editor showing this code:

```
operator stack(gap = 0) {
    if ($children == 1) {
        children();
    }

    if ($children > 1) {
        child = children(0);

        translate([child.max_point.x + gap, 0])
        stack(gap = gap)
        ...children([ 1 : $children - 1 ]);
    }
}

stack(gap = 0.5) {
    cube(1);
    cube(2);
    cube(3);
}
```

Besides that, a model viewer shows three cubes of increasing size, with a small gap between each.
000
Aaron Christiansen @aaronc.cc · 23/06/2026
It's day #100 of Loconundrum! Thanks so much to everybody who's played - it's been lovely to hear from people enjoying the game. To mark the milestone, you can now play all 100 past puzzles from the new Archive! Fill out a missed day, or catch up on puzzles from before you started playing.
Screenshot of the new Archive page, showing a colour-coded calendar of different puzzle days
241
Aaron Christiansen @aaronc.cc · 14/06/2026
Here's a peek behind the curtain at Conductor, the thrown-together dashboard I use to schedule Loconundrum puzzles. It used to automatically pick at random from a pool, but once I ran out of the major stations, I started scheduling puzzles manually instead so I could test things out a bit more.
Conductor UI. There are filters "Show all previous days, reveal today/tomorrow/future days" and a tools section with "All CRSes to date", "Quick check", and a "re-run routing" button. Underneath is a list of all stations queued up, with buttons to reorder or edit them.
130
Aaron Christiansen @aaronc.cc · 09/06/2026
Loconundrum now has dark mode 🌙
A screenshot of Loconundrum with dark mode activated
020
Aaron Christiansen @aaronc.cc · 24/04/2026
If you played Loconundrum today (puzzle #40, 2026-04-24) before 7am BST, there's a chance you may have got the wrong puzzle due to a caching issue. If you got Birmingham New Street, you were affected. It should be fixed now, please load up Loconundrum again and have another go! Sorry about that 🚂
210
Aaron Christiansen @aaronc.cc · 30/03/2026
I wrote a blog post about how Loconundrum actually works. Thank you to everybody who's played! aaronc.cc/2026/03/29/l...
aaronc.cc
Building Loconundrum, a rail station daily guessing game
I wanted to brush up on some web skills, so I made Loconundrum. Along the way, I was significantly side-tracked by calculating journey times using rail open data.
250
Aaron Christiansen @aaronc.cc · 20/03/2026
Arc's "File" menu is probably the worst example of macOS Tahoe's automatic menu icons that I've seen yet
Screenshot of the macOS menu bar for Arc, with the "File" menu expanded. There are about 20 options, but only one of them has an icon, "Save Page As", which causes a bizarre-looking intendation for the icons around it.
010
Aaron Christiansen @aaronc.cc · 18/03/2026
I made a daily game where you try to guess a UK rail station! loconundrum.aaronc.cc
loconundrum.aaronc.cc
Loconundrum
A daily game: can you guess the UK rail station?
6128
Aaron Christiansen @aaronc.cc · 19/02/2026
Falling in love with inline snapshot testing My usual problem with snapshot testing is that you need to find the snapshot files to learn the expected output of a test - but with inline snapshots, the expectation is in the test code, which can be updated automatically by the snapshot tool. Neat!
#[test]
fn test_no_subcommand() {
    let test_env = TestEnvironment::default();
    test_env.run_jj_in(".", ["git", "init", "repo"]).success();
    let work_dir = test_env.work_dir("repo");

    // Outside of a repo.
    let output = test_env.run_jj_in(".", [""; 0]);
    insta::assert_snapshot!(output, @r#"
    ------- stderr -------
    Hint: Use `jj -h` for a list of available commands.
    Run `jj config set --user ui.default-command log` to disable this message.
    Error: There is no jj repo in "."
    [EOF]
    [exit status: 1]
    "#);
020
Aaron Christiansen @aaronc.cc · 09/02/2026
For the latest Gosu Game Jam, I wrote a crop-cultivating roguelike deckbuilder in Ruby, where you race the clock to score coins by combining your crops' effects. This is the most fun I've had creating a jam entry, I've wanted to try making a card game for a while! orangeflash81.itch.io/topsoil
Screenshot of the game. There's 01:24 left on the timer. From my hand, I'm playing a Runner Bean, which reads "On Harvest: Enhance this tile's growth rate by 20%." I'm hovering the game grid, which has crops at various stages of growth already, to decide where to plant my Runner Bean.
010
Aaron Christiansen @aaronc.cc · 26/01/2026
TIL that: 1) you can have SVG favicons nowadays, and 2) they can be styled to respond to light/dark mode automatically evilmartians.com/chronicles/h...
Your HTML page should have a <link> tag in its <head> with rel="icon", type="image/svg+xml" and with the href containing a link to the SVG file as attributes.

SVG is an XML format and can contain a <style> tag to describes CSS. As with any CSS, it can contain media queries like @media (prefers-color-scheme: dark). This will allow you to toggle the same icon between light and dark system themes.
010
Aaron Christiansen @aaronc.cc · 05/01/2026
Agree with a lot of the points in this article. I've found Tahoe's menus take me noticeably longer to scan than before, and I think it's partly down to the inconsistent visual noise of the icons. tonsky.me/blog/tahoe-i...
tonsky.me
It’s hard to justify Tahoe icons
Looking at the first principles of icon design—and how Apple failed to apply all of them in macOS Tahoe
110
Aaron Christiansen @aaronc.cc · 04/01/2026
Do you remember this gadget? It was sold as letting you control your apps/games with your hands. Young-me saw this in Maplin back in the day, thinking how cool it would be. I saw one in a second-hand shop, for a price where I'm not too bothered if it's rubbish. Let's satisfy young-me's curiosity!
The box for a "Leap Motion" controller. It shows the device on the front - a light-grey metal cuboid with a piano-black top. The copy on the front of the box reads "The remarkably accurate, incredibly natural way to interact with your computer."
100
Aaron Christiansen @aaronc.cc · 02/01/2026
I've done some mad science with Ruby 4.0's new Ruby::Box namespacing feature - what if Ruby had JavaScript-style `import`/`export`, rather than requiring entire files? You only get what you import, and imported items don't "leak" between files. Try it, if you dare: github.com/AaronC81/rixby
A VS Code window with three editors:

shapes.rb:
class Rectangle export
end

class Circle export
end

assertion.rb:
export def assert_equal(expected, actual)
end

canvas_test.rb:
import { from 'canvas', :Canvas }
import { from 'shapes', :Rectangle, :Circle }
import { from 'assertion', :assert_equal }
010
Aaron Christiansen @aaronc.cc · 19/12/2025
Had a good time with Langjam Gamejam - a week-long jam where you build a language and then use it to write a game. The resulting game is pretty simple - I didn't have much time left after getting the language to a usable state - but I think it's at least fun! orangeflash81.itch.io/space-blaster
orangeflash81.itch.io
SPACE BLASTER by Aaron Christiansen
Minimal space game for Langjam Gamejam
020
Aaron Christiansen @aaronc.cc · 13/12/2025
For a bit of polish and ease-of-experimentation, there's now a basic editor! Here's one possible implementation of a rounded rectangle. Being able to define a new operation that inspects the geometry, like this `rotate_around_centre`, feels rather useful to me.
YASCAD code editor, with dark theme. On the left, a Monaco code editor, with file and rendering controls. On the right, an orange cuboid with rounded corners on a grid.

The code in the editor is:

operator rotate_around_centre(angle) {
    c = buffer() children();

    // Move so that centre is on (0,0), rotate, then move back
    dx = c.origin.x + c.size.x / 2;
    dy = c.origin.y + c.size.y / 2;
    translate([dx, dy])
    rotate(angle)
    translate([-dx, -dy])
    copy(c);
}

// Subtract this from a rect to round its closest corner to the origin
module rounded_corner(r) {
    translate([r, r]) rotate(180)
    difference() {
        square(r);
        circle(r=r);
    }
}

module rounded_rect(w, h, r) {
    difference() {
        square([w, h]);

                                                        rounded_corner(r);
        rotate_around_centre(90)  translate([w-r, 0])   rounded_corner(r);
        rotate_around_centre(180) translate([w-r, h-r]) rounded_corner(r);
        rotate_around_centre(270) translate([0, h-r])   rounded_corner(r);
    }
}

linear_extrude(1)
rounded_rect(5, 6, r=1);
130
Aaron Christiansen @aaronc.cc · 12/12/2025
Ruby argument validation with pattern matching aaronc.cc/2025/12/12/r...
aaronc.cc
Ruby argument validation with pattern matching
010
Aaron Christiansen @aaronc.cc · 30/11/2025
Starting to get interesting - now you can write operator modules which behave based on some properties of their children - here repeating the children in a grid. You can't do something like this in OpenSCAD unless you also pass a separately-calculated size for the children.
Code editor showing cylinders repeated on a 3x4 grid.

Code:

```
// Repeat the children a certain number of times in the
// X and Y directions to form a grid
operator repeat(xs, ys) {
    // Draw the children to a virtual buffer once
    t = buffer() children();

    for (x = [0:xs-1]) {
        for (y = [0:ys-1]) {
            // Based on the size of that virtual buffer,
            // stamp out copies of the children
            translate([t.size.x * x, t.size.y * y]) {
                copy(t);
            }
        }
    }
}

repeat(3, 4)
cylinder(5, 5);
```
020
Aaron Christiansen @aaronc.cc · 28/11/2025
Having a crack at a project I've been thinking about for a while. An OpenSCAD-alike where you can introspect objects you've already drawn - which means less thinking about how to structure your variables for quick thrown-together 3D prints. First prototype works well!
A code editor showing an STL preview with a small cube on top of another big cube. The code beside is:

```
// Create an object and make a binding for it
big_cube = cube([20, 20, 20]);

// Reference that binding to create another object
translate([0, 0, big_cube.size.y])
cube([5, 5, 5]);
```
030
Aaron Christiansen @aaronc.cc · 09/11/2025
I found out about the “Paged Out!” Magazine, which publishes one-page articles about programming and computing. I absolutely LOVE this pagedout.institute
pagedout.institute
Paged Out!
Deeply technical zine. And it's free.
140
Aaron Christiansen @aaronc.cc · 01/11/2025
Seeing if I can put together a tiny macro pad to live in my work’s office - I miss my macros when I’m not working from home! First steps - a 3D-printed plate with hardwired Gateron Browns (with jumpers I now realise I’ve made far too long)…
Six Gateron Brown key switches inserted into a black plastic plate, with jumper wires coming out the back
100
Aaron Christiansen @aaronc.cc · 28/10/2025
New Twilight Sad, wooo! Fantastic start, can't wait for more... www.youtube.com/watch?v=P9zu...
youtube.com
THE TWILIGHT SAD - WAITING FOR THE PHONE CALL
YouTube video by thetwilightsadofficial
010
Aaron Christiansen @aaronc.cc · 25/10/2025
My Jujutsu problems were caused by .gitignore being case-sensitive. Turns out I've been relying on case-insensitivity for a long time - macOS and Windows will do that to you ;) Patched in case-insensitivity, and now Git and Jujutsu agree with each other: github.com/AaronC81/jj/...
github.com
fork: case-insensitive .gitignore · AaronC81/jj@f4a2143
010
Aaron Christiansen @aaronc.cc · 20/10/2025
I’ve landed a little warning improvement in this release! Gleam was a lovely codebase and community to contribute to - high hopes for where this language goes in the future
A helpful error for Rustaceans, C#ers, and friends

Gleam has a consistent syntax for constructors at the type and value level, using () for both. It does not use () for value constructors and <> for type constructors, as is common in some other languages.

To help folks coming from other languages a set of helpful errors have been added for when they try to use this non-Gleam syntax in their Gleam code.

error: Syntax error
  ┌─ /src/parse/error.gleam:2:12
  │
2 │ type Either<a, b> {
  │            ^ I was expecting `(` here.

Type parameters use lowercase names and are surrounded by parentheses.

    type Either(a, b) {

See: https://tour.gleam.run/data-types/generic-custom-types/
Notice how the error message includes the correct syntax for the specific code that the programmer has written. The programmer could copy/paste the correct version into their code, if they so desired. A link to the documentation is also provided, linking to whichever feature the syntax error is for.

Thank you Aaron Christiansen!
170
Aaron Christiansen @aaronc.cc · 15/10/2025
What if we were 3D printing decades ago? Downloading STLs over dial-up? I mocked up Cura for Windows 95
A UI mockup of Ultimater Cura running on Windows 95. In the centre is a greyscale render of a Benchy on a 3D print bed. The left-hand panel includes dropdowns to select printer, nozzle, and filament settings. Underneath are print properties like a layer height profile, infill slider, support checkbox and adhesion checkbox. Under the render is an object selection list box, with toggle buttons for render controls.
220
Aaron Christiansen @aaronc.cc · 09/10/2025
After a few days - this works alright! Only issue is there's some disagreement between Git and Jujutsu about a few files from LFS - Git is tracking them, but Jujutsu thinks they're new. If I delete them, Git sees the repo as dirty, but Jujutsu is happy and works a treat.
000
Aaron Christiansen @aaronc.cc · 04/10/2025
Having a play with Jujutsu VCS: jj-vcs.github.io/jj/latest/ You can move back to a previous commit and edit it, and all the later commits rebase automatically… coming from Git, that feels MAGIC
121
Aaron Christiansen @aaronc.cc · 22/09/2025
I don’t know how long this has existed, but I’ve never spotted it before… Apple Photos smooshing together geotagging and event listings to give concert photos an artist tag - which you can search by! - is such a damn clever feature
A screenshot of Apple Photos on iOS showing “Magdalena Bay Concert” as a tag
020
Reposted by Aaron Christiansen
K'eeg @armormodekeeg.blacksky.app · 31/08/2025
all the best windows software in history is called something like "joe's thing doer". it does the thing and nothing else and is available on a html website in plain text and takes up under a megabyte of space and uses default windows ui elements and will work until the heat death of the universe
17679491888
Aaron Christiansen @aaronc.cc · 26/08/2025
This looks really promising - I’ve read a lot of praise for uv in Python-land, so having something similar on the horizon for Ruby is exciting andre.arko.net/2025/08/25/r...
000
Aaron Christiansen @aaronc.cc · 23/08/2025
Echo Point Nova is one of my favourite recent indie games, a super fast movement-shooter, and the first game in a while I’ve 100% completed …and it just got an entire second map as a free update. Time to 100% complete this too 😁
A screenshot of Echo Point Nova. Looking from a height over a dense forest, surrounded by water, with snowy mountains in the distance. Checkpoint markers are visible as tall blue and orange streaks of light are visible, sprinkled across the world.
020
Aaron Christiansen @aaronc.cc · 22/08/2025
I enjoy using keyword-argument-heavy languages, and IMO an underappreciated feature is letting arguments have different external vs internal names. An example in Swift - variables named “of” and “with” would be unintuitive inside the function body, but read naturally when calling
Apple Developer documentation for the method “replacingOccurrences(of:with:)”.

Returns a new string in which all occurrences of a target string in the receiver are replaced by another given string.

func replacingOccurrences(
    of target: String,
    with replacement: String
) -> String
140
Aaron Christiansen @aaronc.cc · 17/08/2025
I suddenly remembered the Parallax Propeller - a microcontroller with a custom architecture and language, which I saw mentioned on Arduino forums back in the day and thought looked super cool. Turns out they released a second generation a few years ago! Awesome… www.parallax.com/propeller-2/
parallax.com
Propeller 2 - Parallax
Multicore Specs
020
Aaron Christiansen @aaronc.cc · 05/08/2025
I've been playing with Gleam, a little compiled language targeting BEAM (Erlang's runtime) and JS. I like a lot of its ideas, it's the closest I've felt to writing "garbage-collected Rust". My favourite trick is the `use` keyword, which is like a generalisation of JS' async/await transform:
import gleam/io

pub fn invoker(f: fn(String) -> Nil) {
  f("Hello")
}

pub fn main() -> Nil {
  invoker(fn(i) {
    io.println(i)
  })

  // is equivalent to

  use i <- invoker()
  io.println(i)
}
120
Aaron Christiansen @aaronc.cc · 07/07/2025
New article! Ruby's blocks share many similarities with the anonymous functions found in other languages - but how are they different? The unique control-flow features of blocks make them perfectly suited to a wide range of applications in Ruby. aaronc.cc/2025/07/07/r...
aaronc.cc
Ruby blocks aren't just functions
When you call a method in Ruby, you can pass a block, an additional piece of code which trails the method call. Let's explore how this is different to anonymous functions found in other languages.
010
Aaron Christiansen @aaronc.cc · 01/07/2025
I want to start Posting More - ideally about programming, electronics, and the like. But instead, since we’re half-way through the year, I’ll kick off with a short thread about some music released this year which I’ve really enjoyed. Hopefully, you might enjoy some of it too 🎶🧵
100
Aaron Christiansen @aaronc.cc · 01/03/2025
This is really exciting! Standardised RBS syntax + Sorbet's developer ergonomics = a big win for Ruby static typing
000
Aaron Christiansen @aaronc.cc · 21/02/2025
My first article of the year - defmt has been a slick improvement to my embedded development experience! aaronc.cc/2025/02/20/d...
aaronc.cc
Embracing Embedded Rust - from Serial.println to defmt
010