Pular para o conteúdo principal

Games (Casino)

Integracao do cassino no template. Lista jogos, categorias, providers, busca, start-game, votos e estatisticas via @cactus-agents/games, com cache server-side via GamesCacheService.

Arquitetura

Loader (SSR) Client
| |
v v
GamesCacheService useGamesStore (Zustand)
| |
v v
ServerCache (memory + CF Cache) API Routes → SDK
|
v
@cactus-agents/games (SDK)

Dados publicos (home, categorias, providers) sao cacheados no servidor com stale-while-revalidate. Acoes autenticadas (start-game, votos) vao direto na API.

Arquivos principais

ArquivoTipoDescricao
store/games.tsStore (Zustand)Estado completo do cassino
services/games.client.tsService (client)Client-side games service
services/games.server.tsService (server)Server-side com SDK direto
services/games.cache.server.tsService (server)Cache layer com stale-while-revalidate
config/home-rows.legacy.tsConfigOrdenação das rows da home (modo CASSINO_MODE=legacy; em api_new as rows vêm do BFF)
config/casino-rows.legacy.tsConfigRows do hub /games (modo legacy)
config/casino-live-rows.legacy.tsConfigRows do hub /games/live (modo legacy)
config/categories.personalize.config.tsConfigOverlay opcional (orderBy + displayPriority) sobre categorias vindas do BFF — ativo em legacy e api_new
config/game-details.server.tsConfig (server)SEO e descriptions de jogos (fork-overridable)
utils/game-details.server.tsUtil (server)Resolve templates e retorna details por jogo

Store — useGamesStore

Estado principal:

  • homeRows — rows da home page (banners, categorias, widgets)
  • categories / providers — metadados do catalogo
  • topWins / lastWins — maiores ganhos e ultimos ganhos
  • searchTerm / searchResults — busca
  • activeGame — jogo ativo (detalhe)
  • gameIframe — estado do iframe de jogo
  • voteState — likes/dislikes do usuario

Rotas

Os paths abaixo sao os defaults — configuraveis via Route Registry (~/config/routes.paths). Use routeHref() e gameHref() para gerar links.

ChavePath padraoDescricao
casino/gamesLobby do cassino (home rows)
casino.play/games/:provider/:gameDetalhe de jogo (SEO, stats, votos, iframe)
casino.category/games/category/:slugCategoria de jogos
casino.providers/games/providersGrid de providers
casino.provider/games/providers/:slugJogos de um provider

API Routes

RotaDescricao
api/games/searchBusca de jogos (usa cache de todos os jogos + filtro in-memory)
api/games/startStart game (autenticado)
api/games/voteCriar/remover voto
api/cache/games/purgePurge do cache de jogos

Cache server-side

O GamesCacheService encapsula todas as chamadas do SDK com cache de 2 niveis:

  1. In-memory (isolate do Worker) — hit instantaneo
  2. CF Cache API — shared entre isolates

Estrategia stale-while-revalidate

  • fresh → retorna imediatamente
  • stale → retorna imediatamente + revalida em background via waitUntil()
  • miss → fetch da API, cacheia, retorna

Metodos cacheados

MetodoCache keyDescricao
getHome(){domain}/homeLayout da homepage
getBase(){domain}/baseCategorias + providers
getAllGames(){domain}/all-gamesTodos os jogos (paginado 500/pg)
getByCategory(slug){domain}/category/{slug}Jogos por categoria
getByProvider(slug){domain}/provider/{slug}Jogos por provider
getDetail(slug){domain}/game/{slug}Detalhe de um jogo
getTopWins(){domain}/top-winsTop wins
getLastWins(){domain}/last-winsUltimos wins
search(params)(usa all-games cache)Filtro in-memory

Componentes

Home

  • GameSection — secao generica (titulo + grid/carrossel)
  • LazyGameSections — lazy load das secoes
  • GameCarousel — carrossel horizontal de jogos

Listagem

  • GameCard — card de jogo (thumbnail + nome + provider)
  • GameGrid — grid responsivo de cards
  • GamesFilterBar — filtros por categoria/provider
  • ProvidersGrid — grid de providers

Detalhe

  • GameIframe — iframe do jogo (full-screen ou embed)
  • GameDetailsBar — barra de detalhes (tags, RTP, margem, description com HTML)
  • GameStats — estatisticas por periodo
  • RelatedGames — jogos relacionados

Busca

  • SearchOverlay — overlay de busca com resultados em tempo real

Game Details Config

O arquivo config/game-details.server.ts centraliza SEO e descriptions de jogos. E server-only (nunca entra no bundle client).

Estrutura

export const gameDetails: GameDetailsConfig = {
defaults: {
meta_title: "{game_name} - Jogar Online | {brand_name}",
meta_description: "{game_name} é um jogo de cassino online disponível no {brand_name}...",
front_description: "<strong>{game_name}</strong> é um jogo de cassino online...",
},
games: {
"pgsoft/fortune-tiger": {
meta_description: "Fortune Tiger é um dos slots mais populares...",
front_description: "<strong>Fortune Tiger</strong> é um dos slots...",
// meta_title omitido → herda do defaults
},
},
};

Campos

CampoUsoFormato
meta_title<title> e og:titletexto puro
meta_description<meta description> e JSON-LDtexto puro
front_descriptionExibido na pagina do jogoHTML (<strong>, <em>, etc.)

Template tags

Tags substituidas em runtime com dados reais do jogo:

TagValor
{game_name}Nome do jogo
{game_provider}Nome do provedor
{game_rtp}RTP (fallback: 97 se nao disponivel)
{brand_name}Nome da marca (brand.settings.name)

Resolucao

  1. Se o jogo tem entry em games, cada campo presente sobrescreve o default
  2. Campos omitidos no entry herdam do defaults
  3. Apos o merge, template tags sao resolvidas com dados reais

Override por brand

O arquivo e overridable via Vite alias. Cada brand pode ter seus proprios defaults (idioma, tom de voz) e entries por jogo. Veja overrides/README.md.

Configuração — *-rows.legacy.ts

O template suporta 2 modos de cassino (CASSINO_MODE=legacy|api_new). Em legacy cada page (home, /games, /games/live) é montada a partir de um arquivo *-rows.legacy.ts (brand-overridable). Em api_new as rows vêm do BFF (GET /casino-games/page/{home,cassino,cassino_live}) e os arquivos .legacy.ts ficam dormentes.

// home-rows.legacy.ts — quando CASSINO_MODE=legacy
export const legacyHomeRows = [
{ slug: "home-banners", type: "widget" },
{ slug: "search-field", type: "widget" },
{ title: "Slots", slug: "slots", type: "games-api", maxItems: 15 },
// ...
];

Tipos de row aceitos em config: widget, games-api, providers-api, games-fixed. Todas as brands que usam modo legacy declaram as rows aqui — brands em api_new não precisam destes arquivos.

Pra curar ordenação/stat exibida em categorias BFF (tanto em legacy quanto api_new), use o overlay categories.personalize.config.ts — ver seção dedicada.