A plataforma que tirou a gestão de um campeonato de motocross da planilha e do grupo de WhatsApp — inscrição, pagamento, documentação, resultado e ranking no mesmo lugar.
Imagens: galeria do Campeonato Paulista de Motocross
Um campeonato inteiro rodando em planilha
Organizar uma etapa de motocross envolve muito mais do que largar as motos. Cada piloto precisa se inscrever numa categoria, provar que tem licença e seguro em dia, pagar a taxa, receber um número, correr, e ter o resultado somado à pontuação da temporada. Multiplique isso por dezenas de pilotos, mais de uma dúzia de categorias e várias etapas.
Antes do Portal MX, esse fluxo vivia espalhado entre planilhas, mensagens de WhatsApp e comprovantes soltos. Os pontos de ruptura eram sempre os mesmos:
Inscrição por mensagem, com dados incompletos e retrabalho de digitação.
Documentos e comprovantes de pagamento perdidos na conversa.
Conferência manual de quem pagou, quem está regular e quem pode correr.
Ranking somado à mão depois de cada etapa — lento e sujeito a erro.
Piloto sem lugar nenhum para consultar a própria situação.
Imagens: galeria do Campeonato Paulista de Motocross
O que foi construído
O Portal MX é uma aplicação única com duas faces. A pública, onde o piloto se inscreve e o público acompanha o campeonato. E a administrativa, onde a organização conduz a operação da temporada.
Portal público
18 rotas abertas
/
/eventos
/eventos/:slug
/eventos/:slug/inscrever
/calendario
/rankings
/resultados
/noticias
/galeria
/pilotos
/pilotos/:id
/empresa
/sobre
/blog
/parceiros
/contato
/termos
/privacidade
Painel administrativo
14 módulos, acesso por papel
Dashboard
Eventos
Inscrições
Pilotos
Pagamentos
Categorias
Rankings
Calendário
Notícias
Galeria
Usuários
Logs
Analytics
Configurações
Como as peças se encaixam
É uma SPA em React servida como estático, falando direto com o Supabase. Não existe backend próprio no meio do caminho: a autorização mora no banco, em Row Level Security, e o mesmo conjunto de regras vale para qualquer cliente que se conecte.
Imagens: galeria do Campeonato Paulista de Motocross
As escolhas que sustentam o sistema
Row Level Security como fonte da verdade
Autorização
Esconder um botão no front-end não é segurança. Como o navegador fala direto com o banco, toda regra de quem-vê-o-quê está escrita em policies de RLS no Postgres — 72 delas. Um piloto lê a própria inscrição porque a policy permite, não porque a tela não mostrou o resto.
Quatro níveis de acesso, verificados no banco
Papéis
superadmin, admin, organizer e pilot. O papel vem do perfil do usuário e é lido dentro das policies, então a mesma consulta devolve conjuntos diferentes conforme quem pergunta. As rotas do admin ainda são protegidas no cliente, mas isso é conveniência de navegação — não é a barreira.
Banco versionado em migrations
Schema
São 22 migrations numeradas, do schema base às permissões e ao fluxo de inscrição. O banco é reconstruível do zero em ordem, e cada mudança tem um arquivo com data e intenção — o que evita o clássico "funciona na minha máquina" quando o schema é editado direto no painel.
React Query no lugar de estado global
Dados no cliente
Quase todo o estado da aplicação é, na verdade, estado do servidor. Delegar cache, revalidação e loading ao React Query eliminou a necessidade de um store global e manteve as telas de listagem consistentes sem sincronização manual.
Validação declarada uma vez
Formulários
Inscrição de evento tem muitos campos condicionais. Com Zod descrevendo o formato e React Hook Form ligando ao formulário, a regra de validação fica em um lugar só e o erro aparece no campo certo, sem cadeia de ifs espalhada pelo componente.
O tamanho do projeto
arquivos TypeScript
122
linhas de TS/TSX
20,4 mil
tabelas no Postgres
20
policies de RLS
72
migrations versionadas
22
módulos no admin
14
rotas públicas
18
Números apurados diretamente no código-fonte do projeto. Não incluí métricas de uso (pilotos cadastrados, inscrições processadas) porque essas eu não consigo verificar aqui.
O que eu levo daqui
Autorização perto do dado envelhece melhor. Cada tela nova herda as regras em vez de reimplementá-las.
Modelar o domínio antes da interface economizou reescrita. Categoria, etapa, inscrição e resultado são entidades com regras próprias — tratá-las como tal desde o começo evitou remendos depois.
Software para quem não é da área precisa perdoar erro. Boa parte do esforço foi em estado vazio, mensagem de erro clara e confirmação — não em funcionalidade nova.
Fazer sozinho ensina o custo real de cada decisão: quem escolhe a arquitetura é quem mantém, migra e depura ela às onze da noite.