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 escuro com efeito vidro ("glassy-look").
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) |
| Google Fonts (Lato) |
300/400/700 |
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 estáticos usando fetch).
- TypeScript: Modo estrito,
erasableSyntaxOnly, verbatimModuleSyntax, noUnusedLocals, noUnusedParameters.
- Alias:
react e react-dom mapeados para preact/compat/ no tsconfig.
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.
- 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.
- Tema: Escuro com efeito vidro (glassy).
backdrop-filter: blur(), fundos rgba semitransparentes.
- Botões: Estilo iOS-like, modernos. Variantes
primary (com blur) e secondary (transparente).
- Tipografia: Lato (Google Fonts), pesos 300/400/700.
- Background:
#005873 (azul petróleo escuro). Não muito escuro.
Variáveis CSS (definidas em index.css)
Git
- 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.
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