ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
Questões oficiais do ENEM e da UFPR com resolução, simulados, IA que corrige a redação e um desafio de 10 minutos por dia. Grátis para começar; o completo por um valor simbólico.
Translation pending
EducationTypeScript · PLpgSQLGitHub @TudolinOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
Plataforma de estudos para ENEM e Vestibular UFPR (uso familiar: 1 admin + alunos). Next.js (App Router) · TypeScript · Tailwind · Supabase · Vercel. Planejamento, edital UFPR 2027 e decisões: docs/00-planejamento.md. Status: Fases 1–6 concluídas. Falta só colar a chave do Gemini (passo 6 do deploy).Read the full README ↗
Plataforma de estudos para ENEM e Vestibular UFPR (uso familiar: 1 admin + alunos). Next.js (App Router) · TypeScript · Tailwind · Supabase · Vercel.
Planejamento, edital UFPR 2027 e decisões: docs/00-planejamento.md.
Status: Fases 1–6 concluídas. Falta só colar a chave do Gemini (passo 6 do deploy).
npm install
cp .env.example .env.local # preencha as chaves (abaixo)
npm run dev # http://localhost:3000
| Variável | Onde obter | Observação |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | Supabase → Project Settings → API | pública |
NEXT_PUBLIC_SUPABASE_ANON_KEY | idem (anon / publishable) | pública; protegida por RLS |
SUPABASE_SERVICE_ROLE_KEY | idem (service_role) | segredo, só servidor. Ignora RLS |
GEMINI_API_KEY | Google AI Studio → Get API key | segredo, só servidor. Sem ela, o app funciona e a IA fica desligada |
NEXT_PUBLIC_VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY | npm run vapid (gera o par) | notificações push; a privada é segredo |
VAPID_SUBJECT | opcional | mailto:[email protected] (contato para os serviços de push) |
GEMINI_MODEL | opcional | padrão gemini-flash-lite-latest (o mais barato); troque pelo nome que o AI Studio mostrar |
supabase/migrations/ em ordem: SQL Editor do painel, ou
npx supabase link --project-ref <ref> && npx supabase db push.Cada fase traz uma migration nova em supabase/migrations/ (Fase 2: …0002_question_bank.sql; Fase 3: …0003_attempts.sql; Fase 4: …0004_essays_ai.sql; Fase 5: …0005_performance.sql; Fase 6: …0006_tips.sql).
Aplique só as que ainda não rodou, em ordem. Nunca edite uma migration já aplicada.
npm run create-admin -- [email protected] "Seu Nome" "senha-forte-aqui"
Depois entre em /login e crie os alunos em Administração → Alunos: direto (você define a senha) ou por
convite por link. Em Convidar, escolha aluno ou administrador; opcionalmente, anote para quem é, trave o e-mail e
defina a validade (1–30 dias). O link /convite/<token> aparece uma única vez (o banco guarda só o hash SHA-256), vale
para um único cadastro e pode ser revogado. A pessoa cria nome, e-mail e senha e já entra logada. Precisa da migration 0009.
/ para quem não está logado (logado vai direto para /inicio), com recursos, vídeo, planos e perguntas
frequentes; Termos (/termos) e Privacidade (/privacidade) em rascunho — preencha os campos entre colchetes./cadastro ("Comece grátis"): nome, e-mail, senha, aceite dos termos (com aviso para menores)
e anti-robô Cloudflare Turnstile. Toda conta nova ganha 7 dias de Pro e passa por um onboarding (vestibular,
curso-alvo e meta diária) antes do vídeo de boas-vindas.0010): plans, plan_limits (limites editáveis sem deploy), user_limit_overrides
(limite personalizado por usuário), subscriptions e usage_events. A função entitlement(feature) é a única fonte de
verdade; a cota de correção por IA e o limite de simulados por prova já seguem o plano. A família que já usa o app
foi migrada para o plano Família sem vencimento, e contas criadas pelo admin (convite ou "Novo aluno") também.
Os valores exibidos na vitrine ficam em src/lib/plans.ts (um teste garante que batem com o banco).Configurar no Supabase (Authentication):
Sign In / Providers → Email: Confirm email.
URL Configuration: Site URL = a URL do site (ex.: https://vestibularr.com.br) e, em Redirect URLs,
adicione https://SEU-DOMINIO/auth/confirm (e http://localhost:3000/auth/confirm para testar local).
Emails: use os modelos com a identidade do app, em supabase/templates/ (já trazem o link
{{ .SiteURL }}/auth/confirm?token_hash=…, que funciona mesmo se a pessoa abrir o e-mail em outro aparelho).
Em cada aba, cole o HTML do arquivo e troque o assunto:
| Aba do Supabase | Arquivo | Assunto |
|---|---|---|
| Confirm signup | confirmar-cadastro.html | Confirme seu e-mail e zarpe no Vestibularr ⚓ |
| Change email address | trocar-email.html | Confirme seu novo e-mail no Vestibularr |
| Reset password | redefinir-senha.html | Crie uma senha nova no Vestibularr |
| Magic link | link-de-acesso.html | Seu link para entrar no Vestibularr |
O logo vem de {{ .SiteURL }}/icons/icon-192.png, então o Site URL (item 2) precisa ser o endereço público.
Esqueci minha senha: o link "Esqueci minha senha" do login abre /esqueci-senha, que manda o e-mail de Reset
password. O link do e-mail passa por /auth/confirm (type=recovery), marca um cookie de 15 minutos e leva para
/redefinir-senha, onde a pessoa cria a senha nova sem precisar da atual; ao salvar, as outras sessões caem. A
resposta do pedido é a mesma com ou sem conta (não revela quem está cadastrado). Precisa do SMTP próprio (item 4)
para chegar a qualquer pessoa.
Para volume real de cadastros, configure um SMTP próprio (o envio padrão do Supabase tem limite baixo por hora).
Vercel → Settings → Deployment Protection: deixe a Vercel Authentication em "Standard Protection" (protege só
os deploys de pré-visualização). O endereço de produção (ex.: https://vestibularr.vercel.app) tem de ser público, e é
ele que deve ir para os alunos, para o NEXT_PUBLIC_SITE_URL e para o Site URL do Supabase. Os endereços de cada
deploy (vestibularr-<hash>-<time>.vercel.app) pedem login do Vercel e mostram "Request Access" para quem não é do time.
Sem NEXT_PUBLIC_SITE_URL, o app usa o domínio de produção do projeto (VERCEL_PROJECT_PRODUCTION_URL) nos links.
Variáveis novas (.env.local e Vercel): NEXT_PUBLIC_SITE_URL, NEXT_PUBLIC_TURNSTILE_SITE_KEY e
TURNSTILE_SECRET_KEY (crie um widget gratuito em Cloudflare → Turnstile; sem as chaves, o anti-robô fica desligado).
0014)Aba Tripulação na barra inferior (o Perfil foi para o topo, no celular):
/amigo/<apelido>), pedidos, ranking da semana (zera na segunda),
desfazer, bloquear e denunciar (o admin vê em reports)./tripulacao/entrar/<código>, ranking e mural próprios.0015)npm run vapid → copie as chaves para a Vercel; o vercel.json chama /api/cron/lembretes todo dia às 19h
(horário de Brasília; o plano Hobby permite 1 cron por dia).0017): enquanto não há pagamento, todos os alunos usam o plano Pro (a cota diária de IA continua).
O admin desliga em Admin → Alunos → Beta: tudo liberado quando a assinatura entrar.0018)0016)Estudar → Baixar PDF ou EPUB (ou "Baixar em PDF/EPUB" no resultado de um simulado):
export (Grátis 5/mês, até 20 questões; Estudante 10/mês até 180; Pro/Família ilimitado).
Baixar de novo uma lista pronta não conta.Botão Foco em todas as páginas (inclusive durante a prova), que abre um painel com:
Ajustes e notas ficam no perfil (profiles.preferences.study_tools e study_notes): valem na próxima sessão e em
qualquer aparelho. Código em src/components/study-dock/ e src/lib/study-tools.ts.
public/guia/vestibularr-apresentacao-v2.mp4, ~1 min 52 s) segue a mensagem da marca (docs/brand/mensagem.md):
manifesto, todas as funcionalidades com telas reais do app e o tom pirata. É gerado a partir de docs/video/:
composição em HTML, motor de animação determinístico e trilha sintetizada (sem direitos autorais):
npx tsx docs/video/mapa.tsx # mapa do tesouro (mesmo componente do app) em 6 estados
python3 docs/video/trilha.py /tmp/trilha.wav 112.2
node docs/video/render.mjs public/guia/vestibularr-apresentacao-v2.mp4 30 /tmp/trilha.wav
As capturas usadas ficam em docs/video/shots/ (geradas pelos testes e2e; não versionadas). Ao trocar o vídeo,
mude o nome do arquivo (e GUIDE_VIDEO em src/lib/guide.ts) para nenhum cache servir o antigo.Seed do ENEM (2009–2024, ~2.900 questões; 2009–2023 vêm da API pública enem.dev e 2024 do dataset maritaca-ai/enem, Apache-2.0; baixa na hora, não versionamos os dados):
npm run seed:enem # tudo (leva ~5 min por causa do limite de taxa da API)
npm run seed:enem -- --years 2022,2023 # só alguns anos
npm run seed:enem -- --out enem.json # só baixa e valida, sem tocar no banco
É idempotente (rodar de novo atualiza). A API traz a área, mas não disciplina/assunto nem resolução comentada; a área é derivada da posição oficial (blocos de 45 questões), porque a rotulagem da API tem erros. Questões anuladas ou ausentes na fonte são puladas e listadas no final (alguns anos têm 1–3 a menos). As imagens ficam hospedadas nas fontes (enem.dev e GitHub); se saírem do ar, aparecem como imagem quebrada. 2024: a fonte só tem a versão de inglês da língua estrangeira e a questão 124 está anulada (pulada). ENEM 2025: não há dataset aberto. Opções: importar você mesmo (JSON/CSV) ou usar a extração por IA a partir do PDF oficial do INEP (planejada para depois da Fase 4, quando o Gemini estiver configurado).
Resoluções comentadas (ENEM 2019–2024, todas as questões válidas; versionadas em data/resolucoes/enem-<ano>.json;
escritas com auxílio de IA, uma por questão, resolvendo antes de olhar o gabarito e conferindo depois):
npm run seed:resolucoes # aplica todos os anos disponíveis
npm run seed:resolucoes -- --years 2023 # só um ano
Precisa das migrations 0007 e 0008. Só grava quando o gabarito bate com o do banco (divergências e ausentes são listados).
Os arquivos também trazem correções conferidas no PDF oficial do INEP (cadernos 1 e 7 e gabaritos): enunciados e
alternativas que vieram truncados ou trocados da fonte, figuras recortadas do PDF (em public/questoes/), gabaritos errados no
enem.dev (2021: 15, 25, 38, 53, 139, 145, 152; 2022: 143) e questões anuladas (desativadas). O seed:enem aplica as mesmas
correções, então rodar de novo não traz os defeitos de volta nem apaga resoluções. Ordem recomendada:
seed:enem → seed:resolucoes → seed:taxonomia.
2024: a fonte numera as questões por outro caderno; conteúdo e gabarito estão corretos, só a numeração difere do caderno 1/7.
Feedback dos alunos (migration 0022, rota /feedback e Administração → Feedbacks): o aluno manda elogio,
ideia, melhoria ou problema (com nota opcional da experiência e a tela de origem) pelo menu, pelo cartão no Início, pelo
Perfil ou pela tela de erro. O admin filtra por tipo e status, responde e marca como lido/resolvido; o aluno vê a
resposta na mesma tela. Limite de 20 por aluno por dia.
Análise do admin (migration 0023): a Visão geral mostra a turma — quantos estudaram na semana, questões por
dia (30 dias), horários e dias em que estudam, o ritmo de cada aluno (constante, regular, esporádico, parado, não
começou), quem precisa de atenção (parou, não começou, caiu na semana ou acerto baixo) e o acerto por área,
disciplina e assunto (os mais difíceis e os mais fáceis para a turma). A lista de alunos ordena por último estudo,
questões na semana, menor acerto ou nome, e filtra por ritmo. No painel de cada aluno, a seção Ritmo de estudo traz
o calendário de 12 semanas, horários, questões e minutos por dia de estudo, a semana comparada com a anterior e as
matérias do mais fraco ao mais forte, com a tendência das últimas 2 semanas.
Ajuda "?": conceitos menos óbvios (TRI, escudo, sequência, liga, XP, caderno de erros, simulado × treino…) têm um
botão "?" com explicação curta. Os textos ficam em src/lib/help.ts e o botão é <HelpTip topic="…" />.
Provas reais da UFPR e concursos (migration 0021; data/ufpr/, data/concursos/):
o vestibular da UFPR (1ª fase, PS2020 e PS2022–PS2026, 762 questões nas 7 línguas estrangeiras) e concursos de nível
médio do NC/UFPR (técnico-administrativo 2024 e 2025, 8 cargos, 139 questões). Tudo extraído do caderno oficial do
Núcleo de Concursos, que já traz o gabarito definitivo marcado (►) e as anuladas (*, puladas):
pip install pymupdf
python3 scripts/ufpr-provas.py # vestibular -> data/ufpr/ufpr-<ano>.json + figuras em public/questoes/ufpr/
python3 scripts/ufpr-provas.py --concursos # concursos -> data/concursos/<slug>.json + public/questoes/concursos/
npm run seed:provas # importa as provas com resoluções, matéria/assunto e correções
O extrator separa as questões por disciplina e língua, junta o texto-base a todas as questões que ele cita
("questões 55 a 58", "Fragen 88 bis 89"…), mantém grifos como negrito e recorta como imagem (sem o sinal do gabarito)
o que não vira texto confiável: figuras, tabelas e trechos com fórmulas. Cada questão tem resolução comentada
(data/<pasta>/resolucoes/, escrita com auxílio de IA e conferida com o gabarito oficial; o seed ignora a que diverge)
e as correções de extração conferidas no PDF ficam em data/<pasta>/correcoes.json. Nos concursos, as 30 questões
gerais (português, raciocínio matemático, informática e legislação) são as mesmas em todos os cargos do edital: entram
uma vez e ficam ligadas a cada prova (mesmo external_id). A banca CONCURSO aparece em Simulados, Treino, Exportar,
Desempenho e no onboarding (quem estuda só para concurso pula a triagem, que é do ENEM).
Para incluir outro ano ou edital, acrescente a URL em SOURCES/CONCURSOS no script e rode de novo.
Assuntos e TRI oficial (migration 0011): cada questão do ENEM 2019–2024 tem matéria e assunto
(data/taxonomia/enem-<ano>.json, taxonomia em data/taxonomia/taxonomia.json; classificados com auxílio de IA a partir das
resoluções) e os dados oficiais do INEP (data/inep/enem-<ano>.json): habilidade da Matriz de Referência (H1–H30) e os
parâmetros TRI (a, b, c) de cada item, tirados dos microdados do ENEM (ITENS_PROVA_<ano>.csv) e casados com as nossas
questões pelo gabarito (100% de concordância em todos os anos).
npm run seed:taxonomia # aplica assunto + habilidade + TRI em todos os anos
npm run seed:taxonomia -- --years 2023 # só um ano
python3 scripts/inep-itens.py <pasta> # regenera data/inep a partir dos ITENS_PROVA_<ano>.csv dos microdados
Com isso, o Desempenho e o Resultado do simulado estimam a nota pela TRI (EAP, escala 500 + 100·θ) em vez da
aproximação linear, e mostram Pontos fortes e Onde focar (assuntos que mais caem × chance de errar). Os filtros de
matéria/assunto do treino e o mapa de calor passam a funcionar para o ENEM. É a base da triagem e do plano de estudos
(docs/02-plano-engajamento.md).
Triagem (migration 0012, rota /triagem): ~32 questões reais do ENEM (8 por área, alternando) escolhidas uma a uma
pelo servidor com a TRI (item com dificuldade mais perto do θ atual, sorteado entre os 6 mais próximos; prefere questões
inéditas para o aluno). "Não sei" conta como erro; dá para encerrar antes. O gabarito só aparece no fim. O relatório mostra
nível, nota por área com faixa de incerteza, comparação com a nota de corte do curso, onde focar e pontos fortes (detalhado
nos planos pagos). Logo após o onboarding o aluno cai na triagem (com "Pular, faço depois"); o início mostra o convite até a
primeira triagem. Cota por plano: triagem (Grátis 1/mês, Estudante 2/mês, Pro e Família ilimitada) e triagem_report.
As respostas entram no Desempenho, no domínio por assunto e no caderno de erros.
Só questões com resolução: com a configuração only_solved_questions ligada (padrão), alunos só veem e sorteiam questões
com resolução comentada (ou espelho, nas discursivas) — no banco, na busca, nos simulados, treinos e revisões. Questões de
tentativas antigas continuam visíveis no histórico. O admin vê tudo e liga/desliga em Administração → Questões.
Importar provas (admin → Importar, ou aluno → Estudar → Enviar prova, que passa pela aprovação do admin):
arquivos .json ou .csv; exemplos em public/exemplo-importacao.json|csv. A prévia mostra erros por questão antes de gravar.
Reimportar a mesma prova atualiza em vez de duplicar (chave: prova + número + idioma).
op_id (idempotente) com última escrita por campo.
Indicador: Salvo / Salvando / Offline — será sincronizado.deadline_at); o cliente só calcula a diferença de relógio. Avisos aos 30 e 10 min.
Ao zerar, o servidor encerra a prova; respostas dadas antes do prazo e enviadas depois (offline) ainda contam.after(), até 60 s) e a tela acompanha o status. Notas são estimativas.ai_daily_limit_per_student (padrão 5/dia, fuso de São Paulo) em settings. Falhas não contam. Admin sem limite.npm run db:test:start # Postgres local descartável na porta 54329 (precisa dos binários do PostgreSQL)
npm test # RLS, importação, tentativas/sincronização (Postgres real), pontuação, fila offline, contraste AA
npm run typecheck && npm run lint
Os testes de RLS aplicam as migrations num Postgres puro com um shim do schema auth do Supabase
(supabase/tests/shim.sql) e verificam, por papel, o que cada usuário lê e escreve.
Vitrine em /design (somente em desenvolvimento). Tokens em src/app/globals.css;
src/lib/contrast.test.ts falha se algum par texto/fundo cair abaixo de AA nos temas claro e escuro.
Capturas da Fase 1 em docs/screenshots/fase-1/.
/dicas): 7 páginas iniciais (estrutura da redação ENEM, competências, gêneros da CPT, repertórios,
conectivos, erros comuns, estratégia de prova). O admin edita em Admin → Dicas, com prévia./busca, ícone de lupa): questões (texto completo em português), temas de redação e dicas.prefers-reduced-motion, e tamanho de fonte de leitura ajustável (Perfil e tela da prova).docs/lighthouse.md.supabase/verificar-migracoes.sql). Em Authentication → Sign In / Providers,
deixe "Allow new users to sign up" ligado (cadastro público). Em Authentication → URL Configuration,
coloque a URL da Vercel em Site URL e https://SEU-SITE/auth/confirm em Redirect URLs.main).NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY e
CRON_SECRET (um texto aleatório longo, ex.: openssl rand -hex 32). Nunca prefixe a service-role com NEXT_PUBLIC_.
Para notificações: NEXT_PUBLIC_VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT.vercel.json agenda uma chamada diária a /api/keepalive (protegida pelo CRON_SECRET),
que impede o Supabase gratuito de pausar o projeto por inatividade.GEMINI_API_KEY na Vercel
(e, se quiser, GEMINI_MODEL) e faça Redeploy. Teste enviando uma redação. Sem a chave, tudo funciona,
exceto correção e transcrição (o app avisa).Custos: Vercel Hobby (uso pessoal, não comercial), Supabase Free (500 MB de banco) e Gemini no plano gratuito
(limite diário de 5 correções por aluno configurável em settings).
/prova no modo simulado: 82 (detalhes em docs/lighthouse.md).