Mindforge
Visão Geral
Mindforge é uma ferramenta de estudo para auxiliar na preparação para concursos públicos brasileiros. O sistema permite validar e gerar materiais de estudo a partir de arquivos Markdown hospedados em repositórios Git, utilizando IA (API compatível com OpenRouter/OpenAI) para processamento.
A interface é em português brasileiro e possui um tema claro quente com estética vintage acadêmica — tons de creme, pergaminho e dourado com texturas de papel, seguindo as diretrizes em GUIDELINES-ESTILO.md.
Stack Tecnológica
Frontend (Mindforge.Web)
| Tecnologia |
Versão |
Finalidade |
| Preact |
^10.29.0 |
Biblioteca de interface (alternativa leve ao React) |
| Vite |
^8.0.1 |
Ferramenta de build e servidor de desenvolvimento |
| TypeScript |
~5.9.3 |
Tipagem estática |
| marked |
^17.0.4 |
Renderização Markdown -> HTML |
| diff |
^8.0.3 |
Diff de texto (word-level) |
Nota: marked v17+ inclui tipos TypeScript nativos. @types/marked foi removido. @types/diff v7 permanece em devDependencies como fallback de tipos.
| Google Fonts (Inter) | 400..950 (variável) | Tipografia da interface |
Backend API (Mindforge.API)
| Tecnologia |
Versão |
Finalidade |
| .NET 9 |
net9.0 |
ASP.NET Core Web API |
| C# |
- |
Linguagem |
| Microsoft.AspNetCore.OpenApi |
9.0.12 |
Suporte OpenAPI/Swagger |
| Dapper |
2.1.66 |
Acesso a dados do domínio de flashcards |
| Npgsql |
9.0.4 |
Driver PostgreSQL para persistência de flashcards |
Cronjob (mindforge.cronjob)
| Tecnologia |
Versão |
Finalidade |
| Go |
1.22 |
Linguagem |
| godotenv |
v1.5.1 |
Carregamento de arquivos .env |
Infraestrutura
| Tecnologia |
Finalidade |
| Docker |
Imagens multi-arch (amd64, arm64) |
| Kubernetes |
Orquestracao (Deployments, CronJobs, Services, Ingress) |
| Gitea |
Git hosting + Container registry (git.ivanch.me) |
| Gitea Actions |
CI/CD (build & deploy no push para main) |
| Nginx Ingress |
K8s ingress controller |
| OpenRouter API |
Provedor LLM (endpoint compatível com OpenAI) |
Arquitetura
O projeto é um monorepo com três serviços independentes.
Mindforge.Web: SPA em Preact/Vite com navegação manual por estado e sem react-router.
Mindforge.API: REST API em camadas com Controllers, Services, Repositories, Providers, Middlewares e Models; o domínio de flashcards é persistido em PostgreSQL (mindforge) via Dapper + Npgsql, com schema criado no startup.
mindforge.cronjob: worker em Go executado semanalmente para resumir alterações recentes em arquivos .md.
- Integrações principais: OpenRouter para IA, Gitea como repositório de conteúdo e Discord via webhook para notificações.
- Deploy: cada serviço possui Dockerfile, manifesto Kubernetes e pipeline independente no Gitea Actions.
- Decisões-chave: Git como content store, revisão espaçada calculada em leitura e Preact em vez de React.
Estrutura do Projeto
mindforge/: raiz do projeto com documentação, scripts, logo e workflows do Gitea.
Mindforge.API/: backend .NET 9 com controllers, services, repositories, providers, models e deploy Kubernetes.
Mindforge.Web/: frontend Preact + Vite com componentes de interface, cliente de API e deploy Kubernetes.
mindforge.cronjob/: worker em Go com lógica de IA, Git, erros e mensagens do Discord, além do deploy Kubernetes.
Endpoints da API
Controller de Arquivos (/api/v1/file)
| Método |
Rota |
Descrição |
| POST |
/api/v1/file/check |
Valida a linguagem ou o conteúdo de um arquivo |
Controller de Flashcards (/api/v1/flashcard)
| Método |
Rota |
Descrição |
| POST |
/api/v1/flashcard/generate |
Gera ou substitui bibliotecas de flashcards a partir dos arquivos selecionados |
| GET |
/api/v1/flashcard/libraries |
Lista todas as bibliotecas persistidas |
| GET |
/api/v1/flashcard/libraries/{id} |
Retorna uma biblioteca específica com seus cards |
| POST |
/api/v1/flashcard/review-session |
Inicia uma sessão de revisão com bibliotecas selecionadas |
| POST |
/api/v1/flashcard/review-answer |
Registra se a resposta do card estava correta |
| GET |
/api/v1/flashcard/rag-status |
Retorna o dashboard de revisão espaçada por matéria/submatéria |
Formas de requisição principais:
POST /api/v1/flashcard/generate: { filePaths: string[], amount: 10-30, difficulty: "Easy" | "Hard" }
POST /api/v1/flashcard/review-session: { libraryIds: number[] }
POST /api/v1/flashcard/review-answer: { cardId: number, correct: boolean }
Controller de Repositório (/api/v1/repository)
| Método |
Rota |
Descrição |
| GET |
/api/v1/repository/info |
Nome do repositório |
| GET |
/api/v1/repository/tree |
Árvore de arquivos do repositório |
| GET |
/api/v1/repository/file?path=... |
Conteúdo de um arquivo específico |
Convenções de Desenvolvimento
Frontend (Preact/TypeScript)
- Componentes: Funções nomeadas exportadas com
export function Nome(). Sem export default.
- Props: Interfaces TypeScript definidas no mesmo arquivo do componente.
- Hooks:
useState e useEffect importados de preact/hooks.
- Children: Tipados como
ComponentChildren de preact.
- CSS: Um arquivo
.css por componente, importado diretamente. Sem CSS Modules.
- Estado: Apenas estado local (
useState). Sem store global, sem Context API.
- Roteamento: Alternância de componentes via
display: block/none com o estado activeModule. Não usa react-router.
- API: Chamadas via
MindforgeApiService (objeto singleton com métodos assíncronos usando fetch).
- TypeScript: Modo estrito,
erasableSyntaxOnly, verbatimModuleSyntax, noUnusedLocals, noUnusedParameters.
- Alias:
react e react-dom mapeados para preact/compat/ no tsconfig.
- Layout:
.app usa CSS Grid (grid-template-columns: 288px 1fr) com Sidebar sticky + .main contendo Topbar e área de conteúdo.
Backend (C#/.NET 9)
- Namespaces:
Mindforge.API.Controllers, Mindforge.API.Services, etc.
- Interfaces: Prefixo
I (ex.: IFileService, ILlmApiProvider).
- DI: Todos os serviços registrados como
Scoped em Program.cs. HttpClient obtido via IHttpClientFactory (não injetado diretamente).
- Controllers: Atributo
[Route("api/v1/...")]. Métodos retornam IActionResult.
- Tratamento de erros:
ExceptionHandlingMiddleware captura UserException (400) e exceções genéricas (500).
UI/UX
- Idioma: Todo texto em português brasileiro, com acentuação e grafia corretas nas telas e mensagens.
- Navegação: Os rótulos visíveis da revisão usam "Revisão de Flashcards" e "Revisão espaçada" como nomes canônicos. A marca Mindforge na sidebar navega para a página inicial.
- Revisão de flashcards: "Revisão de Flashcards" e "Revisão espaçada" mantêm seleção/filtros próprios, mas compartilham a mesma sessão visual (
FlashcardStudySession) com título "Sessão de Revisão", flip 3D, atalhos, fila/progresso, carimbo e confete.
- Tema: Claro quente vintage ("mesa de estudo pessoal"). Fundos creme/pergaminho/dourado com textura de papel (grid via
body::before). Vidro translúcido com backdrop-filter em tons quentes.
- Botões: Estilo pill quente com sombras marrons. Variantes
primary (gradiente azul, com brilho hover) e secondary (translúcido pergaminho).
- Tipografia: Inter (UI global), Georgia/Times New Roman (marca e cabeçalhos), Segoe UI/Inter (conteúdo do flashcard).
- Background: Gradiente radial quente (dourado/azul) sobre base
#fff8e6 com overlay de grid de papel 24px.
- Layout: CSS Grid (
grid-template-columns: 288px minmax(0, 1fr)). Sidebar sticky com textura diagonal. Topbar integrada ao fluxo (não fixa).
- Animações: Apenas sob ação do usuário (flip 3D do flashcard, carimbo, saída do cartão, confete canvas). Sem animações infinitas ou spinners.
- Flashcard: Cartão 3D com efeito
rotateY(180deg), frente papel pautado com borda tracejada e verso azulado focado na resposta. No verso, um clique extra revela a pergunta; enquanto essa pergunta auxiliar estiver visível, os botões "Correto" e "Incorreto" ficam bloqueados. O card não exibe status RAG nem metadados de assunto/subassunto/desempenho/última revisão. O carimbo de feedback ("Correto"/"Incorreto") é renderizado no verso visível antes da saída do cartão, e há confete canvas ao acertar.
- Responsivo: Breakpoints em 1120px (sidebar colapsada) e 760px (layout single-column).
Variáveis CSS (definidas em index.css)
Git e Scripts de Build/Deploy
- Branches:
main (produção)
- CI/CD: Gitea Actions dispara no push para
main, faz build com Docker Buildx multi-arch, envia para o Gitea Container Registry e faz o deploy no K8s.
- Build Local:
re-build.ps1 detecta Docker local; se ausente, envia o projeto via SSH para iris.haven e executa docker buildx bake --load remotamente. Se Docker CLI presente, usa DOCKER_HOST para fallback remoto.
- Deploy Local:
re-deploy.ps1 executa o build das imagens e aplica as atualizações no cluster Kubernetes.
- API Dockerfile: mapeia
TARGETARCH=amd64 para x64 (arquitetura esperada pelo .NET).
Configuração e Variáveis de Ambiente
API (Mindforge.API)
| Variável |
Descrição |
OPENAI_API_URL |
URL do endpoint compatível com OpenAI (OpenRouter) |
OPENAI_TOKEN |
Token de autenticação da API |
OPENAI_MODEL |
Modelo LLM a ser usado |
GITEA_REPO_URL |
URL do repositório Gitea |
GITEA_ACCESS_TOKEN |
Token de acesso ao Gitea |
ConnectionStrings:MindforgeDb |
Conexão PostgreSQL usada pelo domínio de flashcards |
Fallback local/padrão para o banco de flashcards:
Host=localhost;Port=3307;Database=mindforge;Username=root;Password=root.
Web (Mindforge.Web)
| Variável |
Descrição |
VITE_API_BASE_URL |
URL base da API (padrão: http://localhost:5123) |
Cronjob
| Variável |
Descrição |
GIT_REPOSITORY |
URL do repositório Git a clonar |
DISCORD_WEBHOOK_URL |
Webhook do Discord para notificações |
OPENAI_API_URL |
URL do endpoint OpenAI |
OPENAI_TOKEN |
Token de autenticação |
HAVEN_NOTIFY_URL |
URL do serviço de reporte de erros |
Repositório base para os arquivos
A base do repositório para os arquivos de estudo (compartilhado pelo Obsidian) é https://git.ivanch.me/ivanch/concurso.
Ele segue o padrão [base]/concurso/[Matéria]/[SubMatéria*]/[Arquivo], onde [base] é a URL do Git, concurso é o nome da pasta dentro do Git base, Matéria é o nome da matéria (ex.: Direito Constitucional), SubMatéria é o nome da submatéria (ex.: Poder Legislativo) - podendo ser opcional e com múltiplas submatérias - e Arquivo é o nome do arquivo (ex.: Câmara dos Deputados.md).
Exemplos:
- [base]/Concursos/Direito Constitucional/Poder Legislativo/Câmara dos Deputados.md
- [base]/Concursos/Direito Constitucional/Poder Legislativo/CPIs.md
- [base]/Concursos/Direito Constitucional/Ciência, Meio Ambiente e Índios.md
- [base]/Concursos/Direito Constitucional/Ciência, Meio Ambiente e Índios.md
- [base]/Concursos/TI/Análise e Engenharia de Dados/Data Lake e Data Warehouse.md
- [base]/Concursos/TI/Rede/VLAN.md
- [base]/Concursos/TI/Rede/E-mail/IMAP e POP3.md