My thoughts, ideas, experiences, and ramblings
My writing on this website will span many different topics, ranging from
web standards, tutorials, mental health, thoughts and ideas, and general
musings. While the bulk of my writing will be technical in nature it will
vary from long form to short form and sometimes include video and audio.
Some content will be beginner-friendly, while other pieces will be geared
towards those who have been building for the web for some time.
On the last point, please note that I might occasionally misjudge the
experience level required for certain content. If you find something where
you believe I've got it wrong, please let me know on GitHub, and I would be happy to correct it.
To help you find the content you're interested in, I offer different ways
to browse my writing. Below, you'll find a list of tags to filter content
by topic. Additionally, all my writing is listed chronologically, allowing
you to scroll through or use your browser's find-in-page functionality to
locate something specific.
As with most things, this website will evolve and improve over time based
on the time I have to work on it and your feedback and suggestions.
One of the first features I want to add is the ability to search for
content across the blog. I believe a well-implemented search feature is
one of the most powerful navigational tools, enhancing usability and
accessibility. I plan to experiment with different implementations, and
once available, I would appreciate your feedback on the search results to
ensure the best possible experience.
I hope you find value in the writing you discover here.
Browse all posts
-
A deep dive into Blue Earth, an experiment that plots positive climate news stories on a rotating 3D globe using the HTML in Canvas API, Three.js, and a build-time pipeline powered by Claude and Geoapify.
-
A light-DOM custom element for CSS masonry layouts that uses display: grid-lanes when available and falls back to a spec-aligned JavaScript placement engine. Version 0.1.0 is ready for real projects.
-
The CSS property type validator now catches type mismatches at the point of assignment, not just at var() usage.
-
Learn how to configure Git to push your code to both GitHub and Codeberg with a single command, including SSH key setup and a handy shell alias for branch-specific control.
-
TypeScript 6.0 enables noUncheckedSideEffectImports by default, which causes a TS2882 error for CSS side-effect imports like import './style.css'. Here is what changed, why, and how to fix it.
-
What started as a question about a free macOS image viewer turned into a deep dive into pan and zoom math, pointer events, WheelEvent quirks, and a TypeScript web component. Here is everything we learned along the way.
-
The CSS Media Pseudo Classes Polyfill is now available on npm. This post covers what shipped, what I learned about the CSSOM and unsupported CSS, how you can try it, and what comes next.
-
CSS @property gives authors a type contract for custom properties, but no tooling enforces it at the consumption site. CSS Property Type Validator is an attempt to close this gap.
-
A layout that seems impossible; aligning titles and dividers across sibling cards regardless of content length. No JavaScript, no table layouts, just CSS subgrid.
-
A real-world exploration of how choosing the right HTML elements for interview transcripts solves both semantic and styling challenges in one cascading swoop.
-
What happens when you try to implement two seemingly straightforward CSS features as a JavaScript polyfill? You discover that specifications are simple because they made hard decisions, and the complexity does not disappear; it just moves.
-
How the new Set methods difference() and symmetricDifference() can replace verbose Set comparisons with clear, expressive code.
-
Timelapse is a progressive web app (PWA) with acollection of widgets that shows how much time has elapsed in the day, week, month, quarter, and year. Widgets and timezone are configurable.
-
How I built an eval-judge-improve loop to autonomously refine a semantic HTML agent skill, taking it from 2.46 to 2.89 out of 3.0 across four iterations and what I learned about the limits of automated improvement.
-
The CSS contrast-color() function lets the browser pick the most readable text colour for any background. Here is what it does, how it works, and why it matters for accessibility and the web.
-
How I structure prompts for AI coding agents to get considered implementation plans instead of premature code.
-
How combining JSDoc annotations with Object.freeze gives you literal type inference, runtime immutability, and better IDE support for JavaScript constant objects.
-
How I replaced my local .env file with Varlock and 1Password, gaining type safety, validation, secret scanning, and a single source of truth for environment variables.
-
Working with temporary directories in Node.js just became cleaner and more intentional with mkdtempDisposable and explicit resource management.
-
How to write a single hook script that works across Claude Code and Cursor, giving you deterministic control over agent behaviour when it matters most.
-
Working code isn't understood code. When AI-generated code feels hard to parse, that's a signal to ask questions, and sometimes, the answer leads to something better.
-
Take a fieldset, pour some radio buttons and visually hidden labels into it, wrap it in scroll-snap, and you have a clean, semantic horizontal scroller on mobile. What could go wrong? Well... there is nuance we need to talk about.
-
A practical walkthrough for when you realise your feature branch was created from the wrong base, covering git log, merge parents, cherry-pick, and bypassing commit hooks.
-
Manage anchor relationships with anchor-scope, leverage the Popover API's implicit anchors, and hide positioned elements gracefully with position-visibility.
-
A deep dive into the JavaScript concepts behind mocking HTMLImageElement behaviour in Vitest, including Object.defineProperty, Object.getOwnPropertyDescriptor, prototype manipulation, and WeakMap for per-instance state tracking.
-
How to structure an AI agent session with sequential tasks, review checkpoints, and explicit deliverables—turning a handoff document into actionable state machines, gap reports, and implementation plans.
-
How to structure a self-contained folder of specifications, screenshots, and Figma links that an AI agent can reference throughout an implementation planning session.
-
How to structure a handoff document that enables AI agents to perform gap analysis and implementation planning—with traceable acceptance criteria, UI state inventories, and explicit business logic.
-
Learn how to safely select DOM elements with special characters in their IDs or classes using CSS.escape() to avoid selector parsing errors.
-
Learn how to programmatically require the presence of a modifier key to enable scroll wheel zoom support in Leaflet maps.
-
How to use TypeScript’s triple-slash reference directives to load type definitions when type-checking JavaScript with JSDoc.
-
Learn how to use Node.js util.parseArgs() to simplify command-line argument parsing in your Node.js CLI utilities.
-
How to use deferred promises to control mock response timing in Playwright tests and avoid race conditions with instant responses.
-
AI coding agents have made me significantly more productive as an engineer, but they have a systematic problem: as context fills, they drift from explicit guidance and violate documented patterns. This examines AI limitations and the workflow adaptations that help while labs address the underlying issues.
-
Combining Zod's runtime validation with JSDoc's type annotations to achieve type safety in JavaScript without TypeScript.
-
Export your Algolia search indices to JSON without building custom export scripts using the Algolia CLI.
-
Build resilient anchor-positioned layouts that adapt when space runs out.
-
What I learned reviewing AI-generated JavaScript: real-world issues, code review tips, and ways to ensure robust, production-ready code.
-
Learn how to use the new CSS ::details-content pseudo-element to style the content area of HTML details elements with greater control and flexibility.
-
Exploring common misconceptions AI agents have about Visual Regression Testing and practical solutions to address them.
-
Take your anchor positioning beyond the grid with functions that give you pixel-level control over placement and sizing.
-
Discover how CSS anchor positioning brings native support for positioning elements relative to each other — no JavaScript required.
-
Learn how to use HTML invoker commands to open and close dialogs without writing any JavaScript.
-
What if we embraced authenticity, take creative risks, and live deliberately without fear of judgment - a reflection on finding freedom through self-acceptance in both personal and technical pursuits.
-
A deep dive into the CSS transform matrix, how it relates to the individual CSS transform properties, a look at the hidden powers of the function forms, and a dragon or two.
-
In this part, we will add a form to our profile page, use a dialog to display our form, deploy our page using Netlify, and set up Netlify to handle form submissions.
-
Harness the power of open source and an innovative culture to drive creativity and collaboration within your team—inspired by Mozilla, GitHub, OddBird, Igalia, and Factorial.
-
In part five of the series, we will complete our layout, add a favicon, and set up Open Graph meta tags for social sharing.
-
Learn about WCAG (Web Content Accessibility Guidelines), including WCAG 2.2 principles, conformance levels, and upcoming WCAG 3 changes, plus insights on accessibility certification value.
-
Learn how to use the HTML dialog element to create accessible modal dialogs for your web sites and applications.
-
Join me on my journey as I prepare for the IAAP Web Accessibility Specialist (WAS) certification, sharing weekly insights, resources, and study plans.
-
In part four of the series, we will do some refactoring of our CSS so that we take advantage of CSS custom properties. We will also complete the mobile layout by adding the LinkTree component to our page.
-
Learn how to build a responsive profile page with modern typography, media queries, and CSS Grid. Part three of our hands-on web development tutorial series.
-
Learn how to build a responsive profile page with modern typography, media queries, and CSS Grid. Part three of our hands-on web development tutorial series.
-
The financial pressures of modern life can make it hard to justify creative pursuits that don't promise immediate returns. This post explores the hidden costs of creativity in tech and society and the value of creative work beyond monetary gain.
-
In this post we will start implementing the design by working through some of the issues, learning more about Git and GitHub, get set up for development, create our first visual component, and learn about performance, CSS, and modern image formats.
-
In this part of the series we will break down the design into components using Atomic Design, set up our repository on GitHub, and create the issues we will need to work on.
-
Meet Project Calavera, a new open-source CLI tool that makes project configuration setup a breeze, especially for developers working outside the familiar framework ecosystems.
-
Learn how to use npm link to test your NPM packages locally before publishing to the registry. With some common troubleshooting tips and best practices.
-
This personal reflection explores how AI chatbots can support emotional growth and self-discovery, offering insights on using AI as a thoughtful companion while acknowledging its limitations compared to human connection and professional therapy.
-
Introducing Minimalist, a modern, lightweight, and customizable CSS library designed to provide a solid foundation for styling websites and web applications. Learn about its key features, technical details, and how you can get involved.
-
Unlock simpler web development with CSS's new individual transform properties—cleaner syntax, more intuitive styling, and delightful animations.
-
Learn how explicit return types in TypeScript can help you catch potential bugs early, improve code reliability, and create more predictable and maintainable TypeScript applications.
-
My takeaways from Zach Leatherman's talk on web components at the 2023 JSHeroes conference.
-
Why you should be careful copying and pasting proposed solutions from LLMs.
-
Perhaps it is the social bubble I find myself in, but it seems there is a lot of talk about gatekeeping happening at the moment. While the bubble metaphor does not quite work for what will follow, I do not have a better one, so humor me.
-
Git rebase is a powerful tool that allows developers to reorganize and clean up their commit history, such as by squashing or fixup-ing multiple commits into a single commit, which can be useful when submitting pull requests.
-
In late December of 2023, TPGi posted its list of the top accessibility errors found through its ARC automation tools in 2023. In this post I explain these errors and offer a solution.
-
While this post does not by any means aim to cover all the amazing things you can do with Intl.NumberFormat, I do cover two very common use cases you may have faced when formatting numbers in JavaScript.
-
In this post, I share 21 pieces of unsolicited advice for junior web developers. I emphasize the challenges of learning web development, encourage collaboration, and highlight the importance of web accessibility. Additionally, I discuss bootcamps, university degrees, and the value of learning to code.
-
In this post, I discuss why I care deeply about web accessibility, emphasizing its importance in ensuring equal access for people with disabilities and removing barriers to interaction with websites and applications.
-
In this post I share how open source empowers me as a developer, fosters community collaboration, and provides a platform for making a meaningful impact. Being part of the open source community is the best way for anyone new to the technology industry to gain experience and contribute to cool projects.
-
Sensible defaults for your Open Source project and community.
-
The topic of Polyfill.io and its sale came across my radar about a week ago when Tobie Langel shared a link to LinkedIn on the OpenJS Foundation Slack.
-
How do I handle type inference challenges with v-for in Vue 3 templates using TypeScript? Let's find out more.
-
A quick post on best practices when installing Nodejs on different platforms and managing multiple versions.
-
How do I merge one repository into another without losing commit history? This is a quick guide on how to do this.
-
A step by step guide to publishing a simple CLI tool to the NPM registry.
-
This post will look at starting a new Vue project using the Vite toolchain.
-
Using the Nodejs EventEmitter with GitHub webhooks
-
Learn how to filter documents in a MongoDB collection by the size of an array field.
-
When running your Playwright tests, how do you load a different set of data based on the current execution environment?
-
An introduction to Flexsearch and its tokenizers through writing and interpreting tests.
-
How to cancel asynchronous operations with the AbortController API.
-
Usng the special Vuejs is attribute to fix common DOM parsing caveats.
-
There are a couple of steps to take when switching from the older babel-eslint to the newer @babel-eslint. No worries, I'll show you how.
-
Let’s work through the process of improving a basic GitHub Action CI workflow to cover multiple Node.js versions and operating systems.
-
How do you style the cursor in CodeMirror 5? Also, how can you do this for light and dark themes? Let's take a look.
-
Could it be that the == operator in JavaScript had a bad rap and it’s time to reconsider it?
-
It’s October, which means pumpkins, candy, costumes, and Hacktoberfest. If you are completely new to open source and contributing on Github, but want to join in the fun, read on.
-
Some thoughts on the current state and challenges with regards to building a PWA in 2021.
-
Ok so, this is very different from what I usually post. It is also, hands down, the hardest post I have ever written. But, there is no point in keeping this to myself. No achievement is unlocked by suffering in silence. No medal for pretending everything is A-OK.