Skip to main content

Moritz L'Hoest and the habit of writing it down

Moritz L'Hoest was on my list of potential guests for a couple of years before I wrote to him, and I was waiting for an occasion to get in touch.

It started with the name. An apostrophe in a German surname is unusual enough that you wonder how it is said out loud, and once you have wondered that, you start noticing where the name turns up. It turned up in the Craft Discord and on Stack Exchange, almost always in an answer rather than a question.

Then in May 2025 he published a video course on CraftQuest, an introduction to multi-language sites in Craft, and I finally had a reason to write. I sent a LinkedIn message. It turned out he already knew the podcast. We recorded in August, and the episode went out on the 13th.

A career by accident

Moritz has been a web developer since 2017, at Schwarzdesign, an agency in Cologne, where he started as an intern and never left. He studied something media-related, did some video production, built a website for a student association and one for his sister, and then needed work.

I needed a job, basically. It wasn't my dream, and it's still important to me that it's not the only reason I live. It's not the only thing I can do. If this all goes away, I could do other things. But I like it, and I'm not planning on going anywhere.

— Moritz L'Hoest

That last part stayed with me, because I'd answer the same way. This wasn't my dream either. For about three years the dream was cartoonist, and I got as far as a few cartoons in two anthologies, plus a third one I edited myself. I'd still struggle if web development went away, but freelance journalism paid my rent for years before this, and there's an e-business degree I worked hard for. I'd find something.

Thrown in the deep end

Moritz's first serious project was Drupal 8, at a moment when it was a different system from Drupal 7 and everything you could find online no longer applied. The project lead had left the agency. He was neither very good at web development yet nor at Drupal, and had to learn both at once.

He is careful about how he describes what followed. Not that Drupal is a bad system. That it was too difficult for him at that point, and that he got burned by not having the experience to work with it properly. His girlfriend at the time told him he complained every time he came home.

He finished the project. The next ones were fun. That, rather than any particular moment of revelation, is how he decided this was something he wanted to do.

The years with ProcessWire

After Drupal, the agency found ProcessWire, and Moritz found the thing he had been missing: build your own content model, write your own templates, no rigid structure imposed on you. They bought most of the commercial modules, built an in-house starter kit that grew into a small framework, and integrated Twig because PHP templates without inheritance got messy fast.

And he started writing. First answers in the ProcessWire forum, then long-form tutorials, then a site of his own, ProcessWire.dev, where he explained things the official documentation did not: namespaces, autoloading, how ProcessWire's custom autoloader differs from PSR-4.

It was just a nice way to formalize my own knowledge and structure my knowledge in a way that I can look up and refer to.

— Moritz L'Hoest

He is explicit that answering questions taught him more than asking them. Writing forces you to structure what you know, and the moment you cannot finish a sentence, you have found your gap.

The site is still online five years after the last edit, built with a static site generator and hosted on Netlify, costing nothing and requiring no updates. He thinks he should probably put a disclaimer at the top.

And it produced something he did not plan. ProcessWire.dev got featured in the ProcessWire newsletter. A developer who was using ProcessWire and looking for work found the site, followed the link back to Schwarzdesign, saw the job posting, and applied. He is now Moritz's long-term colleague and a good friend.

That is the argument for community work in one anecdote, and it beats the ones people usually make.

Ceremony

The reason the agency left ProcessWire was version control, and this is where the conversation stops being a career story and becomes a position.

I’m a nerd for version control. You got to know that about me.

— Moritz L'Hoest

He wants to be clear, and says so repeatedly, that ProcessWire can be version-controlled. You can do it. But it was not built for it. You do not run a Composer command and get a repository that excludes the core. You download a zip, unzip it on a server, and end up with a mixture of folders: some core, some yours, and some in between. The assets folder holds your logo, which you want tracked, and user uploads, which you do not.

To get the full benefit, you had to stop using the backend to create fields and entry types and write migration files instead, in an undocumented format, guessing at setting keys. A lot of what makes ProcessWire pleasant, he says, goes out the window at that point.

He asks what the point of version control is if you can't go back to a specific state, because going back means the templates, the database, the entry types, and the fields, all at once.

I'm just doing it by rote. It's just ceremony. I'm not gaining anything from it.

— Moritz L'Hoest

So the agency stopped. Not the CMS, the version control. They decided it was not worth the hassle when they could not get most of the benefits, and worked off a shared development server where people mounted folders and asked each other whether they could edit the main SCSS file right now.

I've worked on projects like this. Most of us have. The repository exists, commits happen, and it buys you nothing, because half of what defines the site lives in a database nobody is tracking. It takes a certain rigor to call that ceremony instead of calling it good enough.

They moved to Craft in 2021, starting at 3.4, by which point Project Config was already in place. He says it was already the system he wanted it to be.

Loving something and knowing what's wrong with it

Moritz gave a thirty-minute talk at Dot One in Amsterdam about why Project Config and version control work so well together: it is declarative, you describe a state rather than a chain of migrations, and you can go back to any point in time. He calls it his manifesto and says that if you are only going to watch one of his talks, watch that one.

In the same conversation, he explains what is architecturally wrong with it.

Project Config was not in Craft from version 1.0, and you can tell. The control panel is an interface to the database, and it also modifies Project Config. So a change can arrive by two different routes, and they do not always behave identically. Something works when you do it in the backend in your dev environment and does not work when it arrives via Project Config in production. A queue job that should be created when a setting changes gets created in dev and not in production. Something soft-deleted comes back in one environment and not the other. He has filed all of these on GitHub. They were all fixed.

A hundred and twenty issues

He has opened around 120 issues on the Craft CMS GitHub. He mentioned it in passing, and did not seem to think it was remarkable.

I asked him about it, and he shrugged it off. He runs into small problems and small regressions; he writes them up, and they get fixed.

That's the most important thing for me, that issues get addressed, not that they don't happen.

— Moritz L'Hoest

Two things he did are worth following, and I only found them after the recording. In March 2023, a pull request had been open for months that would summarize an entry's validation errors at the top of the page. It missed the 4.4 release. Moritz turned up in the thread to ask why. Error messages in Craft, he wrote, had far too little visibility. Several of their clients had run into trouble because they missed the small notice in the bottom corner indicating that an entry hadn’t been saved. One had lost a lot of work that way, and the agency had apologized because they could not, in good conscience, call it the client’s fault when the system communicated a failure so quietly. He asked for the feature to be prioritized, specifically on accessibility grounds.

Brandon Kelly replied the next day: he hadn't got to the review in time for 4.4, it was planned for 4.5. It shipped that August. I wrote about Craft 4.5 two weeks after it came out. There is a section in that article about the new validation summaries. I had no idea where they had come from.

There is a second one. In June 2024, while the Link field was still an open pull request, Moritz asked whether element links could take a suffix, a fragment, or a query string, as Hyper and the Typed Link Field allow. Brandon's answer was that a separate custom field would cover it. Seven months later, Craft 5.6 shipped an "Advanced Fields" setting for Link fields, and one of its seven options is URL Suffix. Whether the comment caused it, only Pixel & Tonic knows. But the request is on the record, and so is the answer.

A hundred and twenty is not a normal number. Most developers hit the same bugs and work around them, or mention them in a Discord channel and move on. Filing an issue costs half an hour you cannot bill for: reproducing it, writing it up, and answering the follow-up questions.

He also has an open pull request to add proximity search to Craft, so you can query addresses by distance from a point and sort by it. Nobody has looked at it. He calls it more of a proof of concept and says it needs work, and mentions it without any bitterness.

A hundred and twenty issues, one unread pull request, a site of tutorials for a CMS he no longer uses, two conference talks, a video course, and years of Stack Exchange answers. It is the same behavior every time: notice something, write it down, hand it over. Sometimes it produces a colleague. Sometimes it sits in a queue. Sometimes it turns up in a release you write about without knowing whose idea it was.

Accessibility is not a checkbox

Accessibility comes up as one of the quality standards his agency publishes on its own site, and he is impatient with the version of it that consists of sprinkling ARIA roles over finished markup. Semantic HTML first, he says. A redundant ARIA role is worse than none.

I want the web to be inclusive and accessible to everyone. And the cool thing is that 99% of the time, good accessibility is just good user experience, good UX, good performance. So if you make it accessible, you make it better for everyone.

— Moritz

His example of what tools cannot catch has stayed with me. Run an automated audit, and it will tell you your heading levels are in order. It will not tell you that your headings are marketing language that describes nothing. You can tab through the landmarks of an events page, he says, and still have no idea which events are current and which are past, because the labels are terms that mean something inside the company and nothing outside it.

At Schwarzdesign, accessibility is checked in pull request reviews. It is in the workflow, which is the same instinct as everything else he does: if it is going to happen reliably, it has to be written into the process rather than left to good intentions.

The computer goes off

At some point it became important that I'm not sitting eight hours a day in front of a computer, and then I get home and I'm sitting in front of a computer.

— Moritz L'Hoest

The book he recommends is The Pragmatic Programmer, which he read early and says he needs to read again. Not for a language or a framework, but for what he calls professional development: taking responsibility for your own work, being proud of it, approaching a project in a way that will not blow up.

That explains the rest of him better than anything else he said. A hundred and twenty issues nobody asked him to file, and a CMS he left because the version control it allowed was ceremony.

Thomas Sausen

Webentwickler

Selbstständiger Webentwickler, der 2005 mit WordPress-Websites anfing, dann zu ExpressionEngine wechselte und 2013 sein Herz an Craft CMS verlor. Als Gründer von Craftentries, berichtet er seit 2015 über das Craft-Ökosystem.