17 de setembro de 2026 • 13 min de leitura
Como construí o Domina ENEM: arquitetura, IA aplicada e processamento de provas em escala
Como desenhei a arquitetura do Domina ENEM, combinando Next.js, Supabase, pipelines determinísticos de dados e LLMs para transformar anos de provas em dados estruturados.
Como construí o Domina ENEM: arquitetura, IA aplicada e processamento de provas em escala
O Domina ENEM nasceu de uma ideia relativamente simples: criar uma plataforma que ajudasse estudantes a se preparar para o ENEM de uma forma mais direcionada, usando seus próprios resultados para indicar onde estudar e praticar.
O problema é que transformar essa ideia em produto exigia muito mais do que criar algumas telas e armazenar questões em um banco de dados.
Eu precisava resolver problemas de arquitetura de software, processamento de dados, classificação de conteúdo educacional e inteligência artificial, além de pensar desde o início em como construir uma base que pudesse evoluir sem transformar o projeto em um grande conjunto de features desconectadas.
Neste post quero mostrar um pouco de como pensei a arquitetura do Domina ENEM, as principais tecnologias utilizadas e, principalmente, como usei IA de forma aplicada ao produto e à engenharia para resolver um dos maiores desafios do projeto: transformar anos de provas do ENEM em dados estruturados e utilizáveis pela plataforma.
O que é o Domina ENEM?
O Domina ENEM é uma plataforma de preparação para o ENEM baseada principalmente em prática, diagnóstico e acompanhamento de desempenho.
Em vez de funcionar apenas como um banco de questões, a ideia é conseguir entender progressivamente quais assuntos e habilidades o estudante domina e onde ainda existem lacunas.
Algumas das funcionalidades planejadas e desenvolvidas em torno dessa ideia incluem:
- Resolução de questões do ENEM;
- Listas de exercícios;
- Simulados;
- Diagnóstico inicial de conhecimento;
- Acompanhamento de desempenho por área, disciplina, assunto e habilidade;
- Recomendações de estudo;
- Revisão de erros;
- Flashcards;
- Metas e missões de estudo;
- Gamificação e acompanhamento de progresso.
Desde o início, uma decisão importante foi não modelar uma questão simplesmente como algo que possui um enunciado e cinco alternativas.
Para gerar inteligência sobre o aprendizado, eu precisava entender o que aquela questão realmente estava avaliando.
Por isso, a estrutura de conteúdo foi organizada aproximadamente como:
Área → Disciplina → Assunto → Subtópico → Habilidade
Essa taxonomia se tornou uma peça fundamental tanto para a arquitetura da aplicação quanto para os sistemas de recomendação e análise de desempenho.
Stack principal
A aplicação web do Domina ENEM foi construída principalmente com:
- Next.js
- React
- TypeScript
- Tailwind CSS
- shadcn/ui
- Supabase
- PostgreSQL
- Stripe
- IA generativa / LLMs
- Structured Outputs
- Prompt Engineering
- Pipelines de processamento e validação de dados
Também utilizei ferramentas de IA ao longo do processo de engenharia para acelerar tarefas de implementação, exploração de soluções, documentação e análise técnica.
Mas uma preocupação importante foi evitar o uso de IA apenas como um "gerador de código".
O objetivo passou a ser utilizar modelos como componentes de sistemas de software, com contratos claros, validações e mecanismos de controle.
Um dos maiores desafios: transformar provas do ENEM em dados
Para uma plataforma baseada em questões, existe um problema bastante óbvio: de onde vêm as questões?
O INEP disponibiliza as provas e gabaritos oficiais do ENEM, porém esses dados não chegam prontos no formato necessário para uma aplicação.
Uma prova foi feita para ser lida por uma pessoa. Uma aplicação precisa de dados estruturados.
Para cada questão, eu precisava chegar a algo semelhante a:
Questão
├── ano
├── número
├── área
├── disciplina
├── enunciado
├── alternativas
├── resposta correta
├── imagens
├── assunto
├── subtópico
├── habilidade
├── dificuldade
└── resolução
Multiplique isso por várias provas e vários anos.
Nesse momento, ficou claro que fazer toda essa curadoria manualmente não seria uma solução sustentável.
Foi aí que a IA deixou de ser apenas uma ferramenta de produtividade e passou a fazer parte da própria arquitetura de processamento do Domina ENEM.
Construindo um pipeline de extração de provas com IA
Em vez de colocar essa responsabilidade dentro da aplicação principal, criei um projeto separado para processamento dos dados.
A ideia foi tratar a importação das provas como um pipeline de dados independente, responsável por transformar diferentes fontes em um formato canônico consumido pelo Domina ENEM.
A arquitetura segue aproximadamente este fluxo:
Fontes de dados
↓
Extração
↓
Normalização
↓
Validação com gabarito oficial
↓
Processamento de assets
↓
Classificação / taxonomia
↓
Geração de resolução com IA
↓
Validação
↓
Persistência
Essa separação resolveu um problema arquitetural importante.
O Domina ENEM não precisa saber se determinada questão veio de um PDF, de uma API ou de qualquer outra fonte. Todas elas precisam chegar ao sistema seguindo o mesmo contrato.
Normalização antes da inteligência
Uma das decisões mais importantes foi não enviar dados brutos diretamente para um LLM e confiar no resultado.
Antes de qualquer enriquecimento com IA, existe uma etapa determinística de normalização. Essa etapa transforma diferentes formatos de entrada em um contrato único.
Algo conceitualmente parecido com:
interface EnemQuestion {
year: number;
number: number;
statement: string;
alternatives: Alternative[];
correctAnswer: string;
assets: Asset[];
taxonomy: {
area: string;
subject: string;
topic: string;
subtopic?: string;
skill?: string;
};
explanation?: QuestionExplanation;
}
Isso permite desacoplar completamente:
Fonte de dados → Modelo interno → Aplicação
Essa abordagem também tornou muito mais simples adicionar novas fontes no futuro.
IA como etapa de um sistema, não como fonte de verdade
Essa talvez seja uma das principais lições que tirei construindo o projeto.
LLMs são extremamente úteis para tarefas de interpretação, classificação e geração. Mas eles não deveriam ser tratados automaticamente como uma source of truth.
Por exemplo, eu não quero que um modelo "descubra" qual é a alternativa correta de uma questão do ENEM se existe um gabarito oficial publicado pelo INEP.
Nesse caso, a arquitetura correta é:
LLM → Interpretação
INEP → Verdade oficial
O gabarito oficial continua sendo utilizado para validar a resposta.
A IA entra justamente nas partes em que existe um problema semântico mais difícil de resolver apenas com regras tradicionais.
Classificando questões automaticamente
Depois da extração da questão, outro problema aparece: sobre o que exatamente essa questão trata?
Essa informação é fundamental para o Domina ENEM. Sem uma boa classificação, não seria possível dizer para um aluno:
- "Você está com dificuldade em determinado assunto."
- ou "Você precisa praticar mais questões relacionadas a essa habilidade."
Utilizei IA para auxiliar nesse processo de classificação.
Mas novamente existe uma restrição importante. O modelo não pode simplesmente inventar categorias. Ele precisa trabalhar sobre uma taxonomia conhecida pelo sistema.
Isso transforma uma tarefa completamente aberta em algo mais próximo de:
Questão + Taxonomia permitida + Regras de classificação
↓
LLM
↓
Classificação estruturada
Depois disso, a saída ainda passa por validações. Ou seja: geração probabilística + validação determinística.
Esse padrão acabou aparecendo em vários pontos da arquitetura.
Geração de resoluções com IA
Outro problema que seria extremamente caro resolver manualmente seria escrever uma resolução detalhada para milhares de questões.
Nesse caso, os LLMs são particularmente úteis. Criei um fluxo onde a IA recebe informações como:
- Enunciado;
- Alternativas;
- Resposta correta oficial;
- Contexto da questão;
- Taxonomia;
- Instruções específicas para resolução.
A partir disso, o modelo gera uma explicação estruturada.
Mas a resposta gerada não entra diretamente no sistema como conteúdo definitivo. Ela pode ser tratada como um draft, permitindo validação antes da publicação.
Isso cria uma separação importante:
AI generated → Draft → Validation → Published
Em aplicações reais de IA, considero essa distinção bastante importante. Nem todo conteúdo gerado precisa ter o mesmo nível de confiança.
Structured Outputs em vez de texto livre
Outro ponto que mudou bastante a forma como passei a trabalhar com IA foi abandonar, sempre que possível, respostas completamente livres.
Se uma aplicação espera:
{
"topic": "...",
"difficulty": "...",
"explanation": "..."
}
não faz muito sentido depender de um modelo retornando um texto que depois precisa ser interpretado de maneira frágil.
Sempre que possível, passei a trabalhar com outputs estruturados e schemas definidos.
Isso traz algumas vantagens:
- Contratos mais previsíveis;
- Menos parsing manual;
- Validação automática;
- Melhor tratamento de erros;
- Integração mais simples com TypeScript;
- Possibilidade de retry;
- Observabilidade sobre outputs inválidos.
Na prática, o LLM passa a se comportar muito mais como um componente dentro de uma arquitetura tradicional.
Validação de assets
As imagens presentes nas questões também trouxeram um problema interessante. Não bastava simplesmente baixar os arquivos. O pipeline precisava conseguir verificar se o asset recebido era realmente válido.
Por isso implementei validações como:
- Assinatura do arquivo;
- MIME type;
- Dimensões;
- Tamanho;
- Hash SHA-256;
- Associação entre questão e asset.
Isso ajuda a impedir que erros silenciosos durante a importação acabem chegando até a aplicação.
Pipeline bloqueante
Outro princípio da arquitetura foi evitar o famoso: "importa tudo e depois a gente vê o que deu errado."
Algumas validações são bloqueantes. Se uma questão não possui informações fundamentais ou falha em determinadas verificações, o pipeline não deve simplesmente persistir aquele dado.
A ideia é seguir algo próximo de:
Extract → Normalize → Validate → Enrich → Validate again → Persist
Quanto mais cedo um erro aparece no pipeline, mais barato ele é de corrigir.
Idempotência e reprocessamento
Outro desafio importante quando se trabalha com pipelines é poder executar novamente uma operação sem duplicar ou corromper os dados.
Por isso, o processo foi pensado considerando idempotência e upserts. Isso permite situações como:
Processar prova de 2023 → Corrigir algoritmo → Processar 2023 novamente → Atualizar registros existentes
sem criar cópias das mesmas questões. Esse detalhe se torna cada vez mais importante conforme a quantidade de dados cresce.
Separando a aplicação do pipeline de dados
Talvez uma das decisões arquiteturais que mais gostei no projeto tenha sido manter a aplicação principal e o pipeline como sistemas separados.
O frontend e o backend do Domina ENEM possuem responsabilidades relacionadas ao produto:
Usuário → Domina ENEM → PostgreSQL / Supabase
Enquanto o pipeline possui outra responsabilidade:
Fontes externas → Pipeline → Dados normalizados → Domina ENEM
Isso reduz bastante o acoplamento. Também significa que um problema na importação de uma prova não precisa afetar a aplicação utilizada pelos estudantes.
Usando IA também no processo de desenvolvimento
A IA também esteve presente durante o desenvolvimento do próprio produto. Mas procurei utilizá-la de maneira diferente do fluxo:
prompt → gerar código → copiar → pronto
Em vez disso, passei a trabalhar cada vez mais com IA como uma espécie de engineering collaborator.
Utilizei agentes e modelos para tarefas como:
- Exploração de arquitetura;
- Implementação de features;
- Geração de testes;
- Refactors;
- Investigação de bugs;
- Documentação;
- Criação de contratos;
- Análise de alternativas técnicas;
- Revisão de implementações;
- Processamento e classificação de dados.
Para isso funcionar bem, percebi que o contexto fornecido ao agente é tão importante quanto o próprio modelo utilizado.
Por isso fui estruturando documentação, especificações e regras de projeto que permitem aos agentes entender:
Product requirements + Architecture + Domain rules + Coding conventions + Feature specification
↓
AI Agent
↓
Implementation
Isso torna o uso de IA muito mais previsível.
O que mudou na minha forma de enxergar AI Engineering
Construir o Domina ENEM também mudou um pouco minha visão sobre desenvolvimento com IA.
No começo é muito fácil associar AI Engineering apenas à integração com uma API de um modelo. Mas os problemas mais interessantes aparecem ao redor dela.
Por exemplo:
- Como garantir que uma resposta esteja no formato esperado?
- Como validar o resultado?
- Como evitar alucinações (hallucinations)?
- Qual informação precisa vir de uma fonte determinística?
- Quando utilizar regras tradicionais em vez de IA?
- Como reprocessar milhares de registros quando um prompt ou modelo muda?
- Como versionar os resultados produzidos por IA?
- Como medir confiança?
- Como manter humanos no loop quando necessário?
É nesse ponto que AI Engineering começa a se aproximar muito mais de engenharia de software tradicional do que simplesmente de prompt engineering.
O LLM é apenas um componente. Ao redor dele ainda precisamos de contratos, pipelines, validações, observabilidade, fallback, armazenamento e regras de negócio.
Principais desafios técnicos
O Domina ENEM me colocou diante de alguns problemas especialmente interessantes:
- Transformar documentos em dados: Converter provas produzidas para humanos em registros estruturados exigiu pensar em extração, normalização, assets e validação.
- Criar uma taxonomia educacional: Não bastava armazenar questões. Era necessário estruturar o conhecimento avaliado por cada uma delas para possibilitar análises posteriores.
- Integrar IA de maneira confiável: O maior desafio não foi chamar um modelo, mas definir onde confiar nele e onde não confiar.
- Manter outputs previsíveis: Structured Outputs, schemas e validações foram fundamentais para integrar respostas probabilísticas a um sistema tipado.
- Projetar para reprocessamento: Prompts, modelos e classificações podem evoluir. A arquitetura precisava permitir reprocessar dados sem reconstruir tudo manualmente.
- Separar responsabilidades: Manter ingestão de dados, inteligência e aplicação desacopladas deixou o sistema mais fácil de evoluir.
Principais tecnologias utilizadas
No projeto tive contato ou aprofundei conhecimentos em áreas como:
- Frontend: Next.js, React, TypeScript, Tailwind CSS e shadcn/ui.
- Backend e dados: Supabase, PostgreSQL, modelagem relacional, autenticação, storage e políticas de acesso.
- AI Engineering: LLMs, Prompt Engineering, Structured Outputs, classificação semântica, geração de conteúdo, pipelines de IA e human-in-the-loop.
- Data Engineering: ETL, normalização, validação, processamento de assets, hashing, idempotência e upserts.
- Software Architecture: Separação de responsabilidades, contratos entre sistemas, pipelines, schemas, validação e design orientado a domínio.
Muito além de um projeto frontend
Como desenvolvedor com uma base forte em frontend, um dos objetivos pessoais com o Domina ENEM era justamente sair da zona de conforto.
O projeto acabou me obrigando a pensar não apenas sobre componentes React ou interfaces, mas sobre o sistema como um todo:
Produto → Experiência do usuário → Frontend → Backend → Banco de dados → Pipelines → IA → Dados externos
E essa provavelmente é a parte que mais gosto no projeto.
O Domina ENEM se tornou um laboratório real onde consigo experimentar arquitetura de software, desenvolvimento full stack, produto e Applied AI Engineering dentro de um problema concreto.
Próximos passos
Ainda existem vários problemas interessantes para resolver.
Entre eles estão formas melhores de utilizar o histórico do estudante para personalizar recomendações, avaliar proficiência, melhorar os mecanismos de revisão e explorar novas aplicações de IA dentro da experiência de estudo.
Mas existe um princípio que pretendo manter: usar IA onde ela realmente adiciona capacidade ao produto, e não simplesmente porque é possível adicionar IA.
Esse projeto tem sido uma oportunidade de aprender justamente isso: construir aplicações onde modelos de IA não são apenas uma feature isolada, mas componentes inseridos dentro de uma arquitetura de software confiável.
Se quiser conhecer o projeto:
👉 dominaenem.com