FCCLUBS STATS

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.

lêchave públicabloqueado (403)pede sincronizaçãoworkflow_dispatchbusca clube, membrose partidasgravachave secretalista clubesdesatualizadosVocês: toque para ver o que fazVOCÊSnavegadorVercel: toque para ver o que fazVERCEL · NEXT.JSmonta as páginasSão Paulo (gru1)Supabase: toque para ver o que fazSUPABASE POSTGRESpartidas, jogadores,evolução e formaçõesGitHub Actions: toque para ver o que fazGITHUB ACTIONSnpm run sync · Node 24a cada 15 min ou a pedidoAPI da EA: toque para ver o que fazAPI DA EAproclubs.ea.com/api/fcnão oficial · só leitura
Vocês: toque para ver o que fazVOCÊSnavegadorVercel: toque para ver o que fazVERCEL · NEXT.JSmonta as páginasSão Paulo (gru1)Supabase: toque para ver o que fazSUPABASE POSTGRESpartidas, jogadores,evolução e formaçõesGitHub Actions: toque para ver o que fazGITHUB ACTIONSnpm run sync · Node 24a cada 15 min ou a pedidoAPI da EA: toque para ver o que fazAPI DA EAproclubs.ea.com/api/fcnão oficial · só leitura

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. 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. 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. 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.ts

Camadas 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/app

Telas

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 + fingerprint

Gravar 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çãoOnde ficaPara quê
NEXT_PUBLIC_SUPABASE_URLVercel, GitHub (variável), .env.localEndereço do bancoVercel, GitHub (variável), .env.local
NEXT_PUBLIC_SUPABASE_ANON_KEYVercel, GitHub (variável), .env.localChave pública: só lêVercel, GitHub (variável), .env.local
SUPABASE_SERVICE_ROLE_KEYsecretaVercel, GitHub (secret), .env.localChave secreta: grava (sincronização e formações)Vercel, GitHub (secret), .env.local
GITHUB_DISPATCH_TOKENsecretaVercelDeixa o site pedir uma sincronização ao GitHub ActionsVercel
EA_API_BASE_URLOpcionalTroca 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.