Over-engineeren van ons eigen kerstdiner

Bij 10KB sluiten we het jaar af met een diner. Al 13 jaar. Van een simpele lunch is het uitgegroeid tot een avond met partners, een MasterChef en een programma. Vorig jaar speelden we een moordmysterie tussen de gangen van het diner door: Glittersby, een Engelstalig kant-en-klaar pakket met setting in de jaren '20. Dertig mensen aan tafel, dresscode met thema en iedereen in character. Het was een groot succes en hebben er nog lang over doorgepraat.

  • Roland

Written by Roland

Het was zo'n groot succes dat we een jaar later hetzelfde concept nog een keer wilde organiseren. Maar zoals altijd als we iets een tweede keer doen, vragen we ons wel even af: waar kan het beter? De Engelse teksten van vorig jaar waren leuk, maar niet iedereen spreekt even vlot jaren '20 slang. En hoewel het plot vermakelijk was, miste het een persoonlijke touch en was het een klein beetje vlak opgezet. Ewout en ik keken elkaar aan: "Volgens mij kunnen we dit zelf bouwen."

Dus besloten we het te proberen. Zoals ieder jaar organiseren Ewout en ik dit zelf als verrassing voor de rest.

Wat er het afgelopen jaar mogelijk werd

We gebruiken dagelijks AI voor ons werk. In het afgelopen jaar zijn mogelijkheden weer flink verbeterd: Opus, Nano Banana Pro voor afbeeldingen, Cursor met agents. Elke maand werd er weer iets mogelijk dat een maand eerder nog niet kon.

Een moordmysterie voor 30 personen heeft 120 unieke teksten nodig: backstories, motieven, wat iedereen in welke ronde zegt. Dat handmatig schrijven naast je gewone werk gaat niet lukken, maar met de tools die we nu hadden wilden we het proberen. En toen dat eenmaal werkte, kwam de creativiteit los.

Begin november startten we met een conceptdocument. Opus genereerde meerdere plots; wij kozen de versie die realistisch was, niet te ver gezocht, met een verhaallijn die zich mooi kon ontwikkelen. Het thema werd de MS Ruby Riviera: een cruiseschip, jaren '50, La Dolce Vita-stijl. Zonnig, mediterraan, en een goede dresscode.

Opus genereerde de teksten, alle 120, maar niet zonder sturing. We vulden het plot met 10KB-specifieke referenties: het huis dat een collega aan het verbouwen is, het geheime huwelijk van twee anderen, de baby-discussie op kantoor. Geen generieke karakters, maar overdrijvingen van onszelf.

Om de moeilijkheidsgraad te testen lieten we LLMs het spel tegen zichzelf spelen. We gaven het model alle informatie van ronde 1 en 2 en vroegen: "Wie is de moordenaar?" Als het antwoord te snel kwam, waren de hints te expliciet en pasten we ze aan.

"We gaan dit toch niet uitprinten?"

Als alle teksten als markdown in een git repo staan, gaan we ze natuurlijk niet uitprinten op A4'tjes. Dus twee weken voor het event, begonnen we aan een Progressive Web App (PWA).

Persoonlijke login voor iedereen. Real-time vrijgeven van teksten. Push notifications. Een dashboard voor ons als spelleiders. We speelden zelf mee als Staff Captain en Hotel Director, met een alibi dat we in Palermo waren op het moment van de moord.

Een paar weken voor het event kregen deelnemers al hun eerste notificatie: een uitnodiging om de app te installeren en hun personage te bekijken, compleet met dresscode-hints.

De app groeide snel. Eerst om de karakterbeschrijving te lezen. Om dat scherm wat interessanter te maken genereerden we portretfoto's via Nano Banana Pro. Op basis van echte foto's van collega's en hun karakterbeschrijving kreeg iedereen een gepersonaliseerde jaren '50-versie van zichzelf.

Daarna kwamen de persoonlijke teksten per ronde, push notifications, een visuele tijdlijn en scheepsplattegrond van ons kantoor. Tot uiteindelijk volledige puzzel-integraties met QR-codes en audiofragmenten. Feature creep, maar dan bewust. Want als je deadline een feestje is en je code daarna mag weggooien, zeg je niet "dat doen we in v2". Je bouwt het gewoon.

Even voor de duidelijkheid: wat we voor onze opdrachtgevers bouwen is van een ander niveau. Unit tests, code reviews, maintainability, security audits. Dit was code met één doel: het moet werken op 19 december en daarna mag het weg. Geen edge cases, geen refactoring. Feature creep zonder consequenties.

Het werd een escape room

Ergens halverwege december kantelde het. We hadden teksten en een app, maar ons kantoor heeft ook fysieke ruimtes: een opbergkamer, een bar, een receptie. Wat als we die verwerkten in het spel?

Een opbergruimte werd een afgesloten hut van de kapitein. Om binnen te komen moesten spelers zes QR-codes vinden, verspreid door het kantoor. Elke code opende een vraag in de app. De antwoorden lagen verstopt in fysieke props: AI-gegenereerde geboorteaktes, oude zeekaarten, vergeelde krantenknipsels. Pas als de groep alle zes de vragen correct had beantwoord, konden we de deur openen.

In de Captain's Quarters lag de kapitein, vermoord. Zijn kamer was gevuld met aanwijzingen voor de volgende mysteries. Geheimen verborgen in foto's gaven een code die een audiofragment ontgrendelde: een door AI gegenereerde, vervormde noodoproep van de kustwacht. "Het schip... onderweg naar... Malta."

De kantoorverlichting begon mee te doen

Ons kantoor heeft DMX-gestuurde verlichting. Normaal voor sfeer, nu voor een puzzel. We schreven een Node.js controller die via polling de backend checkte en bij bepaalde gamestates signalen naar de lampen stuurde.

Voor de morse-puzzel moesten vier spelers, elk met een andere QR-code, die codes binnen vijf seconden scannen. Geen solo-oplossing mogelijk, je had elkaar nodig. Als vier unieke codes binnen 5 seconden binnenkwamen, triggerde de backend een event. De lampen begonnen te knipperen in morse: de code voor het fysieke dagboek van de kapitein.

19 december, de dag zelf

Om 14:30 meldde een deelnemer zich ziek. Uiteraard had ook hij geen bijrol, maar zijn teksten bevatten clues die andere spelers nodig hadden om de puzzel op te lossen.

Bij een gekocht spel was dit een probleem geweest. Maar onze teksten zaten in code. Een LLM herschreef snel zijn verhaallijn en om 15:02 stond de fix live.

De autocoureur lag nu "ziek in zijn hut met een infectie". Zijn clues werden herverdeeld naar Rick en Raymond. Het plot bleef sluitend. We pushen naar productie. Niemand van de dertig negenentwintig gasten heeft ooit gemerkt dat het script een half uur eerder anders was.

En om 16:21, 39 minuten voor de gasten arriveerden, keken Ewout en ik naar de app en dachten: waarom hebben we eigenlijk geen UI voor de notificatie-geschiedenis? Geen cruciale feature, maar we hadden nog tijd en een deployment pipeline die in minuten deployt. Dus we genereerden het op basis van een net aan voldoende AI implementation plan. Dertig minuten later stond het op ieders telefoon.

Ondertussen maakte het keukenteam van Voertaal Studio, in scheepsuniformen en compleet met Captain's Dinner-menu, de amuse-tafel klaar gedecoreerd met schelpen en een reddingsband.

Op groot scherm draaide een patrijspoort met zicht op zee en een zichtbare klok, zodat iedereen, inclusief de keuken, precies wist hoeveel tijd er nog was tot de volgende ronde. Opus had het draaiboek gemaakt in een volledig in thema vormgegeven PDF: een minuut-voor-minuut script voor spelleiding en keuken, zodat de gangen perfect met het spelverloop syncten.

Was het de moeite waard?

Een PWA met IoT-integratie, DMX-gestuurde verlichting en AI-gegenereerde audio, voor één etentje. Over-engineered? Absoluut.

Maar dit was een speeltuin. Vibe coding, zou je het kunnen noemen: code die op één datum moet werken en daarna mag worden vergeten. Geen klant die vraagt waarom het zo lang duurt. Geen scope die moet worden verdedigd. Geen technical debt, want er is geen later.

We konden experimenteren op een manier die bij een klantopdracht niet kan. Elke bottleneck die we normaal zouden hebben, "we hebben een copywriter nodig", "we moeten wachten op design", viel weg.

De code is inmiddels vergeten. De avond niet. Hoe we dit volgend jaar gaan overtreffen? Geen idee.