Por dentro do site
Como o FC Clubs Stats funciona
O site acompanha qualquer clube do Pro Clubs: lê os números na API da EA, guarda tudo num banco Postgres e monta as páginas a partir desse histórico. A peça menos óbvia: quem conversa com a EA não é o site na Vercel, e sim um robô no GitHub Actions, porque a EA bloqueia os servidores da Vercel.
- Next.js 16· telas
- TypeScript· tudo
- Supabase Postgres· banco
- GitHub Actions· sincronização
- Vercel· hospedagem
- Tailwind + shadcn/ui· visual
- Zod· validação
Mapa geral
Cinco peças e quem fala com quem. Escolha um fluxo para ver os dados andando, ou toque numa peça.
As peças
Toque numa peça para ver o que ela faz e com quem conversa, ou escolha um fluxo nas abas para ver os dados andando passo a passo.
Onde fica o backend
Não existe um servidor próprio ligado o tempo todo: são três serviços gerenciados, dois deles em São Paulo.
Vercel · gru1 (São Paulo)
Servidor do Next.js
Funções que sobem a cada visita: montam as páginas no servidor, salvam as formações e geram os cards do WhatsApp. Não guardam nada entre uma visita e outra.
Supabase · sa-east-1 (São Paulo)
Postgres 17
O banco, com uma API automática na frente. Na mesma cidade da Vercel, então cada consulta faz uma viagem curta. Qualquer um lê; só a chave secreta grava.
GitHub Actions · servidores do GitHub
Robô de sincronização
Um script em Node 24 que liga, conversa com a EA, grava no banco e desliga. É o único que a EA aceita, e roda de graça porque o repositório é público.
Qualquer clube
Nada no código fica preso a um clube: qualquer um do Pro Clubs pode ser acompanhado, no crossplay ou no Switch.
- 1
Buscar pelo nome
Acha os clubes que o site já acompanha. A busca por nome na EA também é bloqueada na Vercel, então clubes novos entram pelo ID.
- 2
Adicionar pelo ID
Com o ID do clube na EA, o botão “Adicionar clube” pede ao robô para buscá-lo. Em 1 a 2 minutos ele aparece, com as partidas que a EA ainda guarda.
- 3
Manter atualizado
A cada 15 minutos o agendamento sincroniza até 20 clubes, começando pelos que estão há mais tempo sem atualizar.
Uma sincronização
O mesmo fluxo roda pelo agendamento, pelo botão ou pela visita a um clube desatualizado. Rodar duas vezes não duplica nada.
Etapa 1 de 5
Gatilho
Agendamento a cada 15 minutos, botão Atualizar, clube novo adicionado pelo ID ou visita a um clube com dados de mais de 20 minutos. Pedidos repetidos viram no máximo uma execução rodando e uma na fila.
Grava
Nada nesta etapa.
Código
scripts/sync-clubs.tsCamadas do código
Toque numa camada para ver do que ela depende e quem depende dela.
Só src/lib/ea fala com a EA.
Só src/lib/db fala com o banco.
src/appTelas
As rotas do site. Cada página lê o banco no servidor, passa os dados pelos cálculos e entrega o HTML pronto. Aqui também ficam as ações que salvam formações e os cards do WhatsApp.
- Usa
src/componentssrc/lib/statssrc/lib/dbsrc/services/syncsrc/lib/ea- É usada por
- Ninguém: é o ponto de entrada.
O banco
Dez tabelas, com a contagem de agora. Toque numa para ver com quem ela se liga e o que guarda.
matches
Placar, tipo de jogo, adversário, data e a impressão digital da partida.
- Chave natural
club_id + fingerprintGravar a mesma coisa de novo atualiza a linha em vez de duplicar.
- Quem grava
- Sincronização · etapa Partidas
- Colunas principais
match_typeplayed_atopponent_namegoals_for / goals_againstresult- Pertence a
clubs- Tem muitas
match_team_statsplayer_match_statsplayer_match_events
O schema completo fica em supabase/schema.sql e cada mudança entra como migração em supabase/migrations/.
Guardado ou calculado
O banco guarda só o que a EA informou. Todo o resto é calculado na hora em que a página abre.
Guardado
- O clube, os jogadores e as estatísticas da temporada como a EA mostra hoje
- Cada partida, com os números do time, do adversário e de cada jogador
- A evolução do skill rating, da divisão e do OVR (a EA só informa o valor atual)
- As formações montadas no site
Calculado ao abrir
- Noites (partidas com menos de 3 h entre si), resumo e MVP da noite
- Time da semana, prêmios do mês, recordes e cansaço da noite
- O cara decisivo, conexões de gol e duplas, impacto em campo, jogos apertados
- Raio-X, fase (em alta ou em baixa), rendimento por posição, química na escalação, duelo x1 e Rei do x1
Melhorar uma fórmula muda todo o histórico de uma vez, sem rodar nada no banco. O preço é que cada visita relê o histórico do clube; quando ele crescer muito, vale guardar as páginas prontas até a próxima sincronização.
O que a EA não dá
A API do Pro Clubs não é oficial nem documentada. Estes limites moldaram várias decisões.
Só as 10 últimas partidas
Por tipo de jogo.
Por isso a sincronização roda a cada 15 minutos: dez jogos levam mais de duas horas e meia.
Nenhum lance a lance
Não diz quem deu o passe de cada gol.
As conexões de gol só contam as assistências que os números da partida garantem.
A IA não entra
Finalizações, passes e desarmes contam só os jogadores.
Os gols do time usam o placar, que pode ter um gol da IA.
Só o setor, não a posição
Cada partida diz gol, defesa, meio ou ataque.
Time da semana e rendimento por posição trabalham por setor.
Bloqueio na Vercel
O firewall da EA recusa a Vercel e o Node 20.
O GitHub Actions com Node 24 passa, então ele faz as buscas.
Só valores atuais
Skill rating, divisão e OVR não têm histórico na EA.
O site guarda um registro a cada jogo para desenhar a evolução.
Deploy e configuração
Um git push no main publica o site: a Vercel faz o build e põe no ar. O GitHub Actions sempre roda o código do main, então a sincronização nova vale na execução seguinte.
| Configuração | Onde fica | Para quê |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | Vercel, GitHub (variável), .env.local | Endereço do bancoVercel, GitHub (variável), .env.local |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Vercel, GitHub (variável), .env.local | Chave pública: só lêVercel, GitHub (variável), .env.local |
SUPABASE_SERVICE_ROLE_KEYsecreta | Vercel, GitHub (secret), .env.local | Chave secreta: grava (sincronização e formações)Vercel, GitHub (secret), .env.local |
GITHUB_DISPATCH_TOKENsecreta | Vercel | Deixa o site pedir uma sincronização ao GitHub ActionsVercel |
EA_API_BASE_URL | Opcional | Troca o endereço da EA (padrão: proclubs.ea.com/api/fc)Opcional |
Os valores nunca ficam no código: cada um é configurado na Vercel, no GitHub e no .env.local.
Onde mexer para…
O caminho mais curto para as mudanças mais comuns. Toque num caminho para copiar.
Uma estatística nova com dados que já existem
Um cálculo novo e a tela que o mostra.
Um dado novo da EA
Validar, mapear, gravar numa etapa, criar a coluna e ler no repositório.
Mudar cores, fontes ou formas
E o design system salvo.
Um card novo para o WhatsApp
Um opengraph-image.tsx na rota, com as peças prontas.
Esquemas táticos e posições
Arquétipos e pontos fortes do FC
Frequência da sincronização
Uma tabela ou coluna nova no banco
Esta página
Retrato do código em 15/10/2026. O código é aberto: github.com/IagoLeal1/ProClubsStats.