Next.js Multi-Site Frontend

One codebase, one deployment, four brands. These are SEO-dependent businesses today — that constraint shapes almost every decision below more than any technical preference does.

Multi-tenancy: domain-based, single dynamic build

Next.js middleware inspects the request hostname, resolves it against sites.domain, and injects the resolved site (+ brand_config) into request context for every Server Component down the tree. One build, one deployment, serves heyaustin.com, laketravis.com, heycrestedbutte.com, 6street.com simultaneously (all pointed at the same Cloudflare Worker via custom domains, deployed with the @opennextjs/cloudflare adapter — see api-architecture.md for the full hosting decision).

Rejected alternative: separate static export/build per site. Would isolate brands more strongly, but 4x's build/deploy/monitoring overhead for a small team — not worth it unless a brand needs genuinely divergent page structure, not just theming.

Theming

brand_config (jsonb, already in sites) drives CSS custom properties (colors, fonts, logo/asset URLs) set at the root layout per request based on the resolved site. Shared component library, per-site visual identity — same pattern as the data model, applied to presentation.

Rendering strategy

SEO parity (non-negotiable for the pilot)

The current sites carry real organic search value — nothing here can regress that:

Search & browse

Maps

Keep Mapbox GL (already proven on the current sites) for the interactive map view (directory map, "near me", individual venue location pins) — no reason to switch mapping providers, venues.lat/lng already model this.

Featured content

Homepage hero/featured rail per site driven by is_featured (curator-set in the admin portal) — not a hardcoded homepage, so curators control what's promoted without a code deploy.

Navigation and homepage (confirmed against the HeyAustin design mockup)

Top nav: Events, Venues, Artists, Blog, Deals, Areas (dropdown) — Artists and Deals are content types added to the schema specifically because this mockup surfaced them (event cards credit performers; a "Half Price Cocktails, 4-6 PM" card is a recurring offer, not a one-time event). Areas maps directly to regions.

Homepage sections, top to bottom:

Footer includes "Submit an Event" — a public form creating an events row with source = 'user_submitted', landing in the same review queue as scraped/AI-ingested events (see ai-ingestion-pipeline.md) rather than publishing directly.

Handoff to mobile apps

The two mobile apps are out of scope for this Next.js work — they're separate native/Flutter clients — but they consume the same /v1 API this frontend uses. Whenever the apps get rebuilt against the new backend (tracked separately, likely late in the migration), they're pointed at the same single API, not a frontend-specific one.