One codebase with a shared core and a thin per-brand layer on top. A brand gets its own design, its own content, its own database and its own domain, while security fixes, performance work and new core features arrive everywhere at once instead of being copied by hand into each site. Adding a brand is configuration and content, not a fork.
Do the website and the mobile app share the same backend?
Yes, and more strictly than that phrase usually means. The API is defined once in PHP, and both the TypeScript client for the web and the Dart client for the app are generated from that definition. Neither is written by hand — the linter rejects a hand-written API type. So the app cannot quietly drift out of sync with the server: a mismatch breaks the build instead of breaking production.
Is the 18-language support real, or machine translation on top?
Real. Every page exists as its own row per language, with its own text and its own URL — this FAQ lives at /frequently-asked-questions in English and at /de/haeufig-gestellte-fragen in German, not behind a translation parameter. That means each language can be written the way people in that market actually search, and it can be corrected in one language without touching the other seventeen.
Can one platform serve several brands without them interfering?
That is what it is built for. Each brand has its own database, its own domain and its own content, so one brand cannot read another's data and a content mistake in one cannot appear in another. What they share is the engine: the routing, the API layer, the admin tooling and the security work.
Cannabivo is live: a search engine for social clubs, where visitors find and compare clubs by location and clubs manage their own listing. Steel is a reference for material equivalents aimed at engineering and procurement; it is in development and not open to the public yet. Both run on the platform described in this section.