Skip to main content

Why Your Curling Club Shouldn't Use a CMS

· 9 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

We know that many of our clubs use WordPress or Joomla for their curling websites. These are popular platforms, and for good reason: they're flexible and there's no shortage of tutorials and plugins. But that popularity comes with a serious downside. General-purpose CMS platforms are massive targets for hackers, and the threat has been escalating rapidly. Here's what you need to be aware of.

Automate Club Management With AI

· 5 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Imagine you're a club manager setting up next season. You open your AI agent and type (or just say):

Set up early bird pricing for the Tuesday Night League. 15% off if they register before September 1st.

Five seconds later, it's done. No browser tabs, no forms, no clicking through menus. With Curling IO v3, this is something you'll be able to do.

Custom Registration Forms Are Coming to Curling IO

· 3 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Registration forms in Curling IO have always collected the basics: team name, lineup, skill level, contact info. But every club runs things a little differently. Some need emergency contacts. Others want dietary restrictions for banquet planning. A bonspiel might ask for team contact information while a league doesn't.

In v2, admins can already choose which questions appear and create custom ones. What's new in v3 is control over the layout: where each question sits, how wide it is, and how the form is organized into sections.

LiveView Admin Panel w/ Gleam and Lustre

· 11 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Curling IO's admin panel has dozens of pages: product configuration, discount rules, affiliate fees, registrations, event scheduling, reports. In Version 2, every form submission reloads the page. Click save, wait for the round trip. It works, but it's slow when you're editing multiple sections on the same product, and it makes features like live toggle switches or inline editing impossible without sprinkling in JavaScript.

Version 3's admin is a single Lustre server component running on the BEAM. One WebSocket connection, one long-lived Erlang process per session. Every interaction goes over that WebSocket and comes back as a DOM patch. The page never reloads, and there's no client-side JavaScript framework. The entire admin UI is written in Gleam, compiled to Erlang, and runs server-side.

AI Agents Love Gleam

· 12 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Fair warning: this post contains some opinions that are going to be controversial and may not age well. Here be dragons.

AI coding agents like Claude Code, OpenAI Codex, and Google Gemini can write code, run it, read the errors, and try again. That loop is the whole game. The faster and more informative that loop is, the more useful the agent becomes. After building Curling IO Version 3 in Gleam alongside AI coding agents, I'm convinced Gleam is the best language for this workflow. Agents don't write better Gleam - there's less training data. But Gleam's compiler lets agents self-correct without waiting for a human.

Parallel Tests for Free

· 5 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

While writing the previous post about our per-test SQLite databases, I was describing how each test gets its own in-memory database, no shared connections, no shared state. And I thought: wait, if nothing is shared, can we just run them all at the same time?

Turns out we could, and our server test suite went from ~4 seconds to ~0.85 seconds for around 800 tests. Zero code changes to the tests themselves. One 25-line Erlang module.

Test Isolation for Free with SQLite

· 9 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

Most web frameworks treat test database isolation as a hard problem. Rails has database_cleaner with three strategies. Django wraps every test in a transaction it rolls back. Phoenix does the same with its SQL sandbox. They all exist because tests share a single database server, and that shared state is the root of flaky tests and ordering dependencies, the kind where a test passes alone but fails in the suite.

Curling IO Version 3 doesn't have this problem. Each test gets its own database. Not a transaction. Not a truncated copy. A completely independent in-memory SQLite database, cloned from a template in microseconds using SQLite's backup API.

Why We Chose SQLite

· 11 min read
Dave Rapin
Dave Rapin
Founder @ Curling IO

We assumed PostgreSQL for Version 3. After a decade running Postgres in production, why would we even consider something else? We knew the tooling, the failure modes, the operational playbook. Postgres is the safe choice for good reason.

Then we looked at what "self-hosting Postgres" actually involves, compared it to what Litestream does for SQLite, and changed our minds. This post covers the decision, the architecture, the trade-offs, and why we'd make the same call again.