Het bouwen van mijn code app liep anders dan voorspeld
- Thim Derks
- Jul 28
- 8 min read
Updated: Jul 28
Het WK zit erop.
Zoals altijd begonnen we met voorspellingen, favorieten en mensen die na twee groepswedstrijden precies konden uitleggen wie wereldkampioen zou worden. En zoals altijd liep het uiteindelijk toch anders dan bijna iedereen vooraf had verwacht. Er waren verrassingen, onverwachte uitslagen en landen die veel verder kwamen, of juist veel eerder naar huis gingen, dan in menig voetbalpoule was ingevuld.
Eigenlijk lijkt dat behoorlijk op mijn ervaring met code apps.
Ook daar begon ik enthousiast aan. Ik had een duidelijk plan, een uitgebreid Dataverse-datamodel en AI die mij zou helpen om het geheel snel te bouwen. Wat kon er misgaan?
De WK-poule-app kwam er uiteindelijk. Deelnemers konden wedstrijden voorspellen, groepen bekijken, punten verzamelen en het knock-outtoernooi volgen. Ook de integratie met Dataverse en de beheerapp stonden uiteindelijk op hun plek.
Maar de weg ernaartoe bevatte minstens zoveel onverwachte wendingen als het toernooi waarvoor ik hem bouwde.
Sommige onderdelen gingen veel sneller dan ik had verwacht. Andere bleken verrassend hardnekkig. En soms leek alles perfect te werken, totdat ik ontdekte dat AI de werkelijkheid iets creatiever had geïnterpreteerd dan de bedoeling was.
De demo die ik eerder op LinkedIn liet zien, was de nette versie van het verhaal.
Dit is de versie met modder aan de schoenen.
En eerlijk gezegd is dat verhaal een stuk interessanter dan alleen het eindresultaat.
Wat ik wilde bouwen
Het idee was overzichtelijk.
Deelnemers moesten hun voorspellingen voor het WK kunnen invullen. Per wedstrijddag of per fase van het toernooi. In de groepsfase moesten de wedstrijden per groep worden getoond. De knock-outfase moest eruitzien als een echt schema.
Verder wilde ik dat deelnemers niet alleen hun punten konden zien, maar ook waarom ze die punten hadden gekregen.
Aan de achterkant kwam een model-driven app voor het beheer van onder andere:
teams en groepen;
wedstrijden en uitslagen;
deelnemers;
scoremodellen;
voorspellingen;
scoredetails.
Dus niet alleen een aardige voorkant met wat voorbeelddata. Het moest echt werken met Dataverse als databron en met plug-ins en custom API’s voor de scoreberekening.

Les 1: de keuze voor je AI-assistent maakt echt verschil
Laat ik maar meteen eerlijk zijn: mijn eerste pogingen met Copilot waren verschrikkelijk.
Niet een beetje onhandig. Gewoon frustrerend slecht.
Voor een eenvoudig datamodel kom je er waarschijnlijk prima mee weg. Met Copilot kun je daar zeker mooie resultaten mee behalen. Maar mijn model was alleen iets minder standaard.
Ik had wedstrijden, teams, groepen, toernooifases, matchslots, deelnemers, voorspellingen en scoredetails.
De thuis- en uitploeg van een knock-outwedstrijd konden bovendien nog onbekend zijn en bijvoorbeeld verwijzen naar de winnaar van een eerdere wedstrijd.
Dat is dus iets anders dan een tabel met tickets en een statusveld.
Copilot leek regelmatig niet goed te begrijpen hoe de verschillende Dataverse-tabellen samenwerkten.
Hij schreef vrolijk verder, maar de wedstrijddata verscheen niet in de app.
Maar ook op het gebied van UI viel mij Copilot erg tegen.
Pas toen ik overstapte naar Codex in Visual Studio Code begon het tempo echt omhoog te gaan. Codex begreep het bestaande datamodel beter (maar zeker niet perfect), kon gerichter bestanden aanpassen en was veel bruikbaarder bij het itereren op de UI.
De keuze van het gereedschap maakt echt verschil.
Les 2: De Dataverse-laag
Je begint zo’n traject toch met de hoop dat AI vooral de saaie stukken uit handen neemt.
Dus je denkt: laat AI de Dataverse-laag maar opzetten. Dan kan ik me bezighouden met de interessante delen.
In de praktijk bleek dat lastiger dan verwacht.
Eerder schreef ik al dat mijn oplossing een complexer datamodel had dan de ‘ticketapps’ die je in veel demo’s ziet. Het gevolg was dat verschillende integraties met Dataverse niet werkten of niet het gewenste resultaat gaven. Ook Codex kwam hier niet helemaal uit. En nee, dit was niet simpelweg een kwestie van: ‘Je hebt onvoldoende context gegeven.’
Zelf kende ik het datamodel door en door. Vanaf het moment dat ik de gegenereerde oplossing handmatig ging aanpassen, onderdelen aanvulde en bruikbare stukken overnam, begon het project te vliegen.
De repositories waren verantwoordelijk voor de ruwe Dataverse-toegang. De services boden concrete acties aan, zoals ‘haal wedstrijden voor deze datum op’ of ‘sla deze voorspelling op’.
De UI kreeg alleen nog eenvoudige modellen waar hij direct mee kon werken.
De Dataverse-laag hoeft namelijk niet creatief te zijn. Die moet gewoon kloppen.
Belangrijker nog: ik wist weer precies waar de data vandaan kwam en hoe die werd verwerkt.
Les 3: Codex was soms iets te creatief
Codex werkte een stuk beter, maar ook daar moest ik goed blijven opletten. Hij probeerde in ieder geval de requirement ten koste van alles te realiseren.
De opdracht was bijvoorbeeld om gegevens uit Dataverse te halen. Voor een gedeelte van de benodigde data werkte dit keer op keer niet. En toen opeens, poef... het werkte! Eindelijk, dacht ik. Dit had veel te veel tijd gekost, maar het werkte.
Wat bleek? Toen ik de code ging reviewen zag ik dat hij een deel van het spelschema van het WK op internet had opgezocht en die vervolgens zelf als fallback in de app had verwerkt.
Het ophalen van de stamdata werkte nog steeds niet, maar de app leek wel te werken.
Dat is misschien nog wel gevaarlijker dan een duidelijke foutmelding.
Een foutmelding is tenminste eerlijk. Hardcoded data kan precies genoeg werken om je te laten denken dat de integratie klaar is. Het scherm toont teams. De wedstrijden staan netjes onder elkaar. Het knock-outschema ziet er goed uit.
Mooi.
Totdat je de stamdata aanpast, een ander toernooi wilt gebruiken of de app in een nieuwe omgeving installeert. Dan blijkt dat een deel van de oplossing niet uit Dataverse kwam, maar ergens verstopt zat in een TypeScript-bestand.
Dat is het digitale equivalent van iemand die zegt dat de IKEA-kast af is, maar ondertussen drie schroeven heeft vervangen door ducttape.
Grondig reviewen is bij AI-gegenereerde code dus geen luxe. Het is onderdeel van het ontwikkelproces.

Les 4: ‘het werkt’ betekent soms vooral ‘ik heb geen foutmelding meer’
AI kan iets met indrukwekkende overtuiging presenteren als opgelost.
‘De Dataverse-koppeling werkt nu.’
Nee.
‘De wedstrijden worden correct geladen.’
Ook nee.
‘De voorspelling wordt zonder duplicaten opgeslagen.’
Nog steeds niet.
Ik moest daarbij regelmatig aan mijn kinderen denken. Die kunnen soms met volledige overtuiging uitleggen dat iets echt waar is, terwijl je met één blik ziet dat het onmogelijk klopt.
En juist dat maakt AI soms verraderlijk. Het antwoord klinkt netjes, de uitleg is logisch opgebouwd en de gewijzigde code compileert misschien zelfs. Maar compileren is niet hetzelfde als werken.
Een succesvolle build bewijst niet dat de juiste gegevens worden geladen. En een groene TypeScript-check bewijst al helemaal niet dat een gebruiker zijn voorspelling daadwerkelijk kan opslaan.
Wat juist wel goed ging
Nu klinkt het misschien alsof ik alleen maar met lichte tegenzin terugkijk op code apps.
Dat is niet zo.
Toen de basis eenmaal goed stond, ging het juist hard.
Vooral aan de UI-kant kon ik snel grote stappen zetten. Een desktop-first ontwerp, wedstrijdkaarten, groepen naast elkaar, vlaggen, score-invoer, de knock-outweergave en een duidelijke uitleg van toegekende punten.
Dat soort werk ging voor mij veel sneller met AI dan wanneer ik alles handmatig had moeten maken.
‘Maak deze kaarten compacter.’
‘Gebruik op brede schermen drie kolommen.’
‘Laat de vlaggen prominenter terugkomen.’
‘Zorg dat het knock-outschema op mobiel horizontaal kan scrollen.’
Daar is zo’n assistent sterk in. Zeker als de componenten al duidelijke invoer krijgen en niet zelf Dataverse hoeven te begrijpen.
En juist omdat ik geen standaard interne app bouwde, merkte ik snel waar iets goed voelde en waar niet.
Een simpele administratie-app vergeeft best veel. Een WK-poule minder.
Als het invoeren van twee scores irritant voelt, merkt iedereen dat meteen. Als groepen onlogisch worden weergegeven, raakt de gebruiker de weg kwijt. Als punten niet uitlegbaar zijn, vertrouwt niemand de ranglijst.
Dan bouw je niet alleen iets dat technisch functioneert. Dan moet het ook prettig werken.
Dat vond ik uiteindelijk het leukste deel van het project.

Zijn canvas apps nu dood?
Kort maar krachtig: nee.
Canvas apps zijn naar mijn mening zeker niet dood. Zelf erger ik mij aan dat soort ragebait. Het is altijd makkelijk scoren door te zeggen dat iets dood is. Vaak ligt dit een stuk genuanceerder.
Ik ga niet ontkennen dat code apps veel potentie hebben. Voor grotere enterprise-apps zie ik persoonlijk een groeiende rol voor code apps.
Je hebt meer controle over de UI, kunt een duidelijke componentstructuur opzetten en werkt met een ontwikkelervaring die beter aansluit bij reguliere softwareontwikkeling.
Maar dat betekent niet dat iedere canvas app nu zo snel mogelijk herschreven moet worden.
Voor kleine, taakgerichte apps zijn canvas apps nog steeds prima. Soms zelfs gewoon de betere keuze.
Een medewerker moet drie velden invullen, een foto maken en op verzenden drukken? Daar hoef je niet per se een compleet React-project voor op te tuigen.
Niet iedere gereedschapskist hoeft een lasapparaat te bevatten omdat je een schroef wilt vastdraaien.
Voor grotere apps zie ik meer potentie in code apps. Voor kleinere en duidelijke taken blijft een canvas app wat mij betreft gewoon een logisch onderdeel van het platform.
Maar wat kost het beheer straks?
Daar zit voor mij nog wel een belangrijke maar.
We leven nu in een periode waarin AI relatief goedkoop en makkelijk beschikbaar aanvoelt. Veel mensen hebben een abonnement en coding agents kunnen in korte tijd behoorlijk wat code produceren.
AI die nu binnen een abonnement goedkoop aanvoelt, hoeft niet voor altijd op dezelfde manier geprijsd te blijven. Naast vaste abonnementen zien we steeds meer verbruiksmodellen met tokens, credits en gebruikslimieten.
Daarom zou ik niet alleen kijken naar hoe snel je vandaag een code app kunt bouwen.
Ik zou ook vragen:
Wie kan hem over twee jaar nog beheren?
Als je een verzameling code apps bouwt, maar niemand in de organisatie begrijpt de code zonder continu een AI-assistent nodig te hebben, dan creëer je een nieuwe afhankelijkheid.
Misschien werkt dat prima. Maar het moet wel een bewuste keuze zijn.
Als niemand de code kan lezen, testen of beoordelen zonder AI, blijf dan voorlopig lekker bij een canvas app.
Dat is misschien minder spannend, maar beheerbaarheid is belangrijker dan een mooie eerste demo.
Een extra LEGO-blokje in de doos
Zo kijk ik uiteindelijk ook naar de plaats van code apps binnen het Power Platform.
Ze vervangen niet automatisch alles wat ervoor bestond.
Power Automate heeft ook nog steeds een rol naast Azure Logic Apps. Er zit overlap in, maar dat betekent niet dat één van beide daardoor nutteloos is geworden.
Het zijn verschillende LEGO-blokjes in dezelfde Microsoft-doos.
Code apps zijn daar nu een nieuw blokje bij.
Een interessant blokje. Een blokje waarmee je dingen kunt bouwen die eerder lastiger waren binnen Power Apps.
Maar nog steeds gewoon één onderdeel van een grotere doos.
De vraag is dus niet welk blokje het nieuwste is.
De vraag is welk blokje past bij wat je probeert te bouwen.
Dat een app sneller gebouwd kan worden, betekent niet dat die app ook binnen het bestaande landschap gebouwd móét worden.
Mijn eerlijke conclusie
Code apps zijn interessant, maar zeker geen kwestie van ‘next, next, finish en binnen een paar uur klaar’.
Voor simpele scenario’s geloof ik best dat je snel iets bruikbaars kunt neerzetten.
Voor complexere datamodellen, relationele data, echte integraties en een UI die ook nog goed moet voelen, blijft het gewoon serieus ontwikkelwerk.
AI helpt daarbij enorm, maar je moet kritisch blijven op wat het maakt, welke aannames het doet en waar de gebruikte data daadwerkelijk vandaan komt.
Voor mij was de grootste winst uiteindelijk niet dat AI alles bouwde.
De grootste winst was dat ik beter ben gaan zien waar AI echt versnelt en waar ik beter zelf het stuur kan vasthouden.
Want uiteindelijk blijft AI gewoon gereedschap.
Goed gereedschap kan je sneller laten werken. Het kan taken makkelijker maken en soms resultaten leveren waar je zelf veel langer over zou doen.
Maar je moet er geen dingen mee bouwen die je zonder AI totaal niet begrijpt.
Of je moet je in ieder geval heel bewust zijn van het risico.
AI mag versnellen. AI mag helpen. En AI mag best een flink deel van het werk doen.
Maar als niemand meer begrijpt wat er gebouwd is, heb je geen slim ontwikkelproces.
Dan heb je vooral een afhankelijkheid met een mooie demo.

Comments