Sports
O template suporta quatro providers de sportsbook: First, Altenar, Betby e Rogue (SDK React nativo da Cactus, renderizado in-app).
A configuracao e feita por arquivo (base + override por marca). O config e um objeto estatico importado diretamente tanto no client quanto no server — sem wrappers ou functions intermediarias.
:::info O modulo vem desligado por default
O base ja vem com main: null, ou seja: um clone novo nao mostra esportes em lugar nenhum — nem no header, nem na sidebar. Isso e esperado. Defina main com um provider pra habilitar.
:::
Onde configurar
- Base:
app/config/sports/sports.ts(exportsportsConfig) - Override por marca:
overrides/<brand-key>/app/config/sports/sports.ts - Hook (client):
app/hooks/useSportsConfig.ts— resolve o provider ativo pela rota
O <brand-key> e derivado do ORIGIN_DOMAIN normalizado (minusculo, pontos viram hifens): minhamarca.com → minhamarca-com.
:::danger Override e substituicao do arquivo inteiro
Sem deep-merge: o arquivo da marca substitui o do base por completo. Copie o base e edite os valores — nao monte um arquivo do zero com so o main, ou vai perder as configs de provider declaradas no base.
:::
Exemplo
import type { SportsModuleConfig } from "@cactus-agents/sports";
export const sportsConfig: SportsModuleConfig = {
main: "altenar",
test: "betby",
first: {
hideBottomNav: true,
hideFooter: true,
},
altenar: {
integration: "minha-marca",
libraryUrl: "https://sb1client-altenar.biahosted.com/...",
},
betby: {
brandId: "minha-marca-id",
theme: "default",
libraryUrl: "https://ui.betby.com/...",
},
};
Configuracao por provider
Altenar
main: "altenar",
altenar: {
integration: "minha-marca",
libraryUrl: "https://sb1client-altenar.biahosted.com/...",
},
Betby
main: "betby",
betby: {
brandId: "minha-marca-id",
theme: "default",
libraryUrl: "https://ui.betby.com/...",
},
First
main: "first",
first: {
hideBottomNav: true,
hideFooter: true,
},
O First nao exige credenciais nem libraryUrl, mas tem dois campos que mudam a UX mobile:
| Campo | Default | Efeito quando true |
|---|---|---|
hideBottomNav | true | O First assume a navegacao no mobile — a barra inferior do site nao renderiza nas paginas de esportes. |
hideFooter | true | O footer do site nao renderiza nas paginas de esportes; a URL do footer e enviada ao iframe do First, que o renderiza internamente. |
Ambos valem true quando omitidos — o base os declara explicitamente so pra deixar o comportamento visivel. Marcas cujo tema do First ja traz navegacao e footer proprios, e que preferem manter os do site, precisam definir false explicitamente.
Rogue
SDK React nativo da Cactus (@cactus-agents/sports-rogue), renderizado in-app com UI/UX propria. Todos os campos de rogue sao opcionais:
main: "rogue",
rogue: {
theme: "default", // familia de cor: default | blue | green | purple | orange | red
scheme: "dark", // "dark" | "light"
oddsStyle: "decimal", // "decimal" | "malay" | "indo" | "hk" | "american"
// themeColors, brandPreferences, customAssets, logoBaseUrl, assetBaseUrl tambem aceitos
},
Para rodar o Rogue em um ambiente especifico sem mexer no main estatico da brand, use a env var FORCE_SPORTBOOK (valores: first | altenar | betby | rogue). Ela sobrescreve o main por ambiente — util quando um worker dedicado roda rogue enquanto a producao da brand segue em outro provider.
Rota de teste
Para testar um provider alternativo sem afetar /sports, defina test:
test: "betby",
Isso habilita a rota /sports-test com o provider de teste. O main continua servindo /sports.
Customizacao da sidebar
Edite app/config/layout/sidebar-sports.ts para personalizar os items de navegacao. O arquivo exporta tres arrays:
| Export | Onde aparece |
|---|---|
sportsMainItems | Items diretos da secao "Esportes" (ao vivo, comeca em breve, e-sports) |
topSportsItems | Sub-secao com os esportes mais relevantes do mercado |
popularChampionships | Sub-secao de campeonatos populares |
export const sportsMainItems: SportsSidebarItem[] = [
{ slug: "live", label: "Ao Vivo", section: "main", ... },
{ slug: "upcoming", label: "Comeca em Breve", section: "main", ... },
];
export const popularChampionships: SportsSidebarItem[] = [
{ slug: "brasileirao-a", label: "Brasileirao Serie A", flagCode: "BR", ... },
// adicione ou remova campeonatos
];
Cada item declara um path por provider que sua marca usa: firstPath, altenarPath, betbyPath e roguePath. O path certo e resolvido em runtime pelo provider ativo, entao um item sem o campo do provider ativo simplesmente nao aparece pra aquela marca.
Os roguePath do base apontam pra home do sportsbook: o esquema de URL do Rogue enderece esporte/liga/evento por slug, e os slugs sao especificos de cada mercado/idioma. Marcas em Rogue devem sobrescrever este arquivo com os deep-links dos proprios slugs.
Desabilitando
Para desabilitar completamente o modulo de esportes:
main: null,