Martijn Stegink

Approach

Rebuilding the volleyball club website

September 28, 2026 · vvouderkerk.nl

Our volleyball club ran on WordPress. That was once the obvious choice, and for what we did with it, it had become far too much. We publish a news item every few weeks, we keep a list of teams, and we put the training times online. For that we had a database, a theme, a stack of plugins and a hosting bill of several hundred euros a year.

The complexity showed in the work. Putting the teams online in a way that looked decent meant fiddling with tables. News items and agenda items each had their own configuration, and neither was simple. The registration forms were a combination of Google Spreadsheets and forms inside WordPress, which meant two places to maintain and two places where something could quietly stop working. The site was dynamic while nothing about our content asks for that.

What I wanted was the other end of that. A site that is plain files, cheap to host and easy to hand over. And I wanted to publish with AI: give it a few keywords, let it write the item, and put it on the site after I approve it. That last part was the actual reason to start.

The site is now Hugo with the Blowfish theme, in a private repository on GitHub, built and published by Cloudflare Pages. Every push to the main branch is live within two minutes. There is no server of ours anywhere, and since the middle of September there is no working copy on a Mac either. GitHub is the source, so the site can be managed from any machine.

Content came over from the old site first. Four policy documents and twenty news items, pulled out of a scrape of the WordPress pages and converted to markdown. The pages that were awkward in WordPress became small building blocks of my own instead: one for a team card, one for a training day, one for an agenda item, one for a photo. A team card takes a name, a training time, a link to the competition page of the federation, and the players as a comma separated list. The agenda lives in a single data file that feeds both the agenda page and the block on the home page, and items that have passed disappear on their own.

The registration forms are one form now instead of four. You pick what you are signing up for, and the form shows only the fields that belong to that choice. A beach registration goes to a different mailbox than the rest, which the form switches by itself. A static site cannot send mail, so the sending runs through an external service.

Functionally, the result is what I was after. I give Claude a few keywords and it writes the item, picks the file name and the date, and places it. When I write something about the club lottery that starts on a certain date, it recognises that this belongs in the news and in the agenda, and it makes both. Removing an item is one instruction. I do not have to decide on a structure in advance either, because I can ask for a proposal, adjust it in a sentence, and approve it. Tonight I added the location of a meeting to a news item and an agenda entry, and it was live before I finished reading the confirmation.

Plenty went wrong on the way, and some of it was my own doing.

The worst one was a form that silently swallowed half a registration. Someone filled it in with the browser translating the page. The script that decides which fields to show compares the chosen option with the Dutch word, and the browser had sent the English one. All the fields that belonged to that choice stayed hidden and disabled, so they never reached the mail. Hidden fields are not checked for being required either, so the form let itself be sent. We got a registration with a place of residence and a date of birth and no name, no address and no way to reach the person.

I also documented an installation script that only existed on my own iMac. It was never committed, the documentation pointed at a raw GitHub URL, and raw URLs do not work on a private repository. A reference in documentation is not proof that a file exists.

Then there was a full width white bar behind the header, which I built with a clip-path. That quietly cut away the mobile menu, because that menu is technically a child of the header. On a phone the menu opened and showed nothing but a sliver.

Moving the repository to the club account broke the connection with Cloudflare Pages, and a Pages project has no setting to point at a different repository, not even through the API. The only route is a new project, new build, move the domains, delete the old one. I spent an evening on that.

And a small stupid one: news cards are cropped to three by two, so the square club lottery logo I put in as a preview image lost its head and its feet.

What I would do differently is start with the data before the pages. Teams and training times went in as nested building blocks, which looked fine but cannot be turned into a form. To get an admin interface, that content has to move into data files anyway, so now it is being converted after the fact. The agenda was set up that way from the start and needed nothing.

I would also have put everything on the club’s accounts on day one. Building it on my own GitHub and my own Cloudflare account was the fast route, and moving it later cost more than doing it right would have. Everything sits on the club now: the repository, the hosting, the domain and the mailbox that all of it hangs from. Whoever takes over gets the mailbox and can reset the rest. That is the test I hold every choice against.

Worth a look if you run a small club or association yourself: vvouderkerk.nl. The technical parts underneath are the same ones large sites use.

What you need. A GitHub account, a Cloudflare account, and an AI that can use a shell. And a domain name. The domain costs about ten euros a year. The rest is free at this size and stays free, because the site is plain files and there is no server to pay for.

Avoid my mistakes. Put everything on the organization’s account from day one, not yours. And decide who publishes before you start. With one person who is comfortable in a chat you need nothing else. Otherwise you need something extra, and that is the work.

Then get AI to do the work for you. Give it the context, tell it what you want to achieve and which components you want to use, and ask it for a plan and a first draft before it builds anything.

Based on my own project folder for the VVO website, September 2026.

Updates

An email when there's something new.

At most one a week, and often less. Unsubscribe sits at the bottom of every email.

Your address goes to Substack, and it is used for this mail only. I don't share it.