Gamification Module
O template integra o SDK @cactus-agents/gamification com Smartico como provider de gamificação. A abordagem é híbrida: UI nativa (React) para listagens e detalhes, widgets overlay do Smartico para interações que não justificam UI própria.
Configuração
gamification.config.ts
Arquivo principal de configuração client-side:
export const gamificationConfig: GamificationConfig = {
enabled: true,
provider: 'smartico',
smartico: {
libraryUrl: 'https://libs.smartico.ai/...',
labelKey: '',
brandKey: '',
visitorLabelKey: '',
visitorBrandKey: '',
allowLocalhost: true,
enableDebug: false,
requestPush: false,
},
naming: { programName: 'VIP', coinsName: 'coins' },
modules: {
missions: { enabled: true, native: true },
tournaments: { enabled: true, native: true },
store: { enabled: true, native: true },
miniGames: { enabled: true, native: true },
levels: { enabled: true, native: true },
profile: { enabled: true },
notifications: { enabled: true, native: true },
badges: { enabled: true, native: true },
bonuses: { enabled: true, native: true },
jackpots: { enabled: true, native: true },
raffles: { enabled: true, native: true },
},
};
O hook useGamificationConfig() vive em app/hooks/useGamificationConfig.ts e usa o config estático (base ou override da brand):
import { useGamificationConfig } from '~/hooks/useGamificationConfig';
const config = useGamificationConfig();
O hook verifica se as keys obrigatórias do Smartico estão configuradas (labelKey ou visitorLabelKey). Se não estiverem, enabled é forçado para false — impedindo que o SDK carregue e que a UI renderize elementos de gamificação.
O hook useGamificationEnabled() também vive no mesmo arquivo:
import { useGamificationEnabled } from '~/hooks/useGamificationConfig';
const enabled = useGamificationEnabled(); // true se config.enabled && keys configuradas
Os arquivos podem ser sobrescritos por brand em:
overrides/<brand-key>/app/config/gamification/gamification.tsoverrides/<brand-key>/app/config/gamification/gamification.server.ts
<brand-key> vem de ORIGIN_DOMAIN normalizado.
gamification.server.config.ts
Configuração server-side para geração do hash de autenticação. Exporta o objeto smarticoHashConfig:
import { smarticoHashConfig } from '~/config/gamification.server.config';
// smarticoHashConfig.saltKey — usado apenas como fallback
A saltKey é um segredo server-side e não deve ser commitada nos arquivos de override. Em vez disso, use a variável de ambiente SMARTICO_SALT_KEY.
Prioridade de resolução da saltKey:
SMARTICO_SALT_KEYvia env var da Cloudflare (secret)SMARTICO_SALT_KEYviaprocess.env(dev local /.dev.vars)smarticoHashConfig.saltKeydo config file (fallback — normalmente vazio)
Inicialização
O componente SmarticoInitializer é montado no layout e gerencia todo o ciclo de vida:
SmarticoInitializer
├── 1. Carrega script Smartico dinamicamente
├── 2. Inicializa SDK com labelKey/brandKey
├── 3. Aguarda sdkReady + auth.hydrated
├── 4a. Autenticado:
│ ├── Identifica via hash MD5 (do loader)
│ ├── Carrega: profile, missions, badges, tournaments,
│ │ storeItems, miniGames, levels, currentLevel,
│ │ bonuses, jackpots, raffles, inboxUnread, translations
│ └── Aplica resolveTranslations (i18n Smartico)
└── 4b. Visitante:
├── Inicializa via vapi()
├── Carrega: missions, tournaments, storeItems, miniGames,
│ levels, jackpots, raffles, translations
└── Aplica resolveTranslations
Hash server-side
No _layout.tsx loader, o hash é gerado e passado ao client. O cf (Cloudflare env) é passado para que a função priorize a env var SMARTICO_SALT_KEY:
const cf = context?.cloudflare?.env;
// ...
const smarticoHash = generateSmarticoUserHash(String(auth.user.id), cf);
// Passado via loaderData para SmarticoInitializer
Internamente, generateSmarticoUserHash resolve a saltKey com prioridade:
cf.SMARTICO_SALT_KEY— env var Cloudflareprocess.env.SMARTICO_SALT_KEY— env var Node (.dev.vars)smarticoHashConfig.saltKey— config file (fallback)
Módulos (enabled / native)
Cada módulo pode ser controlado via flags:
enabled: false— módulo completamente desativado (sem botão, sem página)enabled: true, native: true— UI React própria (páginas de gamificação, modais)enabled: true, native: false— widget overlay Smartico (dp:gf_*)
Comportamento na sidebar
native: true→ botão navega viarouteHref("gamification.missions"),routeHref("gamification.tournaments"), etc.native: false→ botão abrewindow._smartico.dp(WidgetAction.MISSIONS)diretamente
Comportamento no user menu
Mesma lógica: native: true navega, native: false abre widget.
Modo visitante
Páginas de listagem funcionam sem login (dados via vapi). Ao tentar abrir detalhe de uma missão ou torneio, redireciona para modal de login.
Rotas
Os paths abaixo são os defaults — configuráveis via Route Registry (~/config/routes.paths). Use routeHref() para gerar links.
| Chave | Path padrão | Descrição |
|---|---|---|
gamification | /vip | Hub de gamificação |
gamification.missions | /vip/missions | Listagem de missões com filtros |
gamification.tournaments | /vip/tournaments | Listagem de torneios com filtros |
gamification.tournament | /vip/tournaments/:id | Detalhe de torneio (leaderboard, prêmios) |
gamification.store | /vip/store | Loja com filtros |
gamification.miniGames | /vip/mini-games | Listagem de mini-games |
gamification.levels | /vip/levels | Timeline de progresso com perfil lateral |
gamification.badges | /vip/badges | Listagem de badges |
gamification.bonuses | /vip/bonuses | Listagem de bônus |
user.notifications | /user/notifications | Inbox nativo (mensagens expandidas, marcar lidas) |
Todas registradas em routes.config.ts via routePattern().
Componentes
Layout
SmarticoInitializer— inicialização do SDK (montado no layout)SidebarVipButtons— botões highlight no topo da sidebar (torneios, missões)HeaderUserArea— menu VIP no dropdown do usuário (perfil, avatar, coins, nível)
Sections
GamificationSection— seção genérica (título + grid + skeleton + empty state)GamificationFilters— tabs + busca para páginas VIPMissionsSection/TournamentsSection/MiniGamesSection— listagens específicasInboxSection— notificações com corpos expandidos, status (lida/não lida), ações
Cards
TournamentCard, MissionCard, MiniGameCard, StoreItemCard, BadgeCard, JackpotCard, etc.
Modais
MissionDetailModal— detalhe de missão com opt-in
Habilitando/desabilitando
Para desativar um módulo, basta alterar o flag em gamification.config.ts:
modules: {
missions: { enabled: true, native: true },
tournaments: { enabled: false }, // desativado
// ...
}