Pendências — Migração de Rotas EN → PT-BR
Documento de acompanhamento da migração das rotas públicas de inglês para português brasileiro.
Data: 2026-06-30
Branch: feat/rotas-pt-br
Contexto: Migração das rotas voltadas ao usuário de inglês para português brasileiro.
As rotas /about, /store, /auth, /user, /style e as subrotas de /admin/*
foram renomeadas para PT-BR. As raízes /admin, /ai, /blog, /edu e os
endpoints /api/* foram mantidos em inglês (caráter técnico/universal).
O código já está migrado, o build passa e o astro check não introduziu erros novos.
O que falta é configurar serviços externos e monitorar a reindexação.
1. Supabase — Atualizar URLs de redirecionamento de auth
Por que é pendência: O Supabase Auth envia e-mails (confirmação de cadastro,
recuperação de senha, mudança de e-mail) com um link que aponta para uma URL do site.
Essa URL é configurada no dashboard do Supabase, não no código. Com a migração,
o callback agora é /entrar/callback (antes /auth/callback).
O arquivo public/_redirects tem uma regra /auth/callback → /entrar/callback (301),
então links antigos em trânsito ainda funcionam — mas os novos e-mails disparados
após o deploy devem apontar direto para a URL nova para evitar um redirect desnecessário.
Como resolver
- Acesse https://supabase.com/dashboard/project/_/auth/url-configuration
(substitua
_pelo ID do projeto). - Em Site URL, atualize para:
https://valmor.net.br/entrar/callback - Em Redirect URLs (allowlist), adicione (mantendo as existentes):
https://valmor.net.br/entrar/callback https://preview.webapp-civ.pages.dev/entrar/callback http://localhost:4321/entrar/callback http://localhost:4322/entrar/callback - Salve. Não é necessário reiniciar o serviço.
Verificação
Após configurar, criar um usuário novo (ou pedir reset de senha) e confirmar que o
link no e-mail caí diretamente em /entrar/callback?... (sem redirect 301).
2. Google Search Console — Reenviar sitemap e monitorar reindexação
Por que é pendência: O Google indexou as URLs antigas (/about, /store, etc.).
Os redirects 301 do public/_redirects preservam o ranking, mas é necessário
reenviar o sitemap novo para acelerar a reindexação. Pode levar de dias a semanas
para o Google consolidar tudo.
Como resolver
- Acesse https://search.google.com/search-console (propriedade
valmor.net.br). - Em Sitemaps:
- Remova (ou aguarde expirar) o sitemap antigo se houver.
- Envie
https://valmor.net.br/sitemap-index.xml.
- Em Cobertura / Páginas, observe nas próximas semanas:
- As URLs antigas vão aparecer como redirecionadas (301).
- As URLs novas vão ganhar indexação progressiva.
- Manter o arquivo
public/_redirectsno ar por no mínimo 6 meses após o deploy. Remover antes disso quebra links externos/indexados e perde ranking.
Verificação
No Search Console, em Inspeção de URL, testar:
https://valmor.net.br/sobre→ deve constar como indexada após alguns dias.https://valmor.net.br/about→ deve constar como “Redirecionada”.
3. Deploy em produção — Cloudflare Pages
Por que é pendência: A migração só entra em vigor após o deploy. O
public/_redirects é processado automaticamente pelo Cloudflare Pages na borda.
Como resolver
# Deploy de preview primeiro (recomendado p/ testar _redirects em ambiente real)
npm run deploy:preview
# Após validar o preview:
npm run deploy
Verificação pós-deploy
# Testar 301s (deve retornar Location: /sobre, /loja, etc.)
curl -sI https://valmor.net.br/about | rg -i '^(http|location)'
curl -sI https://valmor.net.br/store | rg -i '^(http|location)'
curl -sI https://valmor.net.br/auth/signin | rg -i '^(http|location)'
curl -sI https://valmor.net.br/user/profile | rg -i '^(http|location)'
curl -sI https://valmor.net.br/style | rg -i '^(http|location)'
# Confirmar que rotas novas respondem 200
curl -sI https://valmor.net.br/sobre | rg '^http'
curl -sI https://valmor.net.br/loja | rg '^http'
4. (Opcional) Commit e PR
Por que é pendência: A branch feat/rotas-pt-br está local, sem commit.
O usuário deve revisar as mudanças antes de ir para master.
Como resolver
# Revisar mudancas
git diff master..HEAD --stat # depois de commitar
git status
# Commitar (apos revisao)
git add -A
git commit -m "feat: traduz rotas EN->PT-BR (/sobre /loja /entrar /conta /estilo)
- Renomeia pastas em src/pages/
- Atualiza nav, middleware, sitemap filter
- Adiciona public/_redirects com 301 para todas URLs antigas
- Mantem /admin /ai /blog /edu /api/* em ingles"
# Merge para master (opcional - pode ser via PR)
git checkout master
git merge feat/rotas-pt-br
git push origin master
Notas adicionais
- APIs mantidas em EN: Os endpoints
/api/*(incluindo/api/auth/*,/api/user/*,/api/store/*) não foram traduzidos. São URLs internas chamadas viafetch()pelo frontend, não visíveis ao usuário. - Tokens de pedido/orçamento: As URLs públicas
/loja/pedido/[token]e/loja/orcamento/[token]já estavam em PT; apenas o prefixo mudou de/store/para/loja/. O_redirectscobre os links antigos. Como o projeto está em versão0.1.0(sem tráfego significativo), o impacto é mínimo. - Manter
_redirectspor ≥6 meses para preservar qualquer link externo ou indexado pelo Google.
5. Supabase / Backend — Auditoria pós-migração
Status: Auditoria completa. Nenhuma alteração estrutural necessária no banco. Abaixo os pontos encontrados e como tratá-los.
5.1. page_views.path — histórico duplicado no analytics
O que acontece: A tabela page_views (migration 009) registra cada visita com o
path exato da URL. Após o deploy, novos registros terão paths PT (/sobre, /loja,
etc.) e o histórico anterior terá paths EN (/about, /store, etc.).
O dashboard /admin/analytics/site agrega por path exato
(inc(pageCounts, v.path)), então a mesma página aparece duas vezes no ranking
de páginas populares (ex.: /about e /sobre como entradas separadas).
Impacto: Cosmético. Não quebra nada. Para um projeto em 0.1.0 com pouco
tráfeye, é desnecessário resolver. Se quiser limpar, rodar uma query de normalização
uma única vez, após o deploy:
-- Rodar no Supabase SQL Editor após o deploy.
-- Reescreve paths antigos EN -> PT no histórico do analytics.
UPDATE page_views SET path = '/sobre' WHERE path IN ('/about', '/about/');
UPDATE page_views SET path = '/sobre/termos' WHERE path IN ('/about/terms', '/about/terms/');
UPDATE page_views SET path = '/sobre/privacidade' WHERE path IN ('/about/privacy', '/about/privacy/');
UPDATE page_views SET path = REPLACE(path, '/store/services', '/loja/servicos') WHERE path LIKE '/store/services%';
UPDATE page_views SET path = REPLACE(path, '/store/checkout', '/loja/checkout') WHERE path LIKE '/store/checkout%';
UPDATE page_views SET path = REPLACE(path, '/store/success', '/loja/sucesso') WHERE path LIKE '/store/success%';
UPDATE page_views SET path = REPLACE(path, '/store/orcamento', '/loja/orcamento') WHERE path LIKE '/store/orcamento%';
UPDATE page_views SET path = REPLACE(path, '/store/pedido', '/loja/pedido') WHERE path LIKE '/store/pedido%';
UPDATE page_views SET path = REPLACE(path, '/store/estampas', '/loja/estampas') WHERE path LIKE '/store/estampas%';
UPDATE page_views SET path = REPLACE(path, '/store/', '/loja/') WHERE path LIKE '/store/%';
UPDATE page_views SET path = '/loja' WHERE path = '/store';
UPDATE page_views SET path = REPLACE(path, '/auth/forgot-password', '/entrar/recuperar-senha') WHERE path LIKE '/auth/forgot-password%';
UPDATE page_views SET path = REPLACE(path, '/auth/reset-password', '/entrar/redefinir-senha') WHERE path LIKE '/auth/reset-password%';
UPDATE page_views SET path = REPLACE(path, '/auth/verify-email', '/entrar/verificar-email') WHERE path LIKE '/auth/verify-email%';
UPDATE page_views SET path = REPLACE(path, '/auth/callback', '/entrar/callback') WHERE path LIKE '/auth/callback%';
UPDATE page_views SET path = REPLACE(path, '/auth/signin', '/entrar') WHERE path LIKE '/auth/signin%';
UPDATE page_views SET path = '/entrar' WHERE path IN ('/auth', '/auth/');
UPDATE page_views SET path = REPLACE(path, '/user/profile', '/conta/perfil') WHERE path LIKE '/user/profile%';
UPDATE page_views SET path = REPLACE(path, '/user/addresses', '/conta/enderecos') WHERE path LIKE '/user/addresses%';
UPDATE page_views SET path = REPLACE(path, '/user/orders', '/conta/pedidos') WHERE path LIKE '/user/orders%';
UPDATE page_views SET path = REPLACE(path, '/user/orcamentos','/conta/orcamentos') WHERE path LIKE '/user/orcamentos%';
UPDATE page_views SET path = REPLACE(path, '/user/assets', '/conta/designs') WHERE path LIKE '/user/assets%';
UPDATE page_views SET path = REPLACE(path, '/user/payment', '/conta/pagamento') WHERE path LIKE '/user/payment%';
UPDATE page_views SET path = REPLACE(path, '/user/settings', '/conta/ajustes') WHERE path LIKE '/user/settings%';
UPDATE page_views SET path = '/conta' WHERE path IN ('/user', '/user/');
UPDATE page_views SET path = REPLACE(path, '/style/theme', '/estilo/tema') WHERE path LIKE '/style/theme%';
UPDATE page_views SET path = REPLACE(path, '/style/ui', '/estilo/ui') WHERE path LIKE '/style/ui%';
UPDATE page_views SET path = REPLACE(path, '/style/specs', '/estilo/specs') WHERE path LIKE '/style/specs%';
UPDATE page_views SET path = '/estilo' WHERE path IN ('/style', '/style/');
-- Subrotas de /admin/* (segunda etapa)
UPDATE page_views SET path = REPLACE(path, '/admin/products/materials', '/admin/produtos/materiais') WHERE path LIKE '/admin/products/materials%';
UPDATE page_views SET path = REPLACE(path, '/admin/products/pricing', '/admin/produtos/precos') WHERE path LIKE '/admin/products/pricing%';
UPDATE page_views SET path = REPLACE(path, '/admin/products/new', '/admin/produtos/novo') WHERE path LIKE '/admin/products/new%';
UPDATE page_views SET path = REPLACE(path, '/admin/products/', '/admin/produtos/') WHERE path LIKE '/admin/products/%';
UPDATE page_views SET path = '/admin/produtos' WHERE path = '/admin/products';
UPDATE page_views SET path = REPLACE(path, '/admin/orders/', '/admin/pedidos/') WHERE path LIKE '/admin/orders/%';
UPDATE page_views SET path = '/admin/pedidos' WHERE path = '/admin/orders';
UPDATE page_views SET path = '/admin/cupons' WHERE path = '/admin/vouchers';
UPDATE page_views SET path = '/admin/arquivos' WHERE path = '/admin/assets';
UPDATE page_views SET path = '/admin/usuarios' WHERE path = '/admin/users';
UPDATE page_views SET path = REPLACE(path, '/admin/analytics/', '/admin/estatisticas/') WHERE path LIKE '/admin/analytics/%';
UPDATE page_views SET path = '/admin/estatisticas' WHERE path = '/admin/analytics';
UPDATE page_views SET path = '/admin/configuracoes' WHERE path = '/admin/settings';
UPDATE page_views SET path = '/admin/diagnosticos' WHERE path = '/admin/auth-diagnostics';
⚠️ Não empacotar isso como migration. É uma operação one-shot de saneamento de dados históricos. Rodar manualmente após o deploy e arquivar.
5.2. Documentação do Supabase — já atualizada
Foram atualizados como parte desta migração:
- ✅
db/supabase/templates/SPEC.md— referências a/auth/callback,/store/checkout,src/pages/auth/callback.astro,signin.astrocorrigidas para/entrar/callback,/loja/checkout,src/pages/entrar/callback.astro,entrar/index.astro.
5.3. Comentário em migration antiga (não alterar)
db/supabase/migrations/031_quote_share_token.sql:5ainda menciona/store/orcamento/{token}no cabeçalho. Migrations são imutáveis depois de aplicadas em produção — o cabeçalho é histórico e reflete o estado correto à época. Não alterar.
5.4. Itens verificados — nenhuma ação necessária
| Item | Verificação | Resultado |
|---|---|---|
Templates HTML (confirm-signup, recovery, email-change) | Paths hardcoded | ✅ Só usam {{ .ConfirmationURL }} (variável) + domínio raiz |
Tabela orders | Colunas de URL | ✅ Guarda apenas order_ref e public_token; URL montada em runtime |
Tabela quote_requests | Coluna share_token | ✅ Guarda apenas o token; URL montada via quoteShareUrl() (já PT) |
Tabela profiles | Campos de URL | ✅ Sem colunas com paths de rota |
Tabela vouchers | URL de resgate | ✅ Sem URL hardcoded; o code é validado via RPC |
Tabela site_settings (migration 032) | Chaves com URL | ✅ Só guarda default_ai_model |
| Cron jobs (migrations 013, 014) | URLs hardcoded | ✅ Cron 014 pinga REST do próprio Supabase; cron 013 sonda AI providers |
| Funções RPC | URLs externas | ✅ Nenhuma gera URL de rota interna |
| RLS policies | Dependência de path | ✅ Todas baseadas em user_id/role, não em paths |
Coluna next_url/redirect_url em tabelas | Existência | ✅ Nenhuma tabela tem coluna com esse nome |
5.5. Frontend → API (mantido EN, sem impacto)
As páginas chamam os endpoints via fetch() com paths em inglês. Isso é intencional
e correto — APIs não são visíveis ao usuário. Confirmado:
fetch("/api/auth/login"),fetch("/api/auth/logout"), etc. → mantidosfetch("/api/user/update"),fetch("/api/user/avatar")→ mantidosfetch("/api/store/vouchers/validate")→ mantidofetch("/api/orders/pix"),fetch("/api/quotes/[id]/accept")→ mantidosfetch("/api/admin/orders/update-status"),fetch("/api/admin/orders/delete")→ mantidosfetch("/api/admin/pricing")→ mantido
6. Subrotas do /admin/* (segunda etapa da migração)
Status: Adicionado após usuário solicitar que as subrotas do painel admin também fossem traduzidas. Build passa, typecheck com 83 erros (= baseline, 0 novos), smoke test com 17 rotas admin respondendo 302 (área protegida por middleware).
6.1. Mapeamento aplicado
| Antes (EN) | Agora (PT) |
|---|---|
/admin/orders (e /admin/orders/[id]) | /admin/pedidos (e /admin/pedidos/[id]) |
/admin/vouchers | /admin/cupons |
/admin/products (raiz) | /admin/produtos |
/admin/products/pricing | /admin/produtos/precos |
/admin/products/materials | /admin/produtos/materiais |
/admin/products/new | /admin/produtos/novo |
/admin/assets | /admin/arquivos |
/admin/users | /admin/usuarios |
/admin/analytics/site | /admin/estatisticas/site |
/admin/analytics/ai | /admin/estatisticas/ai |
/admin/settings | /admin/configuracoes |
/admin/auth-diagnostics | /admin/diagnosticos |
/admin (raiz) | mantém (dashboard) |
/admin/orcamentos (e [id]) | mantém (já era PT) |
/admin/blog (e /editor) | mantém (universal) |
/admin/ai (e /models, /providers) | mantém (sigla) |
/admin/setup | mantém (one-shot técnico) |
6.2. _redirects atualizado
O arquivo public/_redirects ganhou a seção /admin/* com regras 301 para todas as
subrotas renomeadas (arquivos products/*, orders/*, etc.). A raiz /admin não tem
redirect (continua válida).
6.3. nav/admin.ts atualizado
Todos os href do menu lateral do painel admin apontam para as novas rotas PT-BR.
Labels já eram PT antes desta migração.
6.4. Bug pré-existente identificado (não resolvido)
Em src/pages/admin/usuarios.astro:261 há um fetch("/api/admin/contas/update-role")
— esse endpoint não existe (o correto seria /api/admin/users/update-role).
É bug pré-existente da fase EN. Não resolvido nesta migração (escopo diferente),
mas fica registrado aqui para tratamento futuro.
Outro bug pré-existente (este sim corrigido nesta migração): o href
/admin/contas em src/pages/admin/index.astro:184 apontava para rota inexistente.
Foi corrigido para /admin/usuarios.
6.5. Itens verificados — nenhuma ação adicional
| Item | Resultado |
|---|---|
/api/admin/* (settings, vouchers, orders/delete, etc.) | ✅ Mantidos em EN (internos) |
components/admin/* (imports internos) | ✅ Pastas físicas intactas (Sidebar/, assets/, icons/, ui/, ai/) |
lib/store/pricing/anchor.ts (deep-link produtos↔precos) | ✅ Atualizado para /admin/produtos/precos#... |
Subpastas dinâmicas ([id], [model], [provider]) | ✅ Mantidas — só o prefixo mudou |