Aplicação Next.js 16 (App Router) com React 19 e Server Components, em que todo acesso a dados acontece no servidor. O Firebase Auth é usado no navegador só para o login com Google; o ID token é trocado por um cookie de sessão httpOnly emitido pelo Firebase Admin SDK, e a partir daí páginas e Server Actions leem e gravam no Firestore com credenciais de serviço. O conteúdo é Markdown com frontmatter versionado no repositório, sobreposto por versões que o professor salva no Firestore, com i18n PT/EN resolvido por cookie e Accept-Language sem mudar as URLs. Hospedado na Vercel.
- Front-end
- Next.js 16.2 (App Router, Server Components, Server Actions)React 19.2TypeScript 5.9Tailwind CSS 4
- Conteúdo
- Markdown com frontmatter (gray-matter)react-markdown 10 + remark-gfmdiretivas próprias para YouTubeáudio e TTS
- Autenticação
- Firebase Auth 12 (Google) no cliente + cookie de sessão do Firebase Admin SDK 14 no servidor
- Banco
- Cloud Firestore (coleções users, submissions e activities)
- Infra
- Vercelcom sitemaprobotsmanifest e imagens Open Graph geradas pelo próprio Next.js
Segurança
Sessão por cookie httpOnly, não por token no navegador
Depois do login com Google, o cliente envia o ID token para uma Route Handler que o valida com verifyIdToken e emite um session cookie de 14 dias (httpOnly, secure, sameSite=lax). Cada request do servidor valida esse cookie com verifySessionCookie; o SDK do Firebase no navegador não lê nem grava dados.
Segurança
Papéis decididos no servidor
O papel de professor vem de uma allowlist de e-mails em variável de ambiente, aplicada na sincronização do usuário no login; a regra promove, mas nunca rebaixa um professor existente. Toda Server Action começa com requireUser ou requireProfessor, então a autorização não depende do que a interface mostra.
Arquitetura
Conteúdo em duas camadas: repositório + banco
As lições base são arquivos .pt.md/.en.md versionados no git; o professor pode criar ou sobrescrever uma lição pelo editor do site, e a versão salva no Firestore tem prioridade no mesmo slug e idioma. Excluir a versão do banco volta a valer a do repositório, e o frontmatter é validado antes de salvar.
Dados
Atividades com correção automática e modelo idempotente
Cada atividade aceita questões abertas e de múltipla escolha definidas no frontmatter; a nota da múltipla escolha é calculada na Server Action, não vem do cliente. A submissão usa id determinístico uid_slug, então rascunho e envio fazem upsert no mesmo documento, e o professor grava nota e retorno nele.
Arquitetura
i18n sem mudar URLs, com fallback por lição
O idioma vem do cookie lang ou, na falta dele, do Accept-Language. Se uma lição não tem versão no idioma pedido, cai na versão em português e é sinalizada como não traduzida, para nenhuma lição sumir do catálogo.
Performance
Mídia leve e build resiliente
O vídeo do YouTube usa uma fachada que só carrega o iframe (youtube-nocookie) no clique, e a leitura em voz alta usa a Web Speech API do navegador, sem custo de servidor. O Admin SDK é inicializado de forma preguiçosa e marcado como serverExternalPackages, para o next build funcionar sem credenciais.