Routes
O template inclui um Route Registry — um registro central que mapeia a URL de cada página da aplicação. A sua marca pode renomear qualquer URL sem tocar em componente nem na árvore de rotas.
Como funciona
Três arquivos formam o sistema:
| Arquivo | Papel |
|---|---|
app/types/routes.ts | Interface RoutePathMap — a lista autoritativa de chaves de rota (59 hoje). |
app/config/routes/paths.ts | Os paths default (routePaths). É este arquivo que você sobrescreve. |
app/router/routes.ts | A árvore de rotas do React Router; lê os paths via routePattern(). |
// app/config/routes/paths.ts (trecho dos defaults)
import type { RoutePathMap } from "../../types/routes";
export const routePaths: RoutePathMap = {
home: "/",
search: "/search",
casino: "/games",
"casino.play": "/games/:provider/:game",
sports: "/sports",
gamification: "/vip",
"user.data": "/user/data",
// ... (ver a lista completa abaixo)
};
Como todos os links da aplicação são gerados por routeHref() / gameHref() e a árvore de rotas usa routePattern(), mudar o mapa de paths atualiza roteamento e navegação de uma vez.
app/routes.ts na raiz do app/ tem só quatro linhas — ele exporta buildRoutes(), que monta a árvore de fato em app/router/routes.ts.
Customizando as URLs da sua marca
- Copie
app/config/routes/paths.tsparaoverrides/<brand-key>/app/config/routes/paths.ts. - Altere apenas os segmentos estáticos dos paths.
- Não renomeie os placeholders de parâmetro (
:slug,:provider,:game,:id,:type,:token) — os componentes leemuseParams()com esses nomes exatos.
O <brand-key> é derivado do ORIGIN_DOMAIN (minúsculo, pontos viram hífens): minhamarca.com → minhamarca-com.
:::danger Override é substituição do arquivo inteiro, e o mapa precisa estar completo
O sistema de override não faz deep-merge — se o arquivo existe no diretório da sua marca, ele substitui o do base por completo, sem fallback campo-a-campo. Além disso, routePaths é tipado como RoutePathMap, então o TypeScript exige todas as 59 chaves: um mapa parcial não compila.
Por isso a instrução é copiar o arquivo base inteiro e editar os valores. Comece de um arquivo completo e você nunca cai nesse erro. :::
Exemplo (trecho)
// overrides/minhamarca-com/app/config/routes/paths.ts
import type { RoutePathMap } from "~/types/routes";
export const routePaths: RoutePathMap = {
home: "/",
search: "/buscar",
"search.casino": "/buscar/cassino",
"search.sports": "/buscar/esportes",
casino: "/cassino",
"casino.live": "/cassino/ao-vivo",
"casino.category": "/cassino/categoria/:slug",
"casino.providers": "/cassino/provedores",
"casino.provider": "/cassino/provedores/:slug",
"casino.play": "/cassino/jogo/:provider/:game",
sports: "/esportes",
"sports.catchAll": "/esportes/*",
"sports.test": "/esportes-teste",
gamification: "/vip",
"gamification.missions": "/vip/missoes",
// ... e assim por diante
};
O bloco acima é um trecho ilustrativo, não um arquivo válido. O arquivo real precisa declarar as 59 chaves — copie app/config/routes/paths.ts como base.
Chaves de rota disponíveis
A lista abaixo reflete app/config/routes/paths.ts. Se divergir, o arquivo é a verdade — chaves novas são adicionadas em app/types/routes.ts.
Home e busca
| Chave | Path default |
|---|---|
home | / |
search | /search |
search.casino | /search/casino |
search.sports | /search/sports |
debug | /debug |
favorites | /favorites |
recents | /recents |
Cassino
| Chave | Path default |
|---|---|
casino | /games |
casino.live | /games/live |
casino.category | /games/category/:slug |
casino.providers | /games/providers |
casino.provider | /games/providers/:slug |
casino.play | /games/:provider/:game |
Esportes
| Chave | Path default |
|---|---|
sports | /sports |
sports.catchAll | /sports/* |
sports.test | /sports-test |
Gamificação
| Chave | Path default |
|---|---|
gamification | /vip |
gamification.missions | /vip/missions |
gamification.tournaments | /vip/tournaments |
gamification.tournament | /vip/tournaments/:id |
gamification.store | /vip/store |
gamification.miniGames | /vip/mini-games |
gamification.levels | /vip/levels |
gamification.badges | /vip/badges |
gamification.bonuses | /vip/bonuses |
Conta do usuário
| Chave | Path default |
|---|---|
user.data | /user/data |
user.wallet | /user/wallet |
user.history | /user/history |
user.config | /user/config |
user.protection | /user/protection |
user.notifications | /user/notifications |
user.validate | /user/validate/:type/:token |
user.refers | /user/refers |
user.rewards | /user/rewards |
user.incomeReport | /user/income-report |
Páginas legais
| Chave | Path default |
|---|---|
legal.page | /page/:slug |
Central de ajuda
| Chave | Path default |
|---|---|
helpCenter | /help |
help.categories | /help/categories |
help.category | /help/:slug |
help.post | /help/:slug |
Conteúdo (promoções, blog, notícias, jogo responsável, FAQ)
| Chave | Path default |
|---|---|
promotions | /promotions |
promotions.category | /promotions/:slug |
promotions.post | /promotions/:slug |
blog | /blog |
blog.category | /blog/:slug |
blog.post | /blog/:slug |
news | /news |
news.category | /news/:slug |
news.post | /news/:slug |
responsibleGaming | /responsible-gaming |
responsibleGaming.category | /responsible-gaming/:slug |
responsibleGaming.post | /responsible-gaming/:slug |
faq | /faq |
faq.category | /faq/:slug |
faq.post | /faq/:slug |
faq.game | /faq/:provider/:game |
:::info Pares categoria/post compartilham o mesmo path
help.category e help.post (e os pares equivalentes em promotions, blog, news, responsible-gaming e FAQ) apontam para o mesmo path de um segmento. Um resolver no servidor decide se renderiza listagem de categoria ou detalhe de post conforme a entidade que existe no CMS. Ao renomear, mantenha os dois pares iguais entre si.
:::
Outros
| Chave | Path default |
|---|---|
promocode | /promocode |
profiles | /perfis |
profiles.detail | /perfil/:slug |
Regras
Estas regras são verificadas em runtime por validateRoutePaths() (app/utils/routes.ts) e a violação derruba o boot com erro descritivo:
- Todo path começa com
/. - Rotas dinâmicas precisam manter seus placeholders —
:slug,:provider,:game,:id,:type,:tokennão podem ser renomeados nem removidos. sports.catchAllprecisa terminar em/*.
Além disso:
- O mapa precisa estar completo — o tipo
RoutePathMapexige todas as chaves; um override parcial não compila. - Rotas de API não fazem parte do registry —
api/*são endpoints internos do servidor e não são expostos na config de marca.
Usando rotas no código
import { routeHref, gameHref, sportPath } from "~/utils/routes";
// Rota estática
routeHref("casino"); // → "/games" (ou o path da sua marca)
// Rota dinâmica (params tipados por chave)
routeHref("casino.category", { slug: "slots" });
// Link de jogo a partir do slug "provider/game"
gameHref("pgsoft/fortune-tiger");
// Deep link do sportsbook
sportPath("/futebol/brasil");
Nunca escreva paths literais ("/games", "/vip/missions") em componentes — eles quebram assim que a marca renomeia a URL.
Adicionando ou removendo páginas
O Route Registry controla apenas as URLs. Para adicionar ou remover páginas, edite a árvore de rotas em app/router/routes.ts:
- Rotas devem ficar aninhadas dentro de
layout("routes/_layout.tsx", [...])— é ali que vivem os providers de marca/ambiente. - Use
index()para a página default de um grupo. - Use
route(routePattern("chave"), "arquivo.tsx")para páginas nomeadas. - Chaves novas precisam entrar em
app/types/routes.tse emapp/config/routes/paths.ts(e em todos os overrides de marca, já que o mapa precisa ser completo).
app/router/routes.ts é avaliado em config time, antes dos aliases do Vite existirem — por isso ele usa imports relativos (../types/routes) em vez de ~/.
Fora disso, o fork é seu: crie os componentes, páginas e hooks que precisar.