Productcatalogus met varianten en bundels: schema en UI-patronen
Ontwerp een productcatalogus met varianten en bundels met duidelijke SKU-regels, voorraadlogica en UI-patronen die onmogelijke combinaties en overselling voorkomen.

Waarom varianten en bundels snel rommelig worden
Een catalogus lijkt simpel wanneer elk product één artikel is met één prijs en één voorraadnummer. Voeg kleur, maat, abonnementsduur of regiogebonden verpakking toe en die eenvoud valt uiteen. Een enkele "Products"-tabel kan basisvragen niet meer beantwoorden: welk precies artikel verkopen we, en hoe houden we het bij?
Kopers verwachten ook dat de details kloppen. Ze willen opties kiezen, direct de juiste prijs zien en weten of hun exacte keuze vandaag kan worden verzonden. Als de pagina "Op voorraad" zegt maar de geselecteerde maat is weg, daalt het vertrouwen snel. Als de prijs pas bij de checkout verandert, ontstaan supporttickets en retouren.
Bundles voegen een tweede laag complexiteit toe omdat ze eruitzien als producten maar zich gedragen als regels. Een "Starter Kit" kan één fles, één pomp en een set filters bevatten. De beschikbaarheid hangt af van de onderdelen, en je kosten en rapportage moeten nog steeds kloppen.
Signalen dat je catalogus begint te scheuren:
- Je maakt dubbele SKU's alleen om een optie te representeren.
- Voorraadniveaus voelen onjuist, vooral na bundelverkopen.
- Adminschermen worden lange lijsten bijna-identieke items.
- Kortingen en belastingen werken voor losse items maar breken voor kits.
- Rapportage kan niet beantwoorden "wat is er daadwerkelijk verkocht?"
De oplossing is vooral discipline: een datamodel dat consistent blijft, en UI-patronen die optie-selectie en beschikbaarheid duidelijk maken voor klanten en je team.
Begrippen in gewone taal: opties, varianten, SKU's, bundels
Als mensen "varianten" zeggen, vermengen ze vaak een paar verschillende ideeën. De woorden vroeg duidelijk krijgen maakt latere beslissingen (schema, UI, voorraad) veel makkelijker.
De meeste teams gebruiken deze definities:
- Optie: een keuze die een shopper kan maken, zoals Maat of Kleur.
- Optiewaarde: één waarde binnen een optie, zoals Maat = M of Kleur = Zwart.
- Variant: één exacte combinatie van optiewaarden, zoals Maat M + Kleur Zwart.
- SKU: een verkoopbaar object dat je in operatie en voorraad volgt. Een variant mapt vaak naar één SKU, maar niet altijd.
- Bundel / kit / multipack: een product gemaakt uit andere producten. Een bundel is een marketinggroepering (de onderdelen kun je apart verkopen). Een kit moet altijd samen verzonden worden. Een multipack is hetzelfde item herhaald (3-pack sokken).
IDs raken in de praktijk ook in de war. Een interne ID is wat je database gebruikt. Een SKU is je operationele code (gebruikt bij picken, aanvullen en rapporten). Een streepjescode (UPC/EAN) is wat scanners lezen. Eén SKU kan meerdere streepjescodes hebben (verschillende regio's), en sommige items hebben helemaal geen barcode.
Een goede regel om te beslissen of iets een verkoopbare variant moet zijn: als het een andere prijs, voorraad, gewicht of verzendregels kan hebben, behandel het als verkoopbaar. Dezelfde T‑shirt in maat M en maat XL heeft meestal aparte voorraadtelling, dus dat moeten aparte SKU's zijn.
Bepaal wat je catalogus moet ondersteunen
Voordat je een schema kiest, begin met de vragen die het bedrijf elke dag moet beantwoorden. Als iemand naar een item kijkt, kun je dan met zekerheid zeggen: is het nu beschikbaar, wat kost het, hoe wordt het verzonden en welke belastingregels gelden?
Een handige manier om hierover na te denken is beslissen waar elk "feit" woont. Zet gedeelde feiten op het product en veranderlijke feiten op de variant (SKU). Als je ze mixt, eindig je met het oplossen van dezelfde bug op twee plekken.
Vragen die meestal bepalen of iets product- of variant-niveau is:
- Als het verandert per maat/kleur/materiaal, hoort het bij de variant.
- Als het voor elke optiecombinatie waar is, hoort het bij het product.
- Als je er per SKU over rapporteert (verkopen, marge, retouren), sla het per variant op.
- Als de operatie het gebruikt om te picken/pakken/verzenden, sla het op waar het magazijn mee werkt: op de SKU.
- Als het veilig af te leiden is (zoals weergavenaam uit optiewaarden), leid het af en sla alleen de bron op.
Houd één bron van waarheid. Sla bijvoorbeeld de "prijs" niet zowel op product- als variantniveau op tenzij de rollen duidelijk zijn (bijv. product heeft MSRP, variant heeft daadwerkelijke verkoopprijs).
Plan voor verandering. Je voegt misschien later een nieuwe optie toe (zoals "Lengte"), retireert een variant of voegt SKU's samen na leverancierswijzigingen. Dit gaat soepeler wanneer varianten eersteklas records zijn, niet alleen labels.
Als je in AppMaster bouwt, maakt duidelijke entiteitsnaamgeving in de Data Designer dit makkelijker te onderhouden als eisen verschuiven.
Een praktisch schema voor producten en varianten
Een schoon schema houdt de catalogus begrijpelijk wanneer een simpel product verandert in tientallen verkoopbare combinaties. Het doel is keuzes (wat shoppers kiezen) apart te modelleren van verkoopbare items (wat je werkelijk op voorraad hebt en verzendt).
Een betrouwbaar setje entiteiten:
- Product: het "ouder"-item (naam, beschrijving, merk, categorie, standaardafbeeldingen)
- Option: een type keuze (Maat, Kleur)
- OptionValue: de toegestane waarden (Small, Medium, Red, Blue)
- Variant: het verkoopbare item (één combinatie van waarden)
- VariantOptionValue: een join-tabel die een Variant verbindt met zijn gekozen OptionValues
Variant-uniciteit is waar veel catalogi fout gaan. De veiligste aanpak is genormaliseerd: handhaaf één OptionValue per Option voor elke Variant en voorkom dubbele combinaties. Als je ook snelheid wilt, sla een berekende "variant key" op zoals color=red|size=m (of een hash ervan) op Variant en handhaaf die als uniek per Product.
Houd velden die per combinatie veranderen op Variant, niet op Product: SKU, streepjescode, prijs, vergelijk-prijs, kostprijs, gewicht, afmetingen, status (actief/uitgefaseerd) en afbeeldingen (of één hoofdafbeelding of een kleine set).
Voor custom attributen (zoals "materiaal" of "wasinstructies") kun je vermijden om steeds nieuwe kolommen toe te voegen. Een JSONB-veld op Product of Variant werkt goed in PostgreSQL, gecombineerd met een kleine validatielaag in je app.
SKU-regels die consistent blijven
Een SKU is een identificator voor een verkoopbaar object waarvan je belooft dat het stabiel blijft. Het moet één vraag beantwoorden: "Welk exact item hebben we verkocht?" Het moet niet proberen je marketingnaam, volledige optie-tekst, seizoen of heel verhaal te dragen. Als je het overladen maakt, wordt het moeilijk om later iets te veranderen zonder rapporten te breken.
Beslis vroeg of SKU's handmatig of gegenereerd zijn. Handmatige SKU's zijn veiliger als je al een ERP, barcodes of leveranciers-SKU's hebt die moeten overeenkomen. Gegeneerde SKU's zijn beter als je veel varianten hebt en consistentie nodig hebt, maar alleen als de regels niet halverwege het jaar veranderen. Een veelgebruikte middenweg is een vaste basis-SKU die je beheert, plus een korte gegenereerde suffix voor variantattributen.
Regels die leesbaar blijven en groei overleven:
- Houd SKU's stabiel zodra een bestelling is geplaatst. "Fix" oude SKU's nooit door ze te hernoemen.
- Scheid de interne ID van de SKU. Gebruik de SKU voor mensen, de ID voor databases.
- Gebruik korte prefixen voor productfamilies (bijv. TSH, MUG), geen volle woorden.
- Vermijd betekenissen die kunnen veranderen (zoals "2026" of "SUMMER") tenzij je business daar echt op draait.
Gearchiveerde/discontinue SKU's moeten niet worden verwijderd. Markeer ze inactief, bewaar hun prijs- en verkoopgeschiedenis, en maak ze selecteerbaar in oude orders, refunds en rapporten. Als je een SKU vervangt, sla een "vervangen door" referentie op zodat support kan traceren wat er gebeurde.
Validatieregels voorkomen trage schade over tijd: handhaaf SKU-uniciteit over alle verkoopbare items, sta alleen letters, cijfers en koppeltekens toe, zet een duidelijke maxlengte (vaak 20–32 tekens) en reserveer prefixen voor speciale gevallen (zoals "BND-" voor bundels). In AppMaster passen deze checks goed als data-constraints plus een Business Process die opslaan blokkeert wanneer een regel wordt overtreden.
Voorraadlogica voorbij simpel op voorraad / uitverkocht
Voorraad wordt verwarrend wanneer hetzelfde "product" veel verschillende verkoopbare eenheden kan betekenen. Voordat je regels schrijft, kies je je voorraad-eenheid: houd je voorraad bij op productniveau, variantniveau of beide?
Als klanten maat of kleur kiezen, is variantniveau meestal het veiligst. Een shirt kan "op voorraad" zijn in het algemeen, maar de Small-Blue variant kan uitverkocht zijn. Productniveau werkt voor items waarbij varianten niet veranderen wat je fysiek opslaat (bijv. een digitale licentie met verschillende betaalplannen). Sommige teams houden beide aan: productniveau voor rapportage, variantniveau voor verkoop.
Voorkomen van overselling draait minder om één magische vlag en meer om duidelijke staten. De meeste catalogi hebben reserveringen nodig (houd units kort vast voor carts of onbetaalde orders), backorders (verkoop toestaan met duidelijke verzenddata), voorraadbuffers (een verborgen hoeveelheid om syncvertragingen op te vangen) en atomische updates (verminder voorraad in dezelfde operatie die de bestelling bevestigt).
Randgevallen zijn waar "mysterievoorraad" vandaan komt. Retouren zouden pas voorraad moeten toevoegen na inspectie, niet wanneer een retourlabel is gemaakt. Beschadigde items moeten naar een aparte status of locatie verplaatst worden zodat ze niet als verkoopbaar verschijnen. Voorraadaanpassingen hebben een audittrail nodig (wie wat en waarom heeft aangepast), vooral als meerdere kanalen voorraad bijwerken.
Bundels en kits voegen één sleutelregel toe: verminder geen "bundel" record als de bundel alleen een groepering is. Verminder de componentitems in plaats daarvan. Een 3-pack moet drie eenheden van dezelfde SKU verminderen; een kit moet één van elk component verminderen.
Voorbeeld: een "Starter Kit" bevat 1 fles en 2 filters. Als je 10 flessen en 15 filters hebt, is de kit-beschikbaarheid 7 omdat filters limiteren. Component-gebaseerde berekening houdt rapportage, refunds en restocking consistent.
In AppMaster map je dit netjes naar varianttabellen in de Data Designer en reserverings-/verminderlogica in de Business Process Editor, zodat elke checkout dezelfde regels volgt.
Bundels en kits modelleren zonder rapportage kapot te maken
Bundels zijn waar catalogi vaak in speciale gevallen vervallen. De eenvoudigste aanpak is bundels te modelleren als normale verkoopbare items en er dan een duidelijke lijst componenten aan te hangen.
Een schone structuur is: Product (verkoopbaar item) plus BundleLines. Elke BundleLine verwijst naar een component-SKU (of een componentproduct plus een vereiste variant) en slaat een hoeveelheid op. Orders tonen nog steeds "één item", maar je kunt het uitbreiden naar onderdelen wanneer je kostprijs, voorraad en fulfillmentdetail nodig hebt.
De meeste bundelopstellingen passen in één van deze:
- Vaste bundel (kit): altijd dezelfde componenten en hoeveelheden.
- Configureerbare bundel: de klant kiest uit toegestane componenten (blijft als lijnen op de order bewaard).
- Virtuele bundel: een marketinggroepering (vaak zonder voorraadimpact), handig voor merchandising zonder fulfilmentlogica te forceren.
Prijzen zijn waar teams per ongeluk rapportage breken. Beslis van tevoren wat op de orderregel verschijnt en wat marge- en voorraadrapporten voedt. Veelvoorkomende benaderingen zijn een vaste bundelprijs, som van onderdelen, of een betaalde som met kortingen per component (bijv. "kies 3 items, de goedkoopste is 50% korting").
Voorraad moet even strikt zijn: een kit is beschikbaar alleen als elk vereist component beschikbaar is in de benodigde hoeveelheid. Voor rapportage sla twee weergaven van de verkoop op:
- Verkocht item: de bundel-SKU (voor omzet, conversie en merchandising).
- Geconsumeerde componenten: uitgebreide BundleLines (voor voorraadbeweging, COGS en picklijsten).
In AppMaster past dit natuurlijk: een Bundle-tabel plus BundleLine-rijen, met Business Processes die componenten bij checkout uitbreiden en zowel de bundelverkoop als componentconsumptie in één transactie wegschrijven.
UI-patronen voor het kiezen van opties en varianten
Goede optie-UI houdt mensen in beweging. Slechte optie-UI laat ze raden, fouten krijgen en weggaan. De sleutel is shoppers vroeg naar een echt, koopbaar variant te begeleiden, terwijl je duidelijk toont wat hun keuzes veranderen.
Klantgericht: opties eerst, varianten daarna
Een betrouwbaar patroon is opties (Maat, Kleur, Materiaal) te tonen en vervolgens alleen keuzes te tonen die nog logisch zijn.
In plaats van klanten elke combinatie te laten kiezen en te falen bij 'Toevoegen aan winkelwagen', deactiveer onmogelijke combinaties zodra de gebruiker een keuze maakt. Bijvoorbeeld, zodra iemand Kleur = Zwart kiest, moeten maten die niet in Zwart bestaan uitgeschakeld worden (niet verwijderd), zodat de klant begrijpt wat niet beschikbaar is.
Terwijl de selectie verandert, update je de onderdelen die het meest belangrijk zijn: prijs (inclusief actieprijs en bundelkorting), hoofdfoto's (match met geselecteerde kleur of stijl), voorraadstatus (exacte variantvoorraad, niet generieke productvoorraad), levertijdschatting (als die per variant varieert) en optioneel de SKU of "artikelcode" voor support.
Houd de interface rustig. Toon een paar optiegroepen tegelijk, vermijd enorme dropdowns wanneer swatches of knoppen beter werken, en maak de huidige selectie duidelijk.
Admingericht: bewerk varianten als een spreadsheet
In admin hebben mensen snelheid nodig, geen mooie kaarten. Een variantgrid werkt goed: elke rij is een SKU, elke kolom is een optie of regel (prijs, barcode, gewicht, voorraad, actief/inactief). Voeg bulkacties toe voor veelvoorkomende taken zoals prijsupdates, beschikbaarheid togglen of afbeeldingen toewijzen.
Als je dit in AppMaster bouwt, is een praktische setup een grid verbonden aan je Variant-tabel met filters (optiewaarde, actieve status, lage voorraad), plus een bulk-updateactie die regels valideert vóór opslaan.
Stapsgewijs: variantselectie en controle van bundelbeschikbaarheid
Een selectieflow moet simpel aanvoelen, maar heeft strikte regels onder de motorkap nodig. Het doel is altijd te weten welke exacte SKU de shopper configureert en of die nu gekocht kan worden.
Variantselectie (enkel product)
Laad meer dan de productnaam en afbeeldingen. Je hebt de volledige set optiewaarden (Maat, Kleur) en de lijst van geldige variantcombinaties nodig die als SKU's bestaan.
Een betrouwbare flow:
- Haal het product op, zijn opties en alle bestaande varianten (of een compacte map van geldige combinaties).
- Bewaar de huidige selectie van de shopper (bijv. Maat=M, Kleur=Zwart) en werk die bij bij elke klik.
- Na elke wijziging vind je de bijpassende variant door geselecteerde optiewaarden te vergelijken met je variantlijst.
- Als er een match is en die is koopbaar (actief, prijs ingesteld, niet geblokkeerd), schakel "Toevoegen aan winkelwagen" in.
- Als er geen match is, houd "Toevoegen aan winkelwagen" uitgeschakeld en begeleid de shopper naar een geldige keuze.
Een klein UI-detail dat frustratie voorkomt: schakel onmogelijke optiewaarden uit zodra eerdere keuzes gemaakt zijn. Als Maat=M alleen in Zwart bestaat, toon andere kleuren als niet beschikbaar zodra M geselecteerd is.
Bundelbeschikbaarheid (kit samengesteld uit componenten)
Voor bundels is "op voorraad" geen enkel getal. Het hangt af van componenten. De gebruikelijke regel is:
bundle_available = minimum over componenten van floor(component_stock / component_qty_per_bundle)
Voorbeeld: een "Starter Kit" heeft 1 fles en 2 filters nodig. Als je 10 flessen en 9 filters hebt, is de beschikbaarheid min(floor(10/1)=10, floor(9/2)=4) = 4 kits.
Foutmeldingen moeten concreet zijn. Geef bij voorkeur "Slechts 4 kits beschikbaar (filters beperken deze bundel)" in plaats van "Uitverkocht." In AppMaster is dit eenvoudig uit te drukken in een Business Process: bereken eerst de matchende variant, dan de bundellimieten, en geef daarna een duidelijke status terug voor de UI.
Veelvoorkomende fouten en valkuilen om te vermijden
Catalogi breken wanneer je modelleert voor "alles wat mogelijk bestaat" in plaats van "wat je daadwerkelijk zult verkopen." De snelste manier om jezelf vast te zetten is alle mogelijke optiecombinaties vooraf te genereren en dan proberen het schoon te houden terwijl de catalogus groeit.
Varianten aanmaken die nooit op voorraad zullen zijn is de klassieke valkuil. Als je 4 kleuren x 6 maten x 3 materialen hebt, zijn dat 72 varianten. Als er slechts 10 ooit verkocht zullen worden, creëren de andere 62 records rommel, lokken fouten uit en vertragen rapportage.
Prijsstelling is een andere stille bron van bugs. Problemen beginnen wanneer dezelfde prijs op meerdere plekken bestaat (product, variant, prijzentabel, promotietabel) zonder één bron van waarheid. Een eenvoudige regel helpt: sla de basisprijs één keer op en sla overrides alleen op waar ze echt nodig zijn (bijv. één variant heeft een andere prijs).
Bundels en kits falen in voorraad als je zowel de bundel als zijn componenten vermindert. Als je een "Starter Kit" verkoopt die 1 fles en 2 filters bevat, leidt het verminderen van 1 kit én ook 1 fles en 2 filters ertoe dat voorraad te snel op 0 komt. Houd de bundel als verkoopbaar item, maar bereken beschikbaarheid en verminderingen vanuit de componenten.
Admin-tools kunnen schade veroorzaken als ze ongeldige data toestaan. Voeg vroeg waarborgen toe:
- Blokkeer dubbele SKU's, zelfs bij gearchiveerde items.
- Vereis dat elke variant alle optiewaarden heeft (geen "maat ontbreekt").
- Voorkom dat twee varianten dezelfde optiecombinatie delen.
- Valideer bundelcomponenten (geen nulhoeveelheden, geen ontbrekende SKU's).
Tot slot, plan voor verandering. Een nieuwe optie later toevoegen (zoals "Breedte" voor schoenen) is een migratie, geen checkbox. Beslis wat er gebeurt met bestaande varianten, hoe defaults gezet worden en hoe oude orders hun originele SKU en optie-snapshot behouden.
Snelle checks voordat je live gaat
Voordat je lanceert, loop de dingen na die in de praktijk breken: SKU's vinden, voorraad updaten en onmogelijke aankopen blokkeren.
Zorg dat elke verkoopbare SKU gemakkelijk te vinden is. Zoeken moet het vinden op naam, SKU-code, barcode/GTIN en sleutelattributen (zoals maat of kleur) ondersteunen. Als je scannen in het magazijn gebruikt, test een paar fysieke scans en bevestig dat ze op de exacte SKU uitkomen, niet alleen op het bovenliggende product.
Wees strikt over waar voorraadwijzigingen plaatsvinden. Kies één bron van waarheid (je inventarisbewegingslogica) en zorg dat elk event die gebruikt: orders, annuleringen, refunds, handmatige aanpassingen en bundelassemblage. Als voorraad in twee schermen of workflows kan worden bewerkt, is drift gegarandeerd.
Launch-checks die de moeite waard zijn:
- Selecteer opties in de UI en bevestig dat ongeldige combinaties vroeg worden geblokkeerd (vóór add-to-cart), niet pas bij de checkout.
- Voor bundels: bevestig dat beschikbaarheid door het schaarste-component wordt gedreven en met de juiste hoeveelheden (2 batterijen per kit halveert de beschikbaarheid).
- Zet een SKU uit en controleer dat deze uit browse- en zoekresultaten verdwijnt, maar nog steeds correct in oude orders, facturen en rapporten verschijnt.
- Plaats een testorder, annuleer die en plaats hem opnieuw; voorraad moet terugkeren en opnieuw gereserveerd worden zonder problemen.
Als je in AppMaster bouwt, houd voorraadupdate-regels in één Business Process en roep die vanuit elk pad aan. Die gewoonte voorkomt de meeste voorraadbugs.
Voorbeeldscenario en praktische vervolgstappen
Stel je een kledingwinkel voor die nog een serieuze catalogus nodig heeft.
Je verkoopt een T‑shirt met twee opties: Maat (S, M, L) en Kleur (Zwart, Wit). Elke verkoopbare combinatie is een eigen variant met een eigen SKU, prijs (indien nodig) en voorraad.
In het schema houd je één Product-record voor "Classic T‑shirt", twee Option-records (Maat, Kleur) en meerdere Variant-records. Elke Variant slaat zijn geselecteerde optiewaarden op (bijv. Maat=M, Kleur=Zwart) en de SKU (bijv. TSH-CL-M-BLK). Voorraad wordt op Variant-niveau bijgehouden, niet op Product-niveau.
In de UI beperk keuzes en voorkom doodlopende wegen. Een schoon patroon is: toon alle Kleuren eerst, dan alleen de Maten die voor de gekozen Kleur bestaan (of andersom). Als "Wit + L" niet bestaat, maak het niet selecteerbaar of toon het als uitgeschakeld met een duidelijke notitie.
Voeg nu een bundel toe: "Gift Set" die bevat:
- 1x Classic T‑shirt (elke variant)
- 1x Sticker pack (simpel SKU)
Bundelbeschikbaarheid wordt beperkt door het krapste component. Als Sticker pack voorraad 5 is, kun je niet meer dan 5 bundels verkopen, zelfs als T‑shirts ruim op voorraad zijn. Als de bundel een specifieke T‑shirt-variant vereist (bijv. Zwart M), dan is bundelvoorraad min(StickerPackStock, BlackMStock).
Praktische vervolgstappen in AppMaster:
- Bouw de tabellen in de Data Designer (Products, Options, OptionValues, Variants, VariantOptionValues, Inventory, Bundles, BundleComponents).
- Implementeer "vind geldige varianten" en "bereken bundelbeschikbaarheid" in de Business Process Editor.
- Genereer web- en native mobiele UI's vanuit hetzelfde project, met overal dezelfde variantfilter- en beschikbaarheidsregels.
Als je snel end-to-end wilt prototypen is AppMaster (appmaster.io) ontworpen voor het bouwen van complete apps met echte bedrijfslogica — precies waar variantselectie en bundelvoorraadsregels van afhankelijk zijn.


