
B2B SaaS-platform
Context
Een B2B SaaS-platform, from scratch ontwikkeld voor de automobielsector:
- 🖥️ Een gespecialiseerde CMS waarmee klantorganisaties (dealers, resellers, leasemaatschappijen) voertuigen en transacties kunnen aanmaken, beheren en publiceren.
- 🤝 Een CRM om hun bedrijfsactiviteiten te beheren.
Voertuigen zijn polymorfe businessobjecten, die end-to-end worden gebruikt binnen een ecosysteem van onderling verbonden applicaties, waarbij elke applicatie ze weergeeft en verwerkt binnen zijn eigen context: backofficebeheer, dynamisch gegenereerde publieke website, interne ERP, klantportaal, enz.
Ik heb 3 jaar aan al deze applicaties gewerkt, waaronder meerdere maanden als enige frontend developer na de lancering van het project.
Polymorfe modellering
De kern van het project was gebaseerd op een gediscrimineerd en genest datamodel. Elke resource die via de CMS wordt aangemaakt is geen generiek object, maar een getypeerd object waarvan de structuur afhangt van de discriminator.

Een vereenvoudigde weergave van het model:
- Een voertuig (auto · motor · vrachtwagen · enz.) deelt een gemeenschappelijke basis, met type-specifieke kenmerken.
- Een voertuig heeft commerciële voorwaarden (verkoop · leasing · verhuur), die eveneens polymorf zijn.

Dit model leidt tot een matrix van businesscases die expliciet end-to-end moeten worden geïmplementeerd (aanmaak-/updateformulieren, validatie, weergave in elke applicatie). Elke combinatie is een afzonderlijke case. Dit niveau van volledigheid maakt het mogelijk dat de UI elke nuance van het domein correct weerspiegelt.
Frontend-implementatie
Het vertalen van een gediscrimineerd model naar een UI is meer dan alleen if/else-logica.
De echte architecturale vraag was: waar moet de discriminerende logica geplaatst worden, en hoe kan die geïnkapseld worden zodat ze onderhoudbaar blijft naarmate het aantal businesscases groeit?
Isolatie van complexiteit & compositie
Het doel was om de discriminerende logica zo dicht mogelijk bij de plaats van gebruik te houden, om te vermijden dat complexiteit onnodig omhoog in de componentenboom wordt verspreid.

In sommige gevallen (zoals de detailpagina van een voertuig of de kenmerkensectie in het backofficeformulier) vond de discriminatie plaats op het niveau van de volledige pagina, waarbij werd bepaald welke view moest worden weergegeven afhankelijk van het type. Elke view combineerde vervolgens gedeelde en specifieke secties via compositie.
Strikte typesafety
Discriminated unions in TypeScript zorgden ervoor dat elke businesscase volledig werd afgehandeld. De compiler gaf een waarschuwing bij niet-gedekte combinaties.
Contextuele validatie
Validatieregels verschilden per type. Een leasingformulier valideert niet dezelfde velden als een verkoopformulier (en volgt mogelijk andere businessregels). Fouten werden per case afgehandeld.
Monorepo-structuur
Een gedeelde codebase (monorepo) garandeerde visuele en gedragsmatige consistentie tussen applicaties: UI-componenten, design system en tooling. Elke applicatie had zijn eigen data access layer (dedicated BFF), waarbij DTO-types automatisch werden gegenereerd uit Swagger-documentatie via de Orval-library. Dit elimineerde handmatige duplicatie en behield tegelijk een duidelijke scheiding van verantwoordelijkheden.
Methodologie & teamcultuur
Klein team (2 frontend developers, 2 backend developers). Systematische code reviews, agile rituelen (standups gericht op het oplossen van blokkades in plaats van rapportering, sprint planning, retrospectives), en regelmatige demo’s voor stakeholders.
Conclusie
3 jaar gewerkt aan een volwaardige SaaS-platform, ontwikkeld van nul tot versie 2.6. Dit project heeft mij geleerd om:
- 🧬 De consistentie van een complex model over meerdere applicaties te waarborgen
- 🤝 Te werken binnen een team met een sterke kwaliteitscultuur (reviews, ownership, demo’s)
- 🕵️ Architecturale beslissingen te anticiperen in plaats van er reactief op te reageren
- 🗄️ Inzicht te krijgen in backend-uitdagingen en datamodellering, wat vandaag mijn evolutie naar fullstack ondersteunt