Dev

TWIL December 5th 2025

  • Argon2id is the state of the art in hashing
    • But for short-lived OTPs, probably overkill

After being reminded subgrid exists & is useful in October, Josh comes swooping in with a typically high quality article about the possibilities it unlocks. Siblings being aware of each-other's size & layout is a very valuable thing in CSS, as is a layout being able to 'penetrate' containers like cards.

I did not...

Continue reading

TWIL November 28th 2025

  • Sometimes you just need to rm -rf the repo and start over
    • but you shouldn't do this with a fair chunk of work on a branch that doesn't exist on remote
    • and you definitely shouldn't do it twice in the same week
    • to the same branch
  • Vite handles styles in dev (at least the ones you import in your components) by adding them as inline style tags
    • this can lead to very annoying and confusing CSS issues
    • and if it does, that's probably a hint your CSS isn't very well scoped
    • should probably make a...
Continue reading

TWIL November 21st 2025

  • Upgrading webpacker (Rails webpack integration) is hell
    • So is migrating from it to Vite
    • So is upgrading it to the actually-maintained React on Rails
    • In general, stuff that integrates React & Rails seems to not be super fun
    • Our internal icons package is not compatible with Vite's interpretation of ESM, and at least one way of fixing that breaks it for everything else
Continue reading

TWIL November 14th 2025

  • Another thing I should have pushed harder for earlier: passkeys over OTP login
    • Seems like people are coming around but I wasted a lot of work investigating/other people's time reviewing the RFC for OTP login
    • Doing proper passkey research makes it blatantly obvious they're the better option, which I could have realised sooner & used to push for them
  • It's possible for the hero section of a header to contain no fewer than 10 elements, just to display a hero logo
  • Check how many times a component is used across your codebase before changing its styles,...
Continue reading

TWIL November 7th 2025

  • Don't run tests locally with dependencies you don't run in CI, then be surprised the tests only fail in CI
    • Don't create projects with dependencies on so many external services it's possible to miss multiple cases of the above in a single test
  • There are about a billion little details you need to think about on frontend; every possible combination of screen sizes you can imagine & some you can't
  • It's possible to get 'overwhelms his senior with PRs' as something to improve on a performance review

I've mentioned this before and doubtless will again,...

Continue reading

TWIL October 31st 2025

  • Exciting as it is to start a greenfield project, adding to an existing one can avoid a lot of infra setup
  • Ruby isn't JS
  • For some reason you need to add body and a bunch of other properties to a Net::HTTP::Request after initialization rather than just passing it to the constructor
    • It'll quite happily take a body argument, but presumably just makes it a header
    • Which makes it annoying hard to notice something is wrong unless you inspect the request/call request.body and notice it's nil
  • Slack bots can't send messages unless they're in the channel, but...
Continue reading

TWIL October 24th 2025

  • I probably should have set up Playwright e2e tests for both projects we're responsible for consecutively
    • Now it's been long enough since the first I forgot the details but feel like it should be easier
    • Doesn't help that this time the React app is embedded in Rails
  • Setting Playwright's baseUrl to host.docker.internal:port lets me make the initial request for the index page
    • But then the script/style tags still go to localhost:port since rails server/webpack doesn't know about the docker container
    • Rewriting the host to host.docker.internal fixes the tags, but breaks regular local dev
    • So either...
Continue reading

TWIL October 17th 2025

  • It's entirely possible to write a Tanstack Query replacement that works
    • You probably shouldn't though, there are a lot of edge-cases/nice QoL features
    • Maybe makes more sense to roll your own for a work project, especially if you can re-use it?
    • Or for a personal project you're doing with the express purpose of learning

The Programmer Identity Crisis - Simon Højberg

Another eloquent AI takedown which expresses my own distaste for the technology better than I ever could. I became a software engineer because I enjoyed writing code, making things and solving problems;...

Continue reading

TWIL October 10th 2025

I'm on holiday next week, so no TWIL since the only thing I'll be learning is boss patterns in Silksong.

  • JS devs will really pull in an NPM package for one thing in one component
    • Admittedly it was a mildly difficult date format
    • But, if they just passed the formatted date to the string they could've used Intl
  • Don't assume a valid timestamp to your backend is a valid timestamp to your frontend
    • Especially when the backend timestamp is nullable
  • Honeycomb's frontend observability is pretty cool since you can link front/backend traces
      ...
Continue reading

TWIL October 3rd 2025

  • It's very easy to take a long detour doing cleanup work which has no business value whatsoever
    • Even for senior devs
  • Designing something to the point where it can work for all future use cases, or even a moderate number of them, is an exercise in futility
  • Staging environments exist for a reason.
    • Even if it's a small, surely harmless change there's no harm doing a rollout just to staging first if there are potentially huge consequences
  • I really do not enjoy writing ADRs/RFCs
    • I recognise they have a lot of value,...
Continue reading

TWIL September 18th 2025

Very short week this time since Monday was a public holiday and I'm taking Friday off to go on a long weekend trip to Nagano with the fiance.

  • Even making a simple change can be complicated if it affects clients
    • Especially if those clients have distributed printed guides to using your service
  • Even if it's frustrating, taking the time to make sure other teams understand how to use your features is worthwhile
    • People won't remember that they messed up by ignoring instructions, they'll remember the bad experience
  • moment.js is 4MB, and dayjs offers...
Continue reading

TWIL September 12th 2025

  • Every time I try a major dependency upgrade (React, Node, etc.) it's an absolute lottery whether it'll be a 3 line or 3 day change
    • Thank god for Typescript and (better than before) test coverage though, without them it'd be hopeless
  • Caching is amazing until you have to troubleshoot a problem caused by cache
    • If you're going to use a variable as part of a cache key, make sure it can't be undefined
  • Yet another NPM social engineering attack made me go through all our dependencies to see if we need them
      ...
Continue reading

TWIL September 5th 2025

  • It's very important to clarify requirements from the PM before holding an RFC meeting
    • otherwise you're just wasting everyone's time because no one knows the problem they're trying to solve
    • still managed to hash out some parts of it though
  • Even if I had all the necessary info, I definitely could have facilitated better
    • maybe ok to open by giving an overview since not everyone had time to read it, but should've prepared something
    • should have opened by going through the comments
    • then asking if anyone had questions/opinions overall
  • Caching is amazing, I...
Continue reading

Exfiltrating Data from Fly.io Postgres

I'm writing this mainly as a reminder for myself, since I'm pretty sure I'll continue procrastinating the Spending Tracker rewrite to Cloudflare/Svelte and need to do this again in the future. But maybe someone else finds themselves in the same situation and by some SEO miracle lands on this article rather than piecing together info from forum posts like I did. Or they just ask our LLM overlords and this is in the training data, either way.

Quick note, this is for their legacy Postgres because that's what I used/it was all they offered at the time. Not sure if...

Continue reading

TWIL August 29th 2025

  • I already knew this, but overwriting Rails' default accessors for model attributes is a bad idea. So many different things can go wrong.
  • If you need an extra argument in your setter on an AR model, you can just redefine the setter and add it in
    • I added a separate update_with_extra_attribute method, but might explore whether I can just use the setter itself tomorrow
    • Defining the separate method lead me to learn about public_send though
    • Since I needed a way to call the setter with an extra argument (attr = value, extra_arg predictably did not work)
    ...
Continue reading

TWIL August 22nd 2025

  • Don't forget an element is in the page twice, especially if it has an ID and you're trying to attach a click handler using that ID
    • can lead to long, hair tearing debug sessions followed by a lightbulb moment when you call click() directly on the element in the browser console
    • I just could not wrap my head around how the inspect panel could show an event attached to it, with the correct code in that event when expanded, but then not do anything when clicked
    • I guess for elements with IDs the inspect panel just shows the...
Continue reading

11ty Migration: Feature Parity

After managing to stick to at least one weekly post for a few months I've decided to reward myself with the true purpose of a personal blog - tinkering.

I started off on Hugo with the Bear Cub theme so I had no excuse to put off writing while I worked on 'essential' features, but now it's time to make my personal site a bit more personal.

I settled on 11ty as that seems to be what a lot of the people I read are using, and my brief interactions with Hugo's config/syntax didn't impress me (+ I just...

Continue reading

TWIL August 15th 2025

  • You can use radial-gradient to draw circles on the background
  • Reminded myself that setting css variables inline applies them to all child elements
    • Since SCSS seems to transpile its variables to CSS variables, could I overwrite those values for consistency?
    • And to provide a proper fallback, as opposed to a default value
    • Or is that a bad idea cos it'll confuse someone else who needs to debug it in the future?
  • Sometimes just requiring the user (if they're a dev) to dump a bunch of JSON into a field is better than inventing your own...
Continue reading

Todos

This Blog

  • legacy 'something' series about vault stuff

    • optimising list endpoint
    • class component refactors
    • store types?
  • Style blockquotes

  • Add custom published/drafts filters an use them to make a drafts page

  • Fire effect animation on the main title?

    • Probably need a reduced motion media query on that one
  • Make a site logo here

    • Pixel style?
    • Bonfire, with final boss veigar colors?
    • animate it?
  • Animated gradient on link hover

  • Custom styles per category

    • list icons
    • colors (through CSS var overrides)
    • ...
Continue reading

Blogs I Enjoy

Josh w Comeau

Topics

  • CSS
  • JavaScript
  • General webdev

Why?

So many reasons, not least of which is that when I went to his blog to grab the link and paste it here, I discovered a new rainbow image on his home page. Then I noticed the parts of the rainbow followed my mouse around, and as I wiggled the rainbow around like a snake charmer I noticed a settings icon, which opened a slickly animated modal which allows me to change various properties of the rainbow for all users of the site (I checked on another device)....

Continue reading

TWIL August 8th 2025

  • Being on the other side of an interview (albeit a screening interview) is really weird
    • Really drives home how nervous and eager to please you must look when you see someone else going through it
    • Also, since it was just a screening I still don't really know what a PM does...
  • Global setup for Playwright seems a bit finicky
    • We tried adding a page.on to catch and throw React errors rather than ignoring them
    • While it worked in the test body it didn't do anything in a beforeEach or test in the setup file
    ...
Continue reading

TWIL August 1st 2025

  • It's amazing the difference in perceived quality replacing a loading spinner with a skeleton can make
  • Migrating an endpoint from only returning a single record to an id-keyed hash of them went smoothly
    • First modified it to accept both the single id and an array of them with different branches
    • Then added a new API call to the frontend which used it to condense multiple existing calls into one
    • Once that was live and known to work in prod, moved all the single calls to the multi-endpoint passing a single element array of ids
    • Finally removed the single...
Continue reading

TWIL July 25th 2025

After spending most of the week trying to get a workflow setup with Copilot/Claude 4 to migrate a bunch of legacy class components to function components, I ended up giving up and just doing it quicker/better myself.

Since we have ~40 class components still in the codebase, my end goal was to set up a semi-automated pipeline we could run them through one-by-one, allowing the team to rid ourselves of a large chunk of tech-debt without the fairly large time investment that would usually require.

I started off by setting up a copilot-instructions.md with some process/code quality expectations about the...

Continue reading

TWIL July 18th 2025

  • BE VERY CAREFUL WITH FORCE PUSHING
  • ABSOLUTELY DO NOT FORCE PUSH WITHOUT CHECKING CHANGES AFTER A LONG AND COMPLEX REBASE ON TRUNK
  • WHY WOULD YOU DO THAT
  • make sure you're not setting this.loading = true on a class that has another 5 or so api calls coming up
    • especially if it's not an observable property
    • and you want them to run simultaneously
  • when you roll out a new feature to prod, don't just spend hours making a performance monitoring dashboard
    • instead you should probably spend that time looking at the error monitoring
    • or do both,...
Continue reading

TWIL July 11th 2025

  • If you're going to have types, don't trick them. No matter how annoying it is to do them properly now, having misleading types will cause someone else a lot more annoyance down the road.
  • Alternating between passing regular props, destructuring them from params, and sometimes using injected props is very confusing. Stick to one.
  • mobx allows you to make properties on a store observable, then components you mark as observers react to changes in observables which affect them.
Continue reading

TWIL July 4th 2025

  • A database column existing does not necessarily mean it's being used
    • even if it's named after the thing you're looking for
    • especially when working on a legacy application
  • You probably don't want to parse, compress and 9MB of JSON before your React app can do anything
    • You especially don't want to iterate over all that data 14 separate times rather than doing a single loop
  • bundle config shows you all the custom config which applies to the directory you're in, and paths to the files which set it
Continue reading

TWIL June 27th 2025

  • It's possible for yarn install to 'succeed' and the package files to not be present in node_modules
  • It's possible for yarn install to 'succeed' and the package files to not be present in node_modules but to be present in your yarn cache
  • It's possible for yarn install to 'succeed', the package files to not be present in node_modules but to be present in your yarn cache and the package files for dependencies of the main package to be present in node_modules
  • If this happens:
    • looking at your node_modules/.bin directory will show a broken symlink from the package name...
Continue reading

TWIL June 20th 2025

  • When a service says they redact PII, trust but verify
  • The 'check' half of 'guess & check' is very important
  • Being able to replicate errors locally really makes all the difference when fixing them
  • You can trigger Sentry errors in prod by editing the browser HTML to add a button which throws on click
    • e.g. <button onclick="throw new Error('test')">Test</button>
  • CI for PRs and trunk should be exactly the same except for deploying, very annoying to merge a PR and have it fail CI
Continue reading

TWIL June 13th 2025

  • enzyme is an alternative to React Testing Library which focuses on the React Tree rather than the DOM
  • Jest can run individual tests or suites concurrently, and so can Vitest
  • Running DOM-based tests concurrently writes all of them to the same DOM (at least by default)
  • This can make it seem like RTL isn't cleaning up the DOM after each test like it should, potentially wasting hours of your time -__-
  • eslint-plugin-jest-dom can tell you when you should be using RTL's custom matchers
Continue reading