Seu diretor regional envia um email às 16h: a nova aquisição boutique em Charleston vai ao ar em oito semanas, padrões de marca obrigatórios, motor de reservas integrado, sem exceções. Você abre sua configuração multi-site atual—dezessete instalações WordPress, cada uma com seu próprio labirinto de plugins, cada uma falhando diferente após atualizações, cada uma exigindo um ambiente de staging separado. Seu time de dev estima no mínimo doze semanas. Já vi esse cenário exato matar cronogramas de lançamento em redes hoteleiras com 8, 25, até 47 propriedades. A decisão de arquitetura que você toma hoje determina se sua próxima propriedade leva três dias ou três meses. A maioria das redes escolhe o caminho que parece seguro—depois gasta dois anos desemaranhando. Aqui está a abordagem Next.js que deixa uma plataforma única potencializar cada propriedade sem o caos.

Existe um caminho melhor. Uma única aplicação Next.js—adequadamente arquitetada—pode servir cada propriedade em uma rede hoteleira a partir de um codebase único, um pipeline de deploy único e uma camada de gerenciamento de conteúdo única. Cada propriedade recebe seu próprio branding, seu próprio conteúdo, seu próprio domínio. O time de engenharia recupera sua sanidade.

Este artigo detalha exatamente como construir esse sistema. Não teoria—padrões de arquitetura reais que usamos em projetos reais de redes hoteleiras.

Índice

Hotel Group Websites: Multi-Property Architecture with Next.js

Por que Redes Hoteleiras Precisam de uma Plataforma Unificada

A situação típica de site de rede hoteleira é assim: Propriedade A roda WordPress com um tema de 2019. Propriedade B está no Squarespace porque o sobrinho do GM configurou. Propriedade C tem um site PHP customizado que ninguém quer tocar. O site corporativo está em uma plataforma completamente diferente.

Cada atualização de propriedade exige um fluxo de trabalho diferente. Consistência de marca é um sonho impossível. Estratégia de SEO é fragmentada entre dezenas de domínios sem autoridade compartilhada. Quando a corporação decide adicionar um novo badge de amenidade ou atualizar o widget de reservas, alguém precisa fazer essa mudança em 15 lugares diferentes.

Os custos se acumulam:

  • Overhead de manutenção: Cada plataforma precisa de seu próprio hosting, patches de segurança, atualizações de plugins
  • Brand drift: Propriedades lentamente divergem das diretrizes de marca
  • Alternância de contexto do desenvolvedor: Seu time (ou agência) precisa de expertise em múltiplas plataformas
  • Lançamentos de propriedade lentos: Novas aquisições levam meses para ficar online
  • Fragmentação de analytics: Nenhuma visão unificada de performance em todo o portfólio

Uma plataforma multi-propriedade centralizada resolve tudo isso. Um codebase único. Um deployment único. Um CMS único. Conteúdo e branding por propriedade entregues por configuração, não codebases separados.

Visão Geral da Arquitetura: Um Codebase, Muitas Propriedades

Aqui está a arquitetura de alto nível que funciona:

┌─────────────────────────────────────────────┐
│              CDN / Edge Network               │
│         (Vercel, Cloudflare, Fastly)          │
├─────────────────────────────────────────────┤
│           Next.js Application                 │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐     │
│  │ Property  │ │ Property  │ │ Property  │     │
│  │ Resolver  │ │ Theming   │ │ Content   │     │
│  │ Middleware│ │ Engine    │ │ Fetcher   │     │
│  └──────────┘ └──────────┘ └──────────┘     │
├─────────────────────────────────────────────┤
│              API Layer                        │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐     │
│  │ Headless  │ │ Booking   │ │ Media     │     │
│  │ CMS       │ │ Engine    │ │ CDN       │     │
│  └──────────┘ └──────────┘ └──────────┘     │
└─────────────────────────────────────────────┘

A app Next.js atua como a camada de renderização. Middleware determina qual propriedade está sendo solicitada (via domínio, subdomínio ou caminho). O motor de temas aplica estilos específicos da propriedade. O fetcher de conteúdo puxa conteúdo com escopo de propriedade do CMS headless.

Tudo downstream—o CMS, motor de reservas, armazenamento de mídia—é consultado com um identificador de propriedade. Esse identificador é o fio que vincula todo o sistema.

Padrões de Multi-Tenancy em Next.js

Existem três abordagens primárias para multi-tenancy em Next.js. Cada uma tem tradeoffs.

Padrão 1: Roteamento Baseado em Subdomínio

Cada propriedade recebe um subdomínio: grandplaza.hotelgroup.com, seasideresort.hotelgroup.com.

Next.js middleware intercepta a solicitação, extrai o subdomínio e resolve a config da propriedade:

// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { getPropertyByDomain } from '@/lib/properties';

export function middleware(request: NextRequest) {
  const hostname = request.headers.get('host') || '';
  const subdomain = hostname.split('.')[0];
  
  const property = getPropertyByDomain(subdomain);
  
  if (!property) {
    return NextResponse.redirect(new URL('/not-found', request.url));
  }
  
  // Inject property context into headers for downstream use
  const response = NextResponse.next();
  response.headers.set('x-property-id', property.id);
  response.headers.set('x-property-slug', property.slug);
  
  return response;
}

Prós: URLs limpas, isolamento fácil de propriedade, bom para SEO se propriedades não precisam de TLDs separadas.
Contras: Gerenciamento de certificado SSL para wildcards, menos independência de marca por propriedade.

Padrão 2: Mapeamento de Domínio Customizado

Cada propriedade tem seu próprio domínio: grandplazahotel.com, seasideresort.com.

Isso é o que a maioria das redes hoteleiras realmente quer. A lógica de middleware é similar, mas você está fazendo match contra uma tabela de lookup de domínio:

const DOMAIN_MAP: Record<string, string> = {
  'grandplazahotel.com': 'grand-plaza',
  'www.grandplazahotel.com': 'grand-plaza',
  'seasideresort.com': 'seaside-resort',
  'www.seasideresort.com': 'seaside-resort',
};

Vercel suporta domínios customizados por projeto nativamente, e você pode mapear até 50 domínios no plano Pro ($20/mês a partir de 2026). Para portfólios maiores, o plano Enterprise remove esse limite.

Prós: Independência completa de marca, equity de domínio existente preservado.
Contras: Overhead de gerenciamento de DNS, provisioning de SSL mais complexo.

Padrão 3: Roteamento Baseado em Caminho

Todas as propriedades sob um domínio: hotelgroup.com/properties/grand-plaza, hotelgroup.com/properties/seaside-resort.

Prós: Mais simples de implementar, autoridade de domínio consolidada para SEO.
Contras: Menos identidade de marca por propriedade, estrutura de URL parece corporativa.

Padrão Independência de Marca Flexibilidade de SEO Complexidade de Implementação Melhor Para
Subdomínio Média Média Baixa Redes economicamente conscientes
Domínio Customizado Alta Alta Média Marcas estabelecidas
Baseado em Caminho Baixa Alta (consolidada) Mínima Novos sites de portfólio

A maioria das redes hoteleiras com as quais trabalhamos na Social Animal acaba escolhendo mapeamento de domínio customizado. Propriedades têm equity de marca em seus domínios, e times de marketing querem a independência.

Hotel Group Websites: Multi-Property Architecture with Next.js - architecture

Estratégia de CMS Headless para Redes Hoteleiras

A escolha do CMS faz ou quebra essa arquitetura. Você precisa de um sistema que suporte multi-tenancy no nível de conteúdo—onde editores da Propriedade A não podem acidentalmente modificar conteúdo da Propriedade B, mas admins corporativos podem gerenciar tudo.

Opções de CMS que Funcionam Bem

Sanity é minha escolha principal para redes hoteleiras. Suas permissões no nível de documento, configuração customizada de studio e linguagem de query GROQ tornam trivial a retrieval de conteúdo com escopo de propriedade. Você pode construir um Sanity Studio único com views workspace-por-propriedade. Preços começam em $99/mês para o plano Team (preços de 2026), e escala bem para grandes volumes de conteúdo.

Contentful funciona se você já está no seu ecossistema. O isolamento no nível de space mapeia bem para propriedades, embora possa ficar caro—cada space no plano Premium adiciona custo, e você está olhando para $2.500+/mês para necessidades de rede hoteleira em escala empresarial.

Strapi (auto-hospedado) é a opção orçamentária. Você precisará construir a camada de multi-tenancy você mesmo usando middleware customizado e controle de acesso baseado em roles, mas não há custos de licenciamento por asiento.

Nós cobrimos o processo completo de seleção de CMS em nosso guia de desenvolvimento de CMS headless.

Modelagem de Conteúdo para Hotéis

Aqui está um modelo de conteúdo que funciona em propriedades:

// Sanity schema example
export const property = defineType({
  name: 'property',
  title: 'Property',
  type: 'document',
  fields: [
    defineField({ name: 'name', type: 'string' }),
    defineField({ name: 'slug', type: 'slug' }),
    defineField({ name: 'domain', type: 'string' }),
    defineField({ name: 'brand', type: 'reference', to: [{ type: 'brand' }] }),
    defineField({ name: 'location', type: 'geopoint' }),
    defineField({ name: 'theme', type: 'propertyTheme' }),
    defineField({ name: 'bookingEngineId', type: 'string' }),
  ],
});

export const room = defineType({
  name: 'room',
  title: 'Room Type',
  type: 'document',
  fields: [
    defineField({ name: 'property', type: 'reference', to: [{ type: 'property' }] }),
    defineField({ name: 'name', type: 'string' }),
    defineField({ name: 'description', type: 'blockContent' }),
    defineField({ name: 'maxOccupancy', type: 'number' }),
    defineField({ name: 'amenities', type: 'array', of: [{ type: 'reference', to: [{ type: 'amenity' }] }] }),
    defineField({ name: 'gallery', type: 'array', of: [{ type: 'image' }] }),
  ],
});

O padrão chave: cada documento de conteúdo referencia uma property. Queries sempre filtram por propriedade. Editores só veem o conteúdo de sua propriedade. Admins corporativos veem tudo.

Componentes Compartilhados vs Customização no Nível da Propriedade

É aqui que a arquitetura fica interessante. Você quer 80% dos componentes compartilhados em propriedades, com 20% permitindo customização por propriedade.

A Camada de Temas

Crie uma configuração de tema por propriedade que alimenta seu sistema de componentes:

// types/theme.ts
export interface PropertyTheme {
  colors: {
    primary: string;
    secondary: string;
    accent: string;
    background: string;
    text: string;
  };
  typography: {
    headingFont: string;
    bodyFont: string;
  };
  logo: {
    light: string;
    dark: string;
  };
  borderRadius: 'none' | 'sm' | 'md' | 'lg';
  heroStyle: 'fullbleed' | 'contained' | 'split';
}

Tailwind CSS v4 (lançado em 2025) torna isso significativamente mais fácil com sua configuração first-CSS e suporte nativo de função de tema. Você pode definir custom properties CSS no nível de layout e tê-las cascatear por cada componente:

// app/layout.tsx
export default async function PropertyLayout({ children }: { children: React.ReactNode }) {
  const property = await getCurrentProperty();
  const theme = property.theme;
  
  return (
    <html
      style={{
        '--color-primary': theme.colors.primary,
        '--color-secondary': theme.colors.secondary,
        '--font-heading': theme.typography.headingFont,
        '--font-body': theme.typography.bodyFont,
      } as React.CSSProperties}
    >
      <body className="font-body text-text bg-background">
        {children}
      </body>
    </html>
  );
}

Composição de Componentes

Componentes compartilhados aceitam tokens de tema e renderizam diferentemente por propriedade sem lógica de branching:

// components/HeroSection.tsx
export function HeroSection({ property }: { property: Property }) {
  const heroConfig = property.theme.heroStyle;
  
  const variants = {
    fullbleed: 'h-screen w-full',
    contained: 'h-[70vh] max-w-7xl mx-auto rounded-2xl overflow-hidden',
    split: 'grid grid-cols-2 h-[80vh]',
  };
  
  return (
    <section className={variants[heroConfig]}>
      {/* Shared hero content structure */}
    </section>
  );
}

Integração do Motor de Reservas

Sites de hotéis existem por uma razão: impulsionar reservas. A integração do motor de reservas precisa ser rock solid.

A maioria das redes hoteleiras usa um destes motores de reservas: SynXis (Sabre), Pegasus, Bookassist, SiteMinder, ou um sistema de reservas central proprietário. O padrão de integração é quase sempre o mesmo: passar um identificador de propriedade, intervalo de datas e contagem de hóspedes para obter disponibilidade.

// lib/booking.ts
export async function checkAvailability({
  propertyCode,
  checkIn,
  checkOut,
  adults,
  children,
}: BookingQuery) {
  const response = await fetch(`${BOOKING_ENGINE_URL}/availability`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${BOOKING_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      hotel_code: propertyCode,
      arrival: checkIn,
      departure: checkOut,
      guests: { adults, children },
    }),
  });
  
  return response.json();
}

Para o widget de reservas em si, você tem duas opções:

  1. Iframe incorporado: O motor de reservas fornece um widget que você incorpora. Menos trabalho, menos controle.
  2. UI customizada orientada por API: Você constrói a UI de pesquisa e resultados, chama a API de reservas diretamente, e entrega apenas para o motor de reservas para pagamento. Mais trabalho, muito melhor UX.

Opção 2 é onde a arquitetura Next.js realmente brilha. Você pode construir uma experiência de reservas lindo, rápida e em marca que se sinta nativa para cada propriedade. Server Components podem pré-buscar dados de disponibilidade. O fluxo de reservas permanece em seu domínio, o que é melhor para rastreamento de conversão e SEO.

Roteamento por Domínio e Resolução de Propriedade

O fluxo de resolução de propriedade precisa ser rápido. Muito rápido. Ele roda em cada requisição única.

Aqui está o padrão que funciona em produção:

  1. Edge middleware resolve domínio → slug de propriedade (lookup em-memória, sub-milissegundo)
  2. Configuração de propriedade é cached na edge usando Vercel Edge Config ou Cloudflare KV
  3. Dados completos de propriedade (tema, navegação, conteúdo de footer) são buscados uma vez por build via ISR ou em request time com caching
// lib/property-resolver.ts
import { get } from '@vercel/edge-config';

export async function resolveProperty(hostname: string): Promise<PropertyConfig | null> {
  // First: check edge config (sub-5ms)
  const domainMap = await get<Record<string, string>>('domain-map');
  const propertySlug = domainMap?.[hostname];
  
  if (!propertySlug) return null;
  
  // Second: get full property config (cached)
  const propertyConfig = await get<PropertyConfig>(`property:${propertySlug}`);
  return propertyConfig;
}

Vercel Edge Config é perfeito para isso—é uma key-value store distribuída globalmente com latência de read sob 1ms. Custa $0 em planos Pro para até 512KB de dados, o que é bastante para uma tabela de lookup de propriedade.

Performance em Escala

Sites de hotéis têm características de performance específicas que importam:

  • Páginas pesadas em imagens: Galerias de quartos, fotos de propriedade, imagens de destino
  • Picos de tráfego sazonal: Períodos de feriados, temporada de convenção, eventos locais
  • Audiência global: Viajantes internacionais navegando de todo lugar
  • Crítico para conversão: A cada 100ms de tempo de carregamento custa reservas

Estratégia de Geração Estática

Use Incremental Static Regeneration (ISR) para páginas de propriedade. Conteúdo de hotel não muda a cada minuto—um período de revalidação de 60 segundos é geralmente fino:

// app/[propertySlug]/page.tsx
export async function generateStaticParams() {
  const properties = await getAllProperties();
  return properties.map((p) => ({ propertySlug: p.slug }));
}

export const revalidate = 60;

Para uma rede de 30 propriedades com ~20 páginas por propriedade, você está pré-gerando ~600 páginas. Next.js lida com isso sem piscar. Tempos de build ficam sob 5 minutos.

Otimização de Imagem

Componente de Imagem Next.js com um loader remoto lida com otimização de imagem por propriedade. Se você está usando Sanity, seu CDN de imagem com conversão automática de formato e redimensionamento é excelente. Cloudinary é outra opção sólida a $89/mês pelo plano Plus.

Uma página de propriedade de hotel típica deve almejar:

  • LCP sob 2.5s em conexões 4G
  • CLS de 0 (sem layout shift ao carregar imagens)
  • Peso total da página sob 1.5MB em carregamento inicial

Dashboard de Gerenciamento Centralizado

Além do CMS, redes hoteleiras precisam de dashboards operacionais. É aqui que você constrói ferramentas customizadas:

  • Visão geral de propriedade: Status de cada site de propriedade (live, staging, manutenção)
  • Frescura de conteúdo: Quais propriedades não atualizaram seu conteúdo sazonal
  • Monitoramento de performance: Core Web Vitals por propriedade
  • Rollup de analytics: Métricas de funnel de reservas em todas as propriedades

Tipicamente construímos isso como uma app Next.js separada (frequentemente com as capacidades do servidor do App Router) que se conecta às mesmas fontes de dados. O dashboard de gerenciamento é uma ferramenta interna—não precisa ser deslumbrante, mas precisa ser funcional.

Deployment e DevOps

Um codebase significa um pipeline CI/CD. Aqui está o fluxo de deployment:

  1. Code changes: PR → review → merge para main
  2. Build: Next.js constrói todas as páginas estáticas em todas as propriedades
  3. Deploy: Vercel (ou similar) faz deploy para edge network
  4. DNS: Cada domínio de propriedade aponta para o deployment

Mudanças de conteúdo não exigem um deployment. O CMS headless dispara revalidação ISR via webhook:

// app/api/revalidate/route.ts
export async function POST(request: Request) {
  const body = await request.json();
  const { propertySlug, contentType } = body;
  
  // Revalidate specific paths for the changed property
  revalidatePath(`/${propertySlug}`);
  
  if (contentType === 'room') {
    revalidatePath(`/${propertySlug}/rooms`);
  }
  
  return Response.json({ revalidated: true });
}

Comparação de Custos no Mundo Real

Vamos comparar os custos reais para uma rede hoteleira de 20 propriedades:

Categoria de Custo Sites Separados (WordPress) Plataforma Unified Next.js
Hosting (mensalmente) $2.000-4.000 (20 × WP gerenciado) $150-400 (Vercel Pro/Team)
Licenciamento de CMS $0-600 (plugins por site) $99-300 (Sanity/Contentful)
Certificados SSL $0-400 (se não usar Let's Encrypt) $0 (auto-provisionado)
Manutenção (anual) $40.000-80.000 (atualizações, segurança) $10.000-20.000
Lançamento de Nova Propriedade $5.000-15.000 por site $500-2.000 (conteúdo + config)
Total Anual (est.) $75.000-150.000 $15.000-35.000

Os números nem são próximos. E isso não leva em conta as melhorias na experiência do desenvolvedor—ter um codebase único significa seu time realmente entende o sistema. Sem mais "qual versão WordPress aquela propriedade está rodando?"

Para redes hoteleiras considerando essa abordagem, nós delineamos nossas capacidades de desenvolvimento Next.js e você pode ver nossa estrutura de preços para uma estimativa mais detalhada.

FAQ

Quanto tempo leva para migrar uma rede hoteleira para uma plataforma unified Next.js?

Para uma rede de 10-20 propriedades, espere 3-5 meses do kickoff ao launch completo. A primeira propriedade leva mais tempo (8-10 semanas) porque você está construindo a plataforma. Cada propriedade subsequente é primariamente migração de conteúdo e configuração de tema, o que leva 1-2 semanas cada. Tipicamente lançamos em ondas—3-4 propriedades por vez.

Propriedades individuais ainda podem ter páginas únicas que outras propriedades não têm?

Absolutamente. O modelo de conteúdo suporta tipos de página específicos de propriedade. Se sua propriedade resort precisa de uma seção "Wedding Venues" mas seu hotel de negócios não, essa é uma decisão de nível de conteúdo. O schema de CMS suporta tipos de página opcionais, e o roteamento dinâmico Next.js lida com renderizar qualquer página que existe no CMS para uma propriedade dada.

O que acontece quando você adquire um novo hotel e precisa adicioná-lo à plataforma?

Este é um dos maiores ganhos. Adicionar uma nova propriedade significa: criar uma entrada de propriedade no CMS, configurar o tema (cores, fontes, logo), adicionar o mapeamento de domínio, e popular conteúdo. Um time de conteúdo competente pode ter uma nova propriedade ao vivo em 1-2 semanas. Compare isso com 2-3 meses para construir um site standalone.

Como você lida com suporte multi-idioma em propriedades em diferentes países?

Next.js tem suporte de roteamento i18n integrado. Combinado com um CMS headless que suporta conteúdo localizado (Sanity e Contentful ambos fazem isso bem), você pode servir cada propriedade em seus idiomas relevantes. Uma propriedade em Barcelona pode precisar de Espanhol, Catalão, Inglês e Francês. Uma propriedade em Miami pode precisar apenas de Inglês e Espanhol. A configuração de idioma de cada propriedade é independente.

Essa arquitetura funciona com Astro em vez de Next.js?

Sim, e para algumas redes hoteleiras é realmente a melhor escolha. Se suas propriedades são primariamente orientadas por conteúdo com mínima interatividade (sem fluxo de reservas complexo, por exemplo), a arquitetura multi-página Astro pode entregar performance ainda melhor com menos JavaScript. Os padrões de multi-tenancy são similares—resolução de propriedade baseada em middleware, CMS headless com scoping de propriedade, tokens de tema por propriedade.

Como você lida com SEO quando propriedades estão em domínios separados mas servidas a partir de uma aplicação?

Cada domínio de propriedade recebe seu próprio sitemap, seu próprio robots.txt, seu próprio structured data (Hotel schema markup), e suas próprias meta tags. Da perspectiva de Google, esses são sites completamente separados. As URLs canônicas apontam para o próprio domínio de cada propriedade. Você também recebe o benefício de geração de schema markup centralizada—cada propriedade automaticamente recebe JSON-LD apropriado para hotéis, quartos, reviews e informações de negócio local.

E quanto a integrações específicas de propriedade como booking de atividades locais ou sistemas de reserva de spa?

A arquitetura de componentes suporta configuração de integração no nível de propriedade. Cada config de propriedade no CMS pode especificar quais integrações de terceiros ela usa. A camada de renderização condicionalmente inclui aqueles componentes de integração. Uma propriedade spa recebe o widget de booking de spa. Um hotel de negócios downtown recebe o configurador de sala de reunião. Esses são carregados como dynamic imports para que não afetem o bundle size para propriedades que não os usam.

Há risco de um spike de tráfego de uma propriedade afetando outras propriedades?

Em uma plataforma como Vercel ou Cloudflare Pages, na verdade não. Essas plataformas edge são projetadas para spikes de tráfego. Páginas estáticas são servidas do cache CDN, então um spike em uma propriedade não consome recursos de servidor que afetariam outra. Para rotas dinâmicas (como checks de disponibilidade em tempo real), você quereria rate limiting por propriedade para prevenir que um momento viral de uma propriedade esgote suas quotas de API do motor de reservas. Mas isso é uma preocupação no nível de API, não de hosting.