Blog

Moving Layout Builder Sites to Drupal Canvas

A shared Drupal 11 base for a fleet of brand sites, built on Canvas and a hundred single-directory components, and a pull-based importer that turns legacy Layout Builder pages into Canvas component trees in about three minutes per site, with 95% of a site migrated automatically on one stack and 80% on the other. What Canvas expects from your components, and what a migration into it looks like.

Moving Secrets out of the Database with Drupal's Key Module

Search credentials on our multisite platform lived in each site's config, which means in the database, in config exports and in every database backup. Moving them into per-site key files in the private file system took two migrations and changed who can set up search.

Drupal on Windows That Doesn't Hurt: DDEV and WSL2

Our Drupal environments on Windows took 30 to 40 minutes to bootstrap and the first CMS page load took ten. Moving the project into the WSL2 filesystem and running Docker inside it brought that down to five minutes and under one.

Upgrading a Drupal Multisite Platform from 9 to 11

Notes from taking an 88-site Acquia Site Factory platform through Drupal 10, 10.2, 10.3, 10.4 and 11: dead modules, orphaned extensions, config imports that run out of memory, and the deploy checklist that came out of it.

BLT Is EOL: Moving to Acquia CLI and Azure Pipelines

BLT used to build, test and deploy our Acquia Drupal platform. When it reached end of life, a few short shell scripts around Acquia CLI replaced it, and the pipeline went from 23 minutes to between 5 and 9.

Migrating a CDN from Cloudflare to Fastly

Moving a multisite Drupal platform from Cloudflare to Fastly is mostly DNS and configuration. The hard part is proving every domain really moved and still behaves the same. Here are the small scripts I used to check DNS, edge headers, caching and geolocation across the whole platform.

Measuring Cloudflare Cache Hit Ratio per Host

The Cloudflare dashboard shows a cache ratio per zone, but a zone can hold many sites with very different traffic. A small CLI on top of the GraphQL Analytics API gave me the number per host, which is what I needed to take a platform from 82% to 96%.

Managing GitHub Actions Secrets Across Many Repositories

GitHub's UI lets you set one secret at a time and never shows a value again. So I built a small web app that edits secrets in bulk and imports them from a .env file, using the same sealed-box encryption GitHub expects.

Building a DAG Workflow Engine in Go

My first workflow engine fit in a few hundred lines and looked parallel, but it wasn't. What I got wrong in that prototype, and how the engine behind BlockNext handles ordering, parallel branches, joins, retries and cancellation.

Running a Workflow Platform on 100 MB of RAM Without Redis

A fresh BlockNext install is seven containers idling at around 100 MB, and Postgres is nearly half of that. The trick isn't clever optimization. Every piece of scale-out infrastructure has an in-process default, and Redis only starts once something is configured to use it.

JSON Schema-First Executors for LLM Tool Calling and MCP

In BlockNext every integration node is described once, as a JSON Schema. That single description drives the UI form, input validation, the LLM function declaration and the MCP tool. Here is how it fits together, using the Slack node as an example.

Exposing Workflow Nodes as MCP Tools

Every integration node in BlockNext doubles as an MCP tool, so Claude or any other MCP client can use your connected services directly. What it takes beyond wrapping a function: credential references, an output shape MCP accepts, per-organization concurrency limits and a real OAuth 2.1 server.

Dropping Frames on Purpose: Low-Latency Streaming Without Queues

DisplayBridge turns a tablet or another computer into a second monitor for a Mac, aiming for under 16 ms end to end. The key decision was to never queue a frame. Plus a pure Rust session core behind a C ABI shared by Swift, Kotlin and desktop sinks.

LumoDine: Architecture of a Multi-Tenant QR Menu SaaS

LumoDine gives restaurants a QR code menu on their own subdomain, in many languages and currencies. The shape of the system: one API, two Next.js apps, a tiny redirect service, and a data model built around a single items collection and a separate graph of relations.

Cutting Solr Requests per Page View from Three to One

Every listing page on our Drupal platform hit Solr three times for a single page view, and every filter click took 700 ms to 1.5 s. Finding where the requests came from took one devel module. The fixes were a forgotten Views attachment, a load-more link and a missing Cache-Control header.

Replacing Solr Autocomplete with a Cached JSON File and Fuse.js

Search autocomplete sent a request to Solr on every keystroke, on every site. We replaced it with one cached JSON file per site and fuzzy matching in the browser. Now a visitor makes one autocomplete request per page, however much they type.

Ping: A Semver-Aware Release Notifier in Go

Ping watches the npm packages a team depends on and tells them when a version in their range ships. One Go binary, one Postgres database, no Redis or broker: the scan queue, the event bus and the delivery queue are all tables claimed with FOR UPDATE SKIP LOCKED.

Billing with Stripe, Paddle and MetaMask in One Product

BlockNext takes subscriptions and credit purchases by card through Stripe or Paddle, and on-chain through MetaMask. Three providers that work very differently, behind one small interface, a handful of optional capabilities and nine normalized events.