Christopher Bennell

I build web stuff. Full Stack/Platform Engineering/Architecture. Senior Software Engineer.

Articles

• 4 min read

Site Redesign Postmortem

After a redesign of this site, I share some thoughts on the unexpected benefits and surprising lessons of vanilla CSS.
• 3 min read

I Tried Three CSS Frameworks So You Don't Have To

I tested OpenProps, Bulma, and TailwindCSS while migrating to Bridgetown, and found they fall on a revealing continuum from pure CSS custom properties to all-in utility classes. Here's what I learned about each approach.
• 2 min read

Bridgetown, TailwindCSS and Kamal: A Tricky Deploy Bug

Deploying a Bridgetown site with Kamal? Watch out for a sneaky Tailwind bug. When the jit-refresh.css file is gitignored, fresh checkouts fail silently during the build process, stripping all your Tailwind styles. Here's how to fix it with a simple esbuild plugin instead of patching your Dockerfile.
• 3 min read

Migrating from Wordpress to Bridgetown

I've used WordPress for many years. It no longer suits my needs as well as it used to, so I've been investigating alternatives, inlcuding migrating this site to Bridgetown, a Ruby-based static site generator. And the switch feels principled and liberating.
• 3 min read

Running WordPress Multisite on Hetzner with Custom Domains

After many years with Ionos, I finally made the switch to self-hosting on Hetzner. In this post, I walk through spinning up a VPS with WordPress preinstalled, hardening it with SSH keys and UFW, and configuring WordPress Multisite to serve multiple domains.
• 2 min read

Default, Dynamic Slot Content in Rails ViewComponents

Ever wished your ViewComponent slots could have dynamic defaults? In this post, I show how I built an Alert component that automatically picks the right icon for its type, but can easily swap in a spinner or any custom icon with a single line of code.
• 3 min read

Filtering by Association Count in Complex Models in Rails

Filtering complex associations in Rails can get tricky: built-in methods like where.associated don’t always provide efficient results. Here’s how I used a SQL subquery inside Rails scopes to make a slow page fast again.
• 3 min read

Rails "Disable-able" Button ViewComponent / Phlex Component

Need a button that enables or disables itself in response to events? I explain how to build a reusable DisableableButton in Rails using ViewComponent (or Phlex) plus a tiny Stimulus controller—perfect for forms where you only want to allow submission once inputs are valid.
• 8 min read

Building an LTI DeepLinking Response in Rails

DeepLinking lets your LTI tool send content back to the LMS—like inserting rich HTML into Canvas’s editor. This guide walks through persisting launch data, building a response form, rendering Rails views into JWTs, and even making the whole flow dynamic with Turbo.
• 6 min read

Handling LTI Launches in Rails

Learn how to set up your Rails application as an LTI Tool Provider, to handle LTI 1.3 launches from an LMS, including the OCID workflow, user authentication and what to do with the information you get from the LMS.
• 6 min read

What's in a Canvas LMS LTI 1.3 JWT?

What’s inside an LTI 1.3 JWT? This post walks through a Canvas launch token claim by claim, so you can decode and understand the data your Rails app receives.
• 3 min read

Parameterized Modules in Ruby

Ruby lets you use `[]` for more than arrays—and that opens the door to clever tricks like parameterized modules.