Multi-brand hotel web platform — European hotel group
In production since 20198 brands, a single Next.js + GraphQL codebase. Tech Lead React / Next.js mission since 2019.
- Next.js (custom server)
- TypeScript
- React 18
- Apollo Client
- GraphQL
- Styled Components
- Express 4
- Jest + Enzyme
- Cypress 14
- Azure DevOps
White-label platform for the e-commerce site of a major European hotel group: a single Next.js codebase that builds 8 apps in parallel, one per brand, each with its own config, Styled Components theme and dedicated port. Custom Express server with applicative middlewares, Apollo Client SSR, GraphQL backend orchestrating Drupal (CMS) + SynXis (booking) + Adyen (3DS1/3DS2 payment) + Mapbox + TripAdvisor. Strict atomic design (57 atoms + 118 molecules + 96 organisms), Jest + Cypress tests, Azure DevOps deployment with weekly release cadence. This is the very platform the neighbouring chatbot POC is embedded on.
The problem
Managing 8 different brands — each with its own visual identity, hotel catalogue, primary language, SEO funnel and product specifics — without duplicating the codebase 8 times. The classic trap: ending up with 8 diverging forks that get patched bug-by-bug and where nobody knows which fix applies to which brand.
The opposite trap: a generic site that feels like it belongs to no brand, where every color token becomes a business condition, and where adding a brand costs an entire sprint.
The solution
White-label architecture: a single Next.js codebase with a multi-brand configuration system. Each brand has its own `config/<brand>/` folder (env vars, feature flags, redirects), its own `themes/<brand>/` folder (C1…C26 tokens, fonts, icon fonts, injected via ThemeProvider Styled Components), and a dedicated local port in dev. The build orchestrates 8 Next.js builds in parallel with `NODE_OPTIONS=--max_old_space_size=4096`.
At runtime, a custom Express server runs a chain of applicative middlewares before delegating to `next()`: locale resolution (cookie → URL → Accept-Language) + GraphQL translation fetch, Apollo SSR + XSRF, Drupal CMS via API, Azure File Share for sitemap/robots/SEO feeds, route → Next page mapping, Azure App Insights + OpenTelemetry tracing.
Live in production
- 8 brands + 16 sub-brands, a single codebase
- Adyen 3DS1/3DS2 + Drop-in payment, secure bank callback
- Runtime multi-locale (cookie → URL → Accept-Language)
- Apollo Client SSR + XSRF + near-operation-file codegen
- Strict atomic design — 57 atoms / 118 molecules / 96 organisms
- HIM pages (per-hotel microsites) + StayConfigurator (booking critical path)
- PWA (@ducanh2912/next-pwa) + service worker, interactive Mapbox
- Tests Jest 29 + Enzyme + Cypress 14, Azure DevOps CI gates
- Weekly release cycle: merge tag → UAT Tuesday → Prod Thursday
- Logs Winston + Loggly + App Insights + distributed OpenTelemetry
AI process in daily delivery
Since 2024, the team has been using Claude Code as a pair-programming partner day-to-day: understanding legacy code, scaffolding atomic-design components (the 5 conventional files: .tsx + .styled.ts + .types.ts + .test.tsx + index.ts), pre-commit AI code review, generating Enzyme `shallow` tests, drafting conventional commits in French. CLAUDE.md kept up to date to scope context (weekly release conventions, fragile critical paths: StayConfigurator, Booking 3DS, Auth, server.ts).
For structural changes (3DS, journey rewrites, adding a brand) the team applies the Superpowers workflow: writing-plans before executing-plans, human review of the plan, task-by-task execution. The chatbot POC described in the neighbouring project was shipped using exactly this method.
- Claude Code (Anthropic)
- Superpowers (Jesse Vincent)
- Conventional Commits (FR)
