This is a collection of my blog posts. If you use a feed reader, you can subscribe!
Inspired by Jeremy's post on how he syndicates to Bluesky, I
thought I'd follow suit (many examples are useful when it comes to API
integration work). A disclaimer though... I'm dubious of the long term prospects
of Bluesky for reasons I won't go into here. That being said, it's currently
a vibrant place, and syndicating from my site to other places keeps my
content in my handsâ¦
Here are a selection of albums which are all-time favourites of mine. They stand
up as a whole (not just as single tracks). I donât claim to have good taste in
music, or that my taste is better than anyone elseâs! With each album Iâve
written a little about times and places I associate with it. The albums are
presented in no particular order. Iâll garden this post over time and add new
material. I've linked to music services where I can find each album available,
but with minimal effort. There are other services, but they're either behind
paywalls or incomprehensible to meâ¦
Last weekend we held IndieWebCamp Brighton 2024, the first in Brighton since
2019. I thought I'd collect my thoughts both as a host, and as an attendeeâ¦
In 2001 I found myself falling down a mechanical keyboard rabbit hole. It
started off with two ortholinear (keys laid out in a grid) keyboards requiring
minimal assembly (mostly adding my own switches and key caps). From there I
moved onto a split keyboard (one unit per hand, connected together by a cable)
with a column staggered layout (keys are aligned in columns, rather than rows
like a conventional keyboard). In the end it was inevitable that I would try to
design my own, but what did I wantâ¦
I've been tracking my Japanese language study session since 2022. You can see
the first year report for
comparisonâ¦
Recently I had a problem where I had to find the first matching element of an
array by type. Ruby provides a method to return the first matching (or nil
)
element in an array, but sorbet isn't smart enough to type narrow it when the
match is related to the type of the elementâ¦
When working with type systems like TypeScript or Sorbet, type narrowing
patterns are a way to handle different types a variable may contain in different
branches. For exampleâ¦
This time last year I put together some custom scripts to send a record of each
study session to my personal site using the micropub endpoint. You can see
them here. Each entry says what I did, how long I did it for,
and when I started doing it. On their own these aren't particularly interesting
or useful. They mostly serve to hold me accountable. However, now that I have a
full year of data, it seems like a good time to see if there are any trendsâ¦
Below is a procedural snowman. I'm using a little code to create Christmas
cards again this year, and as before I wanted each to be unique! If you received
a card from me, you may see something like ?seed=1234567890
in the URL bar.
That will be the random seed which generated your snowflake (and it's yours to
keep). To see a random snowflake, remove everything after the question mark and
hit enter. Refresh the page to see a fresh random snowmanâ¦
I went to ffconf 2022 a couple of weeks ago, and two of the talks in
particular resonated with me... (more actually, but these felt actionable)â¦
The :has()
CSS pseudo-class opens up all sorts of possibilities. I
wanted to see if it could simplify how I handle the ruby text (annotations above
or below text to help with reading) in my Japanese notes. It works (in Safari
and Chrome at least, and hopefully Firefox soon)â¦
I started a new role recently, and the company is large enough that there are a
number of folk learning or proficient in Japanese as a second languageâ¦
Markdown is the standard for writing in techie circles these days, but
it's pretty minimal. For a readme it's all you need, but if you create a site
around Markdown like I have then you pretty quickly bump into its limitations.
Markdown is deliberately limited, so it's no fault of the language or its
creatorâ¦
Below is a procedural snowflake. I'm using a little code to create Christmas
cards this year, and I wanted each to be unique! If you received a card from me,
you may see something like ?seed=1234567890
in the URL bar. That will be the
random seed which generated your snowflake (and it's yours to keep). To see a
random snowflake, remove everything after the question mark and hit enter.
Refresh the page to see a fresh random snowflakeâ¦
A generative patchwork of pastel colours. The colours begin with a randomly
picked colour in LCH. Other
colours are hue rotations in LCH space so that they're perceptually nice
together. Feature detection is used to render using LCH colours when the browser
supports them (Safari only at the time of writing), or to pick a close colour in
RGB space when LCH is not supported (the code for this is based on code in
d3-color). Refreshing generates a new
patchworkâ¦
I had some issues getting the v3 AWS SDK for JavaScript to communicate
with localstack S3, but I found a solution! With the V2 JS SDK, the
configuration object for the S3 client looks likeâ¦
This site uses a static site generator to build plain HTML pages. Since there's
no database to add, update, or delete pages from, determining when to dispatch
mentions can be challenging! Here's how I use a Netlify
build plugin and an atom feed to manage itâ¦
I use marked
to do the markdown rendering for this blog. A recent
feature makes it possible to create custom block types with a little hacking. In
this post I show you howâ¦
Based on the last experiment, this one uses hexagonal grids rather than
triangular ones. The way the SVG is constructed isn't pretty (a mish-mash of
paths) but it gets the job done. I've given the two grids red and blue lines
and a black background to make the moiré pattern stand outâ¦
This experiment was inspired by field of twistronics, the study
of the intersesting properties of misaligned graphene sheets. The misalignment
produces a moiré pattern which echoes the underlying structure. I'm too
lazy to do hexagonal grids in an afternoon of tinkering so I used triangular
grids insteadâ¦
An experiment into generating SVG circles which don't overlap. It was timeboxed to an hour,
so it's a little rough around the edges (but I think that adds to its charm)â¦
It's been a while since my last maths heavy article. I
enjoy writing these but struggle to find the time to write manyâ¦
The graphic below is generated randomly and rendered as an SVG. Occasionally it
glitches, but that's all part of the fun! It was inspired by a graphic seen in
Charlotte Dann's ffconf 2019 talk at about 6:25
in. See the next post for a description of the maths I used to do thisâ¦
The day was packed with interesting and diverse talks, and there's just too much
to talk about in a single post. It's definitely worth searching around for other
blog posts to see other's takes on the dayâ¦
I had a great time last weekend at IndieWebCamp (IWC) Brighton. The first day
was filled with discussions on various IndieWeb related topics. I
attended discussions onâ¦
That's right! After more than a year of talking about adding a dark mode I
finally did it. The wider support for
prefers-color-scheme
is what pushed me over the edge.
I'm also a slave to fashionâ¦
I mentioned a new service which handles webmentions in a
previous post. I decided to replace
the glitch I've been using for
one which is much leaner. It uses
the library which powers webmention.app to handle webmention (and also
older technologies like pingback) endpoint discovery and mention dispatch so I
took this opportunity to ditch my own discovery codeâ¦
In a previous post I talked about an npm script I had written to be executed by a GitHub actionâ¦
I really like webmentions. They provide a way to let folk know that you're
writing about their blog posts. I see them as an alternative to comments which
encourages better discourseâ¦
In the past I used atd to schedule the
publication of my blog posts. When I moved to Netlify I lost the ability to
schedule posts, and didn't think about it until
a recent conversation on twitter with Remy Sharp. Remy asked
how to schedule blog posts for static sites and it got me thinkingâ¦
I made the source code for this site public! You can find it
here. I've
written at length about how I've built this, and having
the code makes it easier to point to particular lines. I hope it'll
inspire you to do the sameâ¦
This week started off a little boring. On the Thursday though, the rebooted Brighton Homebrew Website Club met at Clearleft. After catching up with the folk there, I worked on an experiment to theme this blog, with the theme determined by a toggle in localStorage
. By placing an inline script in the head right after the stylesheet link tag, I demonstrated that it's possible to select a theme before a paint, avoiding an awkward flash of the wrong theme. This may not news to anyone but me. I've not implemented anything just yetâ¦
This edition really covers the last two weeksâ¦
This is my first go at writing a weeknotes entry, and this week has been a busy
oneâ¦
I've made a couple of small contributions to Node.js in the past. These were
quite esoteric, and unlikely to be discovered or noticed by most developers.
Recently I made a contribution which might be noticed thoughâ¦
My resolution this year was to work on my Japanese speaking abilityâ¦
I've been working on this post for a while, but about a month ago my firstborn
arrived, and he's been getting the lion's share of my attention. I start work
again tomorrow, so I decided to just publish this post and be done with it.
Apologies if it's a little rough around the edgesâ¦
Nested resources are common in real life, and when you're a programmer working
on RESTful APIs you may have noticed that there are often trade-offs when it
comes to formatting the routes of nested resourcesâ¦
It occurred to me a couple of days ago that it'd be neat to build a glitch to
announce new blog posts. Since I deploy this blog by pushing to a master branch
on GitHub, creation of a blog post is somewhat less obvious than when publishing
on a platform like wordpress or medium, so I needed to figure out another
approachâ¦
In celebration of the Battenberg theme, here is an animated Battenberg! It's
made of two SVG paths composed of lines and arcs. These are calculated using
three angles and a bucket load of trigonometry (I'm not as good as I used to be
at trig). A requestAnimationFrame
loop updates these angles and the paths.
Click on start to begin the animation. You can tweak the angular speeds using
the three number inputsâ¦
I was recently tripped over by a subtlety in how service worker fetch events
and fetch works in conjunction with content security policy (CSP). This happened
while adding an image to the about page. This post is the result of
a conversation I had with Jake Archibald on twitter (with thanks for
helping me to understand what was going on)â¦
In a recent post I wrote that I had integrated
webmentions, and some of that has since changed. Time for an updateâ¦
When I originally built this blog, I gave it a very simple no nonsense theme.
One colour (beige) for the background and black for text and the odd horizontal
rule. After a couple of minor iterations I added a sticky navigation bar (in
CSS, no JS)â¦
In the last post about this blog I wrote about why
I removed the service worker which made this blog a progressive web applicationâ¦
It's been a while since the last entry about how I've
built this blog. Since it is constantly evolving, now seems as good a time as
ever to write about some of the changes I've madeâ¦
Iâve noticed when helping people to learn JS is that Iâm happy to let them learn
without any tools. In hindsight this is very strange. I wouldnât dream of
programming like this! I make mistakes all the time, and tools help me to catch
them early. Tools also help me to streamline repetitive tasksâ¦
SPOILER ALERT: If you're doing the 2017 Advent of Code, you may not want to read
onwardâ¦
SPOILER ALERT: If you're doing the advent of code this year, you may not want to
read onward. This post does not give any solutions away, but does contain
information about how I approached a part of the first challengeâ¦
After some years of browser vendors working out what web components should look
like, they're almost ready for the prime time. The part which I find most
intriguing (custom elements) has finally stabilised. With custom elements, you
can make new HTML elements which have custom behaviour which you define using
JavaScript. In this post I'll demonstrate a custom element for fuzzy countingâ¦
I've recently been attempting to code a clone of the classic game asteroids
using canvas in the browser. Since this is me, I've been distracted by all sorts
of programming detoursâ¦
I recently got it into my head that I wanted to build an arcade control panel
from parts. Specifically, an 8 way digital joystick and a bunch of buttons. How
it'll look when finished isn't important at the moment. It's enough now to say
that there'll be a joystick, six regular buttons, and two buttons for start and
select useâ¦
To many experienced Node developers, the title of this post will seem
intuitively obvious. Nevertheless, it's useful to see what unexpected behaviour
can occur when the two are used together. Here's an exampleâ¦
I recently attended ffconf, and was introduced to position: sticky;
. Support
for it is patchy, but where not available the header will scroll out of view as
it did in the past. Where available, the navbar will stick to the top of the
window when the rest of the header is scrolled out of viewâ¦
When I first put together the CSS for this blog I avoided a fixed header since
the header felt a bit large, and I didn't want to take up too much space which
could be used for contentâ¦
The npm CLI has a bunch of useful utilities for managing projects. The obvious
one is npm test
but there are others. I particularly like working with
npm version
(the subject of this tip)â¦
ES2015 bought a Set
constructor to JavaScript. It's pretty barebones,
consisting of a constructor which creates objects with a few methods for adding,
removing, checking if something is a member, and iterating over the set.
Instances have the essential quality of a set; an item is a member of the set or
not a member. Unlike an array, an item cannot be an element more than once. In
other words you can avoid using arrays and doing a lot of indexOf
checkingâ¦
Just before Christmas I gave a presentation on the upcoming async-await JavaScript language feature,
its basis in promises and generators, and finally a tiny server framework (like Express but a lot
leaner and more modular) which can make use of async functions as middleware (since an async
function is indistinguishable from a normal function which returns a promise). I'll introduce Toisu!
in a blog post soon, but until then here's the presentationâ¦
I use instanceof
a lot in JavaScript. It's very handy when writing unit tests. It's easier to do
an instanceof
check than it is to exhaustively probe an objectâ¦
This is a short companion to an
earlier article I wrote on using WeakMap
for
private data with JS classes. While private data belongs to instances, private methods can be shared
between instances of a class (just like its regular methods). An implementation using ES2015 modules
looks likeâ¦
This blog is built with a static site generator. The generator, the markdown source files, and the
generated HTML files are all kept together in the same git repository. Every time I commit a change,
a pre-commit hook runs the generator and adds the generated HTML, so that the blog entries are
always up to date. Then the changes are pushed up to GitHubâ¦
I touched briefly on the technology used in this blog in
a previous post, but I didn't explain the motivation behind a lot of
the choices I made when building it. I'd like to do that in this post. The design and architecture
of this blog is the product of what things I like in other blogs, and also those things that I find
frustrating. Where a choice was not obvious, I opted for the simplest option. The point of the
exercise was to get it online. Below are a few points in no particular orderâ¦
This blog took a long time to get started. Every time I tried to build it, I wound up focussed on
some tech I wanted to use to host it. In the previous iteration, I even
wrote a server framework. I took some holiday over the Christmas
period, so I decided to throw everything away and make something minimalâ¦
Private data has always been awkward in JavaScript. It's particularly difficult when it comes to
constructors, and with ES2015 recently published, classes too. Let's say we have an example class,
exported by an ES2015 moduleâ¦