
Van Subdomain naar Path-Based Routing: Een Migration Story
Van Subdomain naar Path-Based Routing: Een Migration Story
Het Échte Verhaal Achter Onze Architectuurkeuzes
Als ontwikkelaar maak je keuzes. Sommige blijken achteraf perfect, andere... minder. Dit is het verhaal van hoe we twee keer pivoteerden met onze seizoensgebonden menu generator architectuur, en waarom dat juist een teken is van gezonde product development.
De Context: Tijd Was Onze Vijand
Het was begin november. De kerstperiode stond voor de deur, en restaurants begonnen massaal te zoeken naar oplossingen voor hun kerstmenu's. We hadden een werkende 21-Diner generator, en de business case voor een kerstdiner variant was kristalhelder.
Maar we zaten nog in test- en ontwikkelfase.
Fase 1: De Experimentele Start (kerstdiner.ronsaiautomatisering.nl)
Tijd: Begin november
Status: Test/ontwikkelfase
Domein: kerstdiner.ronsaiautomatisering.nl
Waarom Dit Domein?
// In dit stadium hadden we nog geen dedicated branding
// Het was letterlijk: "laten we snel testen of dit concept werkt"
const TEMPORARY_DOMAIN = "kerstdiner.ronsaiautomatisering.nl";
De Realiteit:
- ✅ Snel te deployen
- ✅ Geen DNS configuratie voor nieuw domein nodig
- ✅ Perfect voor testen
- ❌ Geen professionele branding
- ❌ Te lang en onhandig domein
- ❌ Slecht voor marketing
Maar toen gebeurde iets onverwachts...
De Pivot Die We Moesten Maken
De Druk: Kerst Komt Eraan
Begin november beseffen we: dit werkt te goed om als test te blijven. Restaurant eigenaren delen de tool, we zien tractie, en de kerstperiode is al bijna begonnen.
"We kunnen niet wachten tot januari om dit 'netjes' te doen. We moeten nu door."
Fase 2: De Eerste Pivot (kerstdiner.menumagie.nl)
Beslissing: Subdomain-based architectuur
Tijd: Midden november
Urgentie: Hoog (kerst nadert!)
De Gedachte: Subdomeinen = Flexibiliteit
// app/config/domainConfig.ts (versie 1)
const DOMAIN_CONFIG = {
"kerstdiner.menumagie.nl": {
theme: "christmas",
branding: "Kerstdiner Generator",
primaryColor: "#10b981" // kerstgroen
},
"21diner.menumagie.nl": {
theme: "casual",
branding: "21-Diner Generator",
primaryColor: "#3b82f6" // blauw
}
} as const;
export function getThemeFromHostname(hostname: string) {
return DOMAIN_CONFIG[hostname] || DOMAIN_CONFIG["21diner.menumagie.nl"];
}
Waarom Subdomeinen Logisch Leken
-
Technische Isolatie
- Elke seizoen zijn eigen "mini-app"
- Makkelijk apart te deployen
- Geen routing complexiteit
-
Branding Flexibiliteit
- Elk subdomain voelt als dedicated product
- Makkelijk te communiceren: "Ga naar kerstdiner.menumagie.nl"
-
Snelheid
- DNS record toevoegen = klaar
- Geen grote refactor nodig
- We konden binnen 2 dagen live
De Implementatie
// supabase/functions/generate-menu/index.ts (versie 1)
Deno.serve(async (req) => {
const origin = req.headers.get("origin") || "";
const hostname = new URL(origin).hostname;
// Theme detection via hostname
const config = getThemeFromHostname(hostname);
const systemPrompt = `Je bent een AI assistent voor ${config.branding}...`;
// Rest van de logic...
});
Resultaat:
- ✅ Live binnen 48 uur
- ✅ Professionele branding (menumagie.nl)
- ✅ Kerst traffic konden we opvangen
- ✅ Product leek "dedicated"
We dachten: probleem opgelost! 🎉
Maar Toen... De Marketing Realisatie
Het SEO Gesprek (Begin December)
Na 3 weken draaien met de subdomeinen zaten we met de marketeer om tafel. De vraag:
"Hoe gaan we dit schalen naar meer seizoenen? Pasen, BBQ, Valentijn..."
En toen viel het kwartje:
Het Subdomain Probleem
kerstdiner.menumagie.nl → SEO autoriteit = 0 (nieuw domein)
21diner.menumagie.nl → SEO autoriteit = 0 (nieuw domein)
pasen.menumagie.nl → SEO autoriteit = 0 (nieuw domein)
bbq.menumagie.nl → SEO autoriteit = 0 (nieuw domein)
menumagie.nl (hoofd site) → Krijgt GEEN voordeel van subdomeinen
De Pijn:
- Elke backlink naar
kerstdiner.menumagie.nlhelpt NIET21diner.menumagie.nl - Blog content op
menumagie.nl/blogversterkt de tools NIET - Google ziet subdomeinen als aparte websites
- We bouwen 10 kleine eilandjes in plaats van 1 sterk platform
De Path-Based Oplossing
menumagie.nl/kerst → Profiteert van menumagie.nl autoriteit
menumagie.nl/21-diner → Profiteert van menumagie.nl autoriteit
menumagie.nl/pasen → Profiteert van menumagie.nl autoriteit
menumagie.nl/blog → Versterkt ALLES op menumagie.nl
= Compound effect 📈
De Beslissing: Tweede Pivot
Risico: Nog een refactor (kosten: ~12-15 uur development)
Reward: Alle toekomstige marketing inspanningen stapelen op 1 domein
"Dit betaalt zich binnen 6 maanden terug. We doen het."
De Migratie: Hoe Simpel Het Eigenlijk Was
Stap 1: Theme Detection Refactor
// VOOR (hostname-based):
export function getThemeFromHostname(hostname: string) {
return DOMAIN_CONFIG[hostname] || DOMAIN_CONFIG["21diner.menumagie.nl"];
}
// NA (path-based):
export function getThemeFromPath(pathname: string): ThemeConfig {
if (pathname.startsWith("/kerst")) {
return {
theme: "christmas",
branding: "Kerstdiner Generator",
primaryColor: "#10b981"
};
}
if (pathname.startsWith("/21-diner")) {
return {
theme: "casual",
branding: "21-Diner Generator",
primaryColor: "#3b82f6"
};
}
// Default fallback
return { theme: "casual", branding: "21-Diner Generator", primaryColor: "#3b82f6" };
}
Impact: 1 file, 15 regels code veranderd.
Stap 2: Routing Aanpassen
// src/App.tsx (VOOR)
<Routes>
<Route path="/" element={<GeneratorPage />} />
<Route path="/blog" element={<BlogPage />} />
</Routes>
// src/App.tsx (NA)
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/kerst" element={<GeneratorPage theme="christmas" />} />
<Route path="/21-diner" element={<GeneratorPage theme="casual" />} />
<Route path="/blog" element={<BlogPage />} />
<Route path="/blog/:slug" element={<BlogDetailPage />} />
</Routes>
Impact: 1 file, routing logic uitbreiden.
Stap 3: Edge Function Update
// supabase/functions/generate-menu/index.ts
// VOOR: Theme uit hostname halen
const origin = req.headers.get("origin") || "";
const hostname = new URL(origin).hostname;
const config = getThemeFromHostname(hostname);
// NA: Theme uit request body halen
const { theme, preferences } = await req.json();
const config = getThemeConfig(theme); // "christmas" | "casual"
Impact: Edge function verwacht nu theme in request body.
Stap 4: Frontend Aanroep Update
// VOOR: Edge function detecteert automatisch theme via hostname
const response = await supabase.functions.invoke("generate-menu", {
body: { preferences }
});
// NA: Frontend stuurt expliciet theme mee
const response = await supabase.functions.invoke("generate-menu", {
body: {
theme: "christmas", // of "casual"
preferences
}
});
Stap 5: DNS & Redirects
# 301 redirects voor oude URLs
kerstdiner.menumagie.nl → menumagie.nl/kerst
21diner.menumagie.nl → menumagie.nl/21-diner
Totale Migratie Tijd: ~8 uur (minder dan verwacht!)
De Resultaten & Lessen
Wat We Bereikten
✅ SEO Consolidatie:
- Alle backlinks versterken nu menumagie.nl als geheel
- Blog artikelen (zoals deze!) verbeteren ranking van ALLE tools
✅ AI Search Ready:
- ChatGPT Search, Perplexity, Google SGE zien nu sterker branded platform
- Beter context begrip: "MenuMagie heeft meerdere seizoenstools"
✅ Schaalbaarheid:
- Nieuwe seizoenen (Pasen, BBQ) lanceren in < 1 dag
- Geen DNS configuratie meer nodig
- Directe SEO boost vanaf dag 1
✅ Code Eenvoud:
- Cleaner routing logic
- Makkelijker te testen (geen hostname mocking)
- Betere developer experience
De 3 Grootste Lessen
1. Fouten Maken Is Normaal (En Gezond)
We kozen eerst voor subdomeinen. Was dat "fout"? Nee. Het was de snelste oplossing voor de business need op dat moment.
Perfect is the enemy of shipped.
Door snel te shippen leerden we wat klanten écht wilden, en kregen we marketing inzichten die we niet hadden als we 2 maanden hadden zitten architecten.
2. Refactoring ≠ Failure
Development teams die nooit refactoren zijn niet aan het leren.
De tweede pivot was geen "we hadden het gelijk goed moeten doen", maar nieuwe inzichten toepassen die we 3 weken eerder nog niet hadden.
Product Evolution:
Test domein (nov week 1)
→ Subdomeinen (nov week 2-4)
→ Path-based (dec week 1)
= Sneller bij eindoplossing dan via "perfect plannen"
3. Eenvoud Wint Altijd
De uiteindelijke path-based oplossing is:
- Simpeler te begrijpen
- Makkelijker te onderhouden
- Beter voor SEO
- Flexibeler voor toekomst
Maar we hadden dit niet beredeneerd in november. We ontdekten het door te bouwen.
Conclusie: Embrace The Pivot
Dit artikel laat het échte proces zien van product development:
- ✅ Ship fast met "good enough" architectuur
- ✅ Learn van echte gebruikers en marketing data
- ✅ Refactor als je nieuwe inzichten hebt
- ✅ Communicate transparant over je keuzes
De volgende keer dat je team debatteert over "de perfecte architectuur", herinner ze aan dit verhaal:
We gingen van test domein naar subdomeinen naar paths in 4 weken. De migratie kostte 8 uur. De marketing voordelen zijn blijvend.
Dat is de trade-off die je wilt maken.
Wil je zien hoe we deze generators technisch gebouwd hebben? Check ons artikel over AI-Powered Menu Generation.
Klaar om jouw eigen seizoensproduct te lanceren?
Wil je weten hoe deze AI-oplossing voor jouw bedrijf werkt?
Van inzicht naar toepassing
De praktijkcase: een multi-tenant SaaS-evenementenplatform bouwenGerelateerde artikelen
Case study: deze website - volledig gebouwd met AI-prompting
Een diepgaande kijk op hoe deze complete business website in dagen gebouwd werd door enkel te prompten. Van concept tot live deployment, inclusief backend, beveiliging en AI-features.
Website moderniseren: van oude HTML naar een moderne website
Een verouderde HTML-website is opnieuw opgebouwd met React en bewerkbare Markdown-inhoud. Een anonieme praktijkcase over paginastructuur en beheer.
Van Google Forms naar slimme intake: een praktijkvoorbeeld
Een echte case: hoe we een intakeproces transformeerden met Tally, Make en AI. Van 45 minuten naar 5 minuten.