Eén pagina goed bouwen, dertig klantsites eruit
Een sitebouwer voor bureaus waarin het compositiesysteem de beweging bewaart en de inhoud vrij laat.

- Product
- Route
- Onderwerp
- Platform
- Jaar
Een bureau maakt niet één website maar dertig, en bij elke daarvan wordt dezelfde afweging opnieuw gemaakt: waar begint de tekst, hoe komt dat beeld binnen, waar valt de naad tussen twee secties. Magicpage draait dat om. De blokken zeggen alleen wat ze zijn, het systeem beslist wat er gebeurt, en de choreografie die je één keer goed hebt gezet begint bij de volgende klant weer van voren af aan.
- TypeScript
- React 19
- Next 15
- GSAP
- CSS Cascade Layers
- Cloudflare Pages
- pnpm-workspace
In het kort
- 317
- 58
- 110
- 14
- 440
Wat er lag
Een bureau maakt niet één website maar dertig, en bij elke daarvan wordt dezelfde afweging opnieuw gemaakt: waar begint de tekst, hoe komt dat beeld binnen, waar valt de naad. Bestaande bouwers geven je een template, en zodra je ervan afwijkt valt het uit elkaar. De opgave: de choreografie één keer vastleggen en de inhoud vrij laten. Eén pagina goed bouwen, en de volgende klant daarvandaan beginnen.
Drie details die het verschil maken



Hoe het is gemaakt
Het probleem was niet “een site maken”
Een bureau maakt er dertig, en bij elke daarvan wordt dezelfde afweging opnieuw gemaakt: waar begint de tekst, hoe komt dat beeld binnen, waar valt de naad tussen twee secties. Dat is het dure deel, en het is bij elke klant grotendeels hetzelfde.
Bestaande bouwers lossen daarom het verkeerde probleem op. Ze geven je een template, een afgewerkt ontwerp waar je content in giet, en zodra je ervan afwijkt valt het uit elkaar. Wat je wilt is het omgekeerde: de choreografie vastleggen en de inhoud vrij laten.
Magicpage is daarom gebouwd rond een compositiesysteem, en pas daarna rond pagina's. Je maakt één keer een pagina zoals je hem wilt hebben, legt hem vast, en begint de volgende klant daarvandaan: andere blokken, ander merk, andere tekst, dezelfde beweging.
Blokken blijven dom
Elk blok zegt alleen wat het is, of hoe het zich verhoudt tot zijn buurman. Het systeem beslist wat er gebeurt. Een blok noemt zijn kop een kop en de overgang naar het volgende blok een band; welke beweging daarbij hoort en hoe die band eruitziet staat ergens anders. Dat klinkt als een detail en het is de hele architectuur.
Daarom kan één regel in een bewegingsset alle honderdtien blokken veranderen, en hoeft een nieuw blok niets van beweging te weten. Bij elk nieuw idee is dat de toets, en hij heeft in drie maanden meer beslissingen genomen dan welk overleg dan ook.
Eronder ligt een cascade van vijftien CSS-lagen in één declaratie, en die volgorde is geen smaak: hoofdstukken komen ná de doorlopende beweging omdat hoofdstukruimte marge is die bovenop alle voorgaande afstanden komt, en de viewport-laag komt daar weer achter zodat een schermregel altijd het laatste woord heeft. Elke positie in die rij is één keer beargumenteerd en staat in de code uitgeschreven.
Kan het blok het benoemen zonder het uit te voeren?
De lus die het product ís
Alles hierboven bestaat voor één werkgang. Bouw één maximale pagina (dertien blokken, vijf hoofdstukken, gemeten overgangen) en leg hem vast als sjabloon. Niet een gekocht ontwerp maar jouw concept: alle pagina's met hun choreografie, plus merk en art directie. Dat is het dure werk en je doet het één keer.
De volgende klant begint daarvandaan. Je wisselt de blokken, en de naden, hoofdstukken en scènes blijven staan. Je herbrieft de inhoud: wat het bedrijf doet, voor wie, wat het onderscheidt. En dan gaat er één beeld-sweep over de hele site.
Dat werkt in concepten, de tabs bovenin de werkbank: varianten van dezelfde site die je naast elkaar aan een klant laat zien. Elk concept heeft zijn eigen pagina's op één oneindig canvas, dus je bladert niet door schermen maar zoomt uit.
Die laatste stap is het principe in het klein. Een blok vertelt al alles wat een beeldbriefing nodig heeft: dat dit slot een beeld wil, wat voor beeld (het pad ernaartoe zegt dat een avatar een portret is), welke verhouding, wat het onderwerp is (de kop van het blok) en welke art directie eroverheen ligt. Je hoeft het alleen op te rapen. Dus geen promptveld erbij, maar: het systeem stelt de briefing op en jij corrigeert hem.
Toen deden we de telling die de aanpak bevestigde. Tweeëntwintig beeldslots zitten in blokken die zichzelf als beeldblok aankondigen, en honderdvier daarbuiten: avatars in testimonials, teamrasters, blogcovers. Alleen op die aankondiging afgaan had vijf zesde van de beelden overgeslagen.

Veertien poorten tegen stille fouten
Elke poort in dit project is ontstaan uit één concrete fout die stil was. Geen foutmelding, geen rode build, alleen een pagina die er “gewoon anders” uitzag. Dat is de duurste soort, want je vindt hem pas als een klant kijkt.
Er staan er nu veertien: een poort die controleert dat het paneel alleen scènes aanbiedt die een blok kán dragen, een die kijkt of elk gevonden beeldpad ook wordt teruggeschreven, een die merkkleuren betrapt die bij het publiceren stil wegvielen, een die nakijkt of elk formulier post naar iets dat bestaat.
De jongste is meteen de mooiste. De keuzeruimte is elf thema's maal acht interfacesets maal vijf bewegingssets: vierhonderdveertig combinaties, waarvan er ooit vijf met het oog bekeken waren. Die poort rendert ze nu alle vierhonderdveertig en controleert dat de CSS die ze gebruiken ook meekomt, en dat het onder de negenhonderd kilobyte blijft. Vier seconden voor de hele set, want React is na de eerste render warm.
Wat we eruit hebben geleerd
- 01
Het meest voorkomende defect in dit project was een afwezigheid: acht keer was er iets gebouwd, getest, en werd het door niets aangeroepen. Compositielagen die nergens werden gezet. Scènes die het paneel niet aanbood. Een veld met veertien lezers en geen enkele schrijver. Het patroon is verraderlijk omdat alles groen is: de code compileert, de test slaagt, het ding bestaat, en alleen doet het niets. “Wie roept dit aan?” is de goedkoopste vraag die er is en we stelden hem het minst.
- 02
Drie keer stelden we voor iets te schrappen omdat het zeldzaam was, en drie keer klopte dat niet. Formulieren kwamen in geen enkel sjabloon voor, maar een site zonder werkend contactformulier is geen site. Frequentie meet blootstelling in de data die je toevallig hebt; het meet niet wat het ding doet. De vraag is niet hoe vaak iets voorkomt maar wat je verliest als het weg is.
- 03
Drie knoppen logen. Een knop die na twee seconden “geverifieerd” zei, ongeacht wat er in de DNS stond. Een contactformulier dat op drie verschillende manieren “Verzonden!” teruggaf terwijl er niets verzonden werd. De venijnigste had een keurige try/catch. Alleen gooit die bibliotheek niet bij een fout van de dienst, hij geeft het resultaat mét een foutveld terug. De catch ving dus alleen netwerkfouten, en een geweigerde sleutel gleed er zo langs. Een knop die liegt kost je pas iets op het moment dat je erop vertrouwt, en bij een contactformulier is dat een gemiste klant.
- 04
En meet eerst je meetopstelling. Een halve dag ging op aan “deze functie werkt niet”, terwijl we aan het meten waren in een verborgen browserpaneel: daar is de pagina officieel onzichtbaar en tikt de tekenlus niet, dus alles wat op beweging wacht staat stil. Het pijnlijke was dat dit al opgeschreven stond van een eerdere sprint, waar screenshots zwart bleven om dezelfde reden. Een meting die je niet begrijpt is eerst verdacht op zichzelf, en pas daarna op het ding dat je meet.
Letters en kleuren
- Koppen en tekst
- Inter Variable
- Code en velden
- JetBrains Mono
- #f1f0eede achtergrond van de werkbank
- #ffffffpanelen en kaarten
- #e4e2dfeen spoor waar een control in ligt
- #0a0a0btekst
- #6544fchet ene accent: de knop en de actieve tab
- De werkbank is grijs en het accent violet, zodat de site van de klant in het canvas de enige kleur is die telt.
- Kleur in een gebouwde site wordt niet per thema uitgeschreven maar afgeleid: één basisvlak en één basisletter voeden vier sporten van een ladder.
- De waarden komen uit de tokens in de code, 7 september 2026.
Waar het van gemaakt is
- Bouw
- TypeScript
- React 19
- Next 15
- GSAP
- pnpm-workspace
- Compositie
- 15 CSS-cascadelagen
- 110 blokken
- 128 CSS-delen
- Poorten
- 14 poorten
- 440 combinaties
- Vier seconden
- Uitvoer
- Statische HTML
- CSS ingesloten
- Eén gedeeld motion-bestand
- Cloudflare Pages
Voor wie verder wil lezen
Onder de motorkap
TypeScript, React 19, Next 15 en GSAP, zes packages in één pnpm-workspace, uitgerold op Cloudflare Pages.
TypeScript, React 19, Next 15 en GSAP, zes packages in één pnpm-workspace, uitgerold op Cloudflare Pages. 112.500 regels TypeScript en 18.500 regels CSS, in drie maanden en achtenvijftig sprints, door één ontwikkelaar. Honderdtien blokken, honderdachtentwintig CSS-delen.
Twee technieken zijn het waard om mee te nemen. Kleur wordt niet per thema uitgeschreven maar afgeleid: één basisvlak en één basisletter voeden vier sporten van een ladder, en elk kleurschema leidt daar zijn gronden uit af. Dat werkt vanzelf de goede kant op, licht of donker. En de overgang van een portfoliokaart naar de case-pagina die hij opent gebeurt zonder één regel JavaScript: de browser doet dat zelf, mits de naam die de twee aan elkaar knoopt uniek is binnen één document. Een case-pagina die zichzelf toonde in haar eigen “meer werk”-raster had hem twee keer, en sloopte de hele overgang.
De motion-runtime stond eerst inline in élke pagina: 159 kilobyte, zes keer hetzelfde. Nu is het één gedeeld bestand. De CSS blijft wél inline, en dat verschil is de hele afweging: CSS blokkeert het tekenen, beweging niet.
Wat er open staat
Een eerlijke case noemt ook wat er niet af is.
Een eerlijke case noemt ook wat er niet af is. Er is nog nooit uitgerold. Het hele pad tot en met de bestandenset is gemeten, het uploaden zelf niet. Eén echte uitrol toetst in één keer drie dingen die nooit gedraaid hebben.
Hoe die vierhonderdveertig combinaties eruitzien weten we ook niet. De poort controleert dat de CSS meekomt, niet dat de combinatie mooi is. Dat vraagt ogen, geen script.
En video. Dezelfde beeldbriefing, andere modaliteit, maar met wachttijden in minuten in plaats van seconden. Dat vraagt een taak met een wachtrij, en dát is de kostenpost, niet de aanroep zelf.
Voor wie is dit?
Voor een bureau dat niet één website maakt maar dertig, en bij elke daarvan dezelfde afweging opnieuw maakt.
Wat is een sjabloon hier?
Jouw eigen concept: alle pagina's met hun choreografie, plus merk en art directie. Niet een gekocht ontwerp waar je content in giet.
Hoe komt het beeld erin?
Een blok vertelt al alles wat een beeldbriefing nodig heeft; het systeem stelt de briefing op en jij corrigeert hem. Eén sweep over de hele site.
Is het al uitgerold?
Nee. Het hele pad tot en met de bestandenset is gemeten, het uploaden zelf niet. Eén echte uitrol toetst drie dingen die nooit gedraaid hebben.
Wat weten jullie nog niet?
Hoe de vierhonderdveertig combinaties eruitzien. De poort controleert dat de CSS meekomt, niet dat de combinatie mooi is. Dat vraagt ogen, geen script.


