Sports
Integracao de sportsbook multi-provider no template. Suporta First (iframe), Altenar (JS SDK) e Betby (JS SDK) via o pacote @cactus-agents/sports.
Visao geral
sports.config.ts (dados estaticos, fork-overridable)
|
+---------+-----------+
| |
v v
useSportsConfig() sportsConfig (import direto) <-- client / server
| |
v v
_layout.tsx loaders / API routes
|
v
SportsAltenar / SportsBetby / SportsIframeFirst
A selecao do provider e feita 100% por configuracao — sem mudancas de codigo para trocar entre providers.
:::info Regra arquitetural
app/config contem somente dados estaticos de brand. Hooks, parsers e logica de negocio nao devem ficar em app/config. O hook useSportsConfig() vive em app/hooks/useSportsConfig.ts.
:::
Configuracao
sports.config.ts (client)
Arquivo principal de configuracao (fork-overridable):
import type { SportsModuleConfig } from "@cactus-agents/sports";
export const sportsConfig: SportsModuleConfig = {
main: null, // provider principal (/sports) — null = desabilitado
test: null, // provider de teste (/sports-test) — null = desabilitado
first: {},
altenar: {
integration: "my-brand",
libraryUrl: "https://sb1client-altenar.biahosted.com/...",
},
betby: {
brandId: "my-brand-id",
theme: "default",
libraryUrl: "https://ui.betby.com/...",
},
};
O sportsConfig e importado diretamente tanto no client quanto no server — nao ha mais um wrapper sports.server.config.ts. API routes fazem import { sportsConfig } from "~/config/sports.config".
Overrides por brand
As configuracoes podem ser sobrescritas por brand em:
overrides/<brand-key>/app/config/sports/sports.ts
<brand-key> vem de ORIGIN_DOMAIN normalizado.
Hook — useSportsConfig()
Hook central consumido por rotas e componentes. Localizado em app/hooks/useSportsConfig.ts:
import { useSportsConfig } from "~/hooks/useSportsConfig";
const {
config, // SportsModuleConfig completo
activeProvider, // provider ativo para a rota atual
hasSports, // true se main != null
hasTestRoute, // true se test != null
isTestRoute, // true se pathname = /sports-test*
getConfigFor, // retorna sub-config de um provider
} = useSportsConfig();
O hook importa sportsConfig de ~/config/sports.config e combina com getActiveProvider() do SDK para resolver o provider ativo baseado na rota atual.
Componentes
SportsIframeFirst
Renderiza <iframe> do First com comunicacao postMessage. Sincroniza navegacao bidirecional entre o iframe e React Router via URLs semanticas.
SportsAltenar
Carrega o SDK Altenar dinamicamente, inicializa com AltenarWSDK.init(), e sincroniza navegacao via onRouteChangeDetailed. Busca token de auth via /api/sports/altenar-token.
SportsBetby
Carrega o SDK Betby (BTRenderer), autentica via /api/sports/betby-jwt. Recarrega a pagina em mudancas de auth (login/logout) para reinicializar o SDK.
Rotas
| Rota | Descricao |
|---|---|
/sports | Layout + index. Renderiza o provider ativo. |
/sports/* | Catch-all. Deep links de esporte. |
/sports-test | Provider alternativo para testes. |
O layout monta o componente do provider uma vez e mantem vivo em todas as sub-rotas. O conteudo interno e controlado pelo SDK do provider, nao por rotas React.
API Routes
| Rota | Descricao |
|---|---|
api/sports/search | Busca esportiva |
api/sports/launch | Launch First (autenticado) |
api/sports/anonymous-launch | Launch First (anonimo) |
api/sports/betby-jwt | JWT para Betby |
api/sports/altenar-token | Token para Altenar |
Sidebar — sidebar-sports.config.ts
Define items de navegacao com paths por provider:
export const sportsMainItems: SportsSidebarItem[] = [
{ slug: "live", label: "Ao Vivo", firstPath: "...", betbyPath: "...", altenarPath: "..." },
{ slug: "upcoming", label: "Comeca em Breve", ... },
{ slug: "esports", label: "E-Sports", ... },
];
export const popularChampionships: SportsSidebarItem[] = [
{ slug: "brasileirao-a", label: "Brasileirao Serie A", flagCode: "BR", ... },
{ slug: "champions-league", label: "Champions League", flagCode: "EU", ... },
// ... 11 campeonatos
];
Cada item carrega firstPath, betbyPath e altenarPath. O path correto e resolvido em runtime via resolveMenuItemPath().
Configurando uma nova marca
- Criar
overrides/<brand-key>/app/config/sports/sports.ts - Definir
maincomfirst,altenar,betbyounull - Opcionalmente definir
testpara habilitar/sports-test - Configurar
altenaroubetbydentro do arquivo quando necessario - Customizar items do sidebar em
sidebar-sports.config.tsse necessario