A year ago, the Marais Biestebroeck Alliance came to the school to present their fight: 1.5 hectares of wetland in Anderlecht, threatened by a property development. A workshop, work picked up again in spring, a mockup approved by the association. This autumn, in one month, we built it. The site is live.
The teaching problem
A web development course always hits the same wall: the fictional project. Students code a page for a client who does not exist, with a deadline that is not one, and the work ends up in a folder nobody will ever open. The grade comes in, the code dies.
The Marais Biestebroeck Alliance changed the terms of the problem. A real association, an ongoing fight, a permit already granted to the property development called The Dock. The launch date was not negotiable: it depended on how the case was moving, not on the academic calendar.
Thirty-nine blocks, twelve authors
The « History and context » page is a horizontal timeline telling the story of the wetland, from the sixteenth century meadows to today's protest. It holds 39 blocks across five sections: history, context, neighbourhood, protest, today.
Each block belongs to one student, several per person. For each, two files and the right to touch nothing else: NN-slug.php for the HTML, NN-slug.css for the styling. The page assembles them on its own.
<?php foreach ($evenements as $evenement) : ?>
<?php if (file_exists('template-parts/timeline/' . $evenement['fichier'] . '.php')) : ?>
<?php include 'template-parts/timeline/' . $evenement['fichier'] . '.php'; ?>
<?php else : ?>
<?php include 'template-parts/timeline/a-faire.php'; ?>
<?php endif; ?>
<?php endforeach; ?>
Five lines of PHP carrying the whole setup. The else is the key piece: if a student's file does not exist yet, the page shows a grey box naming the expected files. Nobody can break everyone else's page by not handing in their work.
The contract
Twelve people in the same repository, thirty-nine blocks sitting side by side, means as many ways to break everything. The frame comes down to a few rules, written before the first line of code.
- Every CSS rule starts with the block class -
.evt--04-prairies-1550prefixes every selector. Nobody can reach someone else's block, even on purpose. - The variables are imposed - colours, fonts and sizes come from
tokens.css, taken from the approved Figma mockup. No hardcoded value, so no visual drift across 39 blocks. - Two files, not one more - the timeline mechanics, the navigation and the data are shared: they go through a pull request.
- Every image carries an alt that describes it - starter blocks ship with
alt="", and filling it in is the student's job. - No PHP inside a block - HTML and CSS only. The logic stays in the teacher's files.
The height is imposed too: each block takes exactly one screen, position bar included. The width, however, is free. It is the only room to manoeuvre, and it is enough to make 39 blocks feel different.
From prototype to WordPress theme
The prototype was there to build the timeline in class. The delivered site, however, had to stay alive without us: the Alliance adds an event, a press clipping, a resource, without ever touching a file. Hence a custom WordPress theme, marais, with no page builder and no parent theme.
Three content types carry the site, declared with ACF and versioned as JSON inside the theme:
| Content type | Taxonomy | What it feeds |
|---|---|---|
| Events | Section | The timeline, the key moments on the home page, upcoming actions |
| Press | - | The press review |
| Resources | Resource type | Downloadable documents |
Nine ACF field groups complete the set: home page, contact details, petition box, event, media, press, resource, section, theme. The acf-json files live inside the theme, so a single deployment carries the structure from one environment to the next.
The timeline, WordPress side
The inc/frise.php module rebuilds the timeline from the events. A block a student handed in keeps its own layout; the others go through a generic block that takes the colour of its section. So the Alliance can add an event long after we left: it slots into the timeline, in the right place, with no design to write.
Tinting photos on upload
The mockup calls for tinted photos, one colour per chapter. Asking the Alliance to do that work on every image would have killed the whole thing. The theme does it instead: when an image is uploaded, it produces three tinted copies, stored separately.
uploads/marais-teintes/185-brun.jpg 1600 px, full width
uploads/marais-teintes/185-brun-moment.jpg 960 px, cards on the Alliance page
uploads/marais-teintes/185-brun-vignette.jpg 450 x 300, home page banner
The number is the attachment ID. That separate folder comes from an incident. Dropped next to the original under the name photo-brun.jpg, the copy overwrote another image uploaded under that very name, then deleted it along with the original. A dedicated folder and a name built on the ID settle the matter for good.
A user guide inside the admin
A custom theme without documentation turns back into a black box the day you leave. So the theme adds a « User guide » page under the Events menu, and a « How do I fill in an event? » link right inside the edit screen. The page opens on top, served on its own, without the WordPress menu or toolbar, the way a plugin details sheet does.
The rest of the theme follows the same logic: inc/og.php builds the share previews for every page, inc/admin-evenement.php rearranges the edit screen, inc/affichage.php gathers the helpers shared by the templates. Eight page templates, two post templates, no builder plugin.
Deployment as a teaching tool
Each student puts their own block online, from VS Code, with a Node script and a .env file that never leaves their machine. The demo site updates within the minute.
That detail changes how the work feels. A block that does not render, a wrong image path, CSS spilling over: it shows immediately, in public, next to the others. The correction no longer comes from the teacher, it comes from the page.
The timeline
| Step | When | What happens |
|---|---|---|
| Workshop | Autumn 2025 | The Alliance presents their fight at the school |
| Design | Spring 2026 | Students pick the project up again, Figma mockup |
| Approval | 28 September 2026 | « FINAL » mockup approved, CSS variables extracted |
| Development | September to October 2026 | One month: 39 blocks, five pages, the WordPress theme |
| Launch | October 2026 | maraisbiestebroeck.be |
A year between the first meeting and the site. One month of actual development. The gap between the two is how long it takes for a student project to become just a project.
What I learned
- Constraints set you free. The stricter the rules on what is shared, the more real the freedom on what is not. The 39 blocks look related without being identical.
- A grey box beats a blank page. Falling back on
a-faire.phpdid more for the calm of the project than any deadline reminder. - A real client does not negotiate quality. The Alliance approved a mockup, not an intention. What shipped had to look like it.
- Automate what you cannot demand. Tinting called for graphic work on every single image: the theme does it on upload, and the constraint disappears.
- A delivered site documents itself in its own admin. The user guide lives inside WordPress, not in a PDF nobody will ever find again.
- It is still a school project. There are rough edges, some blocks weaker than others. The site is live anyway, and that is the point.
See the site
The timeline, the Alliance's alternative vision, the press review and the petition. Project run with Hélène and Sébastien, and the third-year students of Haute École Francisco Ferrer.
maraisbiestebroeck.be