In short
- The question
- A training practice needed a platform for activities with series and options, registrations in several languages, payments and invoices.
- Approach
- I map out what the practice needs, design and build the platform, and have run it since 2015.
- Delivered
- A platform of its own with registrations, online payment through Mollie, invoices ready for Peppol, gift cards, online courses and a website in five languages.
The context
Hilde Van Bulck is a trainer and coach. She teaches family constellations in workshops, series and online courses. Since 2015 I have been the only technical partner of her practice, Samtati: I map out what she needs, decide what we build and in what order, and build and run it.
From WordPress to a platform of our own
In the first years the site ran on WordPress, for a while with a shop in WooCommerce, and then on Squarespace. For what the practice needed, that fell short: activities with series, days and options, registrations in several languages, invoices. So from 2019 I built a platform of our own in PHP, and in 2020 it went live on hildevanbulck.com (opens in a new window), with accounts and in three languages. Since then it has grown with the practice: registration and payment through Mollie, invoices and discount codes, pages Hilde edits herself, and later gift cards, online courses and five languages.
Activities: the heart of the practice
Most of the practice revolves around activities: workshops, series and training days. An activity is more than a date with a price. It has series with days, three ways to price (per day, per day with two rates, or one price for the whole series), options with their own VAT rate, discounts and a teaching language, all of it in five languages.
I first had to draw that up as a data model, so that a single source of truth carries through everywhere. From that one record the site builds the activity page, the calendar, the menu, the offer, the sitemap and the structured data for search engines (schema.org/Event). Whether an activity can be booked, is full or has already started, the platform works out for itself. Hilde changes something in one place, and it is right everywhere.
Hilde edits the page herself
Hilde changes the text, photos and videos of an activity page on the live page itself, not in the small boxes of an admin. She sees straight away what visitors will see. You rarely come across that outside platforms like Squarespace, and it makes the work far more pleasant for her.
To build it, I put an editor into the page that only loads for admins: visitors get plain HTML. A switch toggles between editing and viewing as a visitor, and leaving the page with unsaved text asks first. A photo Hilde drags into the text goes straight to the server, is checked, resized and delivered as WebP. Whatever is pasted from Word gets cleaned up. And editing a page in another language turns it into a translation of her own, which the automatic translation never overwrites again.
Registration and payment
Registering takes three numbered steps: choose dates, choose options and fill in your details, with a summary beside it that recalculates live. Anyone not yet signed in signs in along the way, and the choices are kept. The server trusts nothing the browser sends: it traces every choice back to the activity itself, recalculates the price and refuses a registration if the series changed in the meantime. Discount codes, early-bird discounts and gift cards are checked again.
Payment runs through an integration with the Mollie API. The site creates the payment, sends the visitor on, and learns the outcome in two ways: the visitor coming back and a notification from Mollie. Every payment is processed exactly once, even when both arrive at the same moment. The platform calculates amounts in cents, as whole numbers, with one pricing module for the site and the admin: the price you see is the price you pay, with VAT per rate.
Invoices and credit notes follow one continuous numbering, refunds are tracked, and the platform prepares every invoice for e-invoicing through Peppol. Every quarter it produces a file for the accountant.
Gift cards
A gift card looks simple, until you build one. It has to be usable in parts, down to the cent, and two people checking out at the same moment must not spend the same balance twice. So the platform reserves the amount in a single database transaction, holds it while the payment runs, and gives it back if that payment fails or is refunded.
I designed the codes to be easy to read (without characters that look alike) and still impossible to guess, and anyone who tries gets blocked after a few attempts. A card can go out by email on a chosen day, without a separate scheduler. And together with the accountant I turned the VAT rules for vouchers into code, all the way into the quarterly export.
Online courses
Alongside the activities I built a learning platform. A course consists of modules and lessons with text, video, audio, questions and exercises. Access follows payment: after a refund the course closes by itself. A pathway bundles courses into one order, and anyone who already owns one pays a personal, proportional price.
The work was in the details. Participants’ answers stay with their question, even when Hilde adds or moves questions, and they are saved as you type. Videos sit behind signed links that expire after a few hours. The platform streams audio itself, so you can skip around, and the listening position is kept on the server: you carry on listening on another device. And anyone who requests their data or deletes their profile gets those answers along, or loses them.
The lessons include interactive exercises. Each exercise is one engine of my own in SVG and JavaScript, without a library, that works in a lesson, in a workbook and full screen, so Hilde can also use it live. Dragging and turning also work with the keyboard.
Signing in without a password
Participants sign in with a six-digit code they receive by email, or with a passkey. For the code I had to build the security myself: it is only stored hashed, expires after a quarter of an hour, and attempts and new codes are limited per address and per device.
For passkeys I built on a proven WebAuthn library, with checks of my own on top, because the details make the difference: challenges that only count once, a strict check of the origin, and only the public key on the server. Tests drive a real browser with a simulated authenticator and prove that attacks bounce off: a replayed response, a tampered signature, a foreign challenge and a missing CSRF token.
Five languages
The site exists in Dutch, English, French, German and Spanish, each with its own addresses, translated URLs and the right hreflang for search engines. Adding a language means adding a folder; the code knows no language by name except the source.
Every day AI translates what is new or changed, but with safeguards around it that I built myself. A fingerprint of the text makes sure nothing is translated twice. Images, video and code are taken out beforehand and put back afterwards. A translation in which the markup changes is rejected. And Hilde’s own translation always comes first.
An admin for the phone
Hilde often runs her practice from her phone. So I built the admin to work on a 390-pixel screen: a table that does not fit turns into one card per row by itself. A test opens every kind of admin page at that width and fails if a single one scrolls sideways.
Every email the platform sends can be checked there, in every language, at desktop or phone width. And if the normal sending fails, the same email goes out another way, so a confirmation never just gets lost.
Seeing what goes wrong
A platform that handles money and registrations has to be followed up. So I built a logbook of its own. Errors are grouped into one row per problem, and email addresses and IP addresses are masked. Anything that affects visitors or money emails me straight away, at most once an hour.
Every week AI writes a report from it, with read-only access and cleaned up, because logs partly come from strangers. That helps enormously, but it does not replace the work: I read the report, look at the problems in the admin, fix them and tick them off. Following up remains human work, and it takes time.
Safe and tested
The platform runs in Docker at DigitalOcean, behind Cloudflare, with a managed MySQL database and a nightly backup to another region. From the logs I drew up a Cloudflare rule of my own against scanners looking for known weak spots. Whatever slips through gets a bare 404 before any session or database is loaded.
Behind all that are unit tests and end-to-end tests. The latter drive a real browser through registration, payment, courses, pathways and gift cards, against Mollie’s test mode and never against production, and clean up their test data afterwards.
How I build
The platform runs on a light base of my own in PHP, without an external framework: a router per language, views, translations and a data layer. For years I built everything alone: the data model of the activities, the Mollie integration, invoices and credit notes, editing on the page, the move to Docker and the cloud, and the groundwork for Peppol.
Since 2026 I have worked with an AI coding assistant as a building partner. With it I refreshed and modernised the site and the admin, on the same base and on top of what was already there, and added gift cards, the learning platform, passkeys and five languages. The AI helps enormously, but I decide what gets built and in what order, write out the analysis and the rules, and review and test every change. The documentation grew along with it, into an extensive handbook.
Why it matters
Working for the same client for so long means living with your own decisions. The platform grew from a registration form into the backbone of the practice, and every step built on the one before.


