Mindforge
Visao Geral (Overview)
Mindforge e uma ferramenta de estudo para auxiliar na preparacao para concursos publicos brasileiros. O sistema permite validar e gerar materiais de estudo a partir de arquivos Markdown hospedados em repositorios Git, utilizando IA (OpenRouter/OpenAI-compatible API) para processamento.
A interface e em portugues brasileiro e possui um tema escuro com efeito vidro ("glassy-look").
Tech Stack
Frontend (Mindforge.Web)
| Tecnologia |
Versao |
Finalidade |
| Preact |
^10.29.0 |
UI library (lightweight React alternative) |
| Vite |
^8.0.1 |
Build tool e dev server |
| TypeScript |
~5.9.3 |
Tipagem estatica |
| marked |
^17.0.4 |
Renderizacao 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 |
Versao |
Finalidade |
| .NET 9 |
net9.0 |
ASP.NET Core Web API |
| C# |
- |
Linguagem |
| Microsoft.AspNetCore.OpenApi |
9.0.12 |
Suporte OpenAPI/Swagger |
Cronjob (mindforge.cronjob)
| Tecnologia |
Versao |
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 OpenAI-compatible) |
Arquitetura (Architecture)
O projeto e um monorepo com tres servicos independentes e deployaveis separadamente.
Servicos
1. Mindforge.Web (Frontend)
- Tipo: Single Page Application (SPA)
- Funcao: Interface do usuario para validacao de arquivos e geracao de flashcards
- Modulos: Home, Verificador, Flashcards
- Roteamento: State-based manual via
useState (nao usa react-router). Componentes sao alternados com display: block/none.
- Estado: Apenas
useState/useEffect locais. Sem store global, sem Context API.
2. Mindforge.API (Backend)
- Tipo: REST API
- Padrao arquitetural: Clean layered architecture
- Controllers -> validacao e roteamento HTTP
- Services -> logica de negocio (FileService, FlashcardService, AgentService, GiteaService)
- Providers -> abstracao de APIs externas (OpenAIApiProvider implementa ILlmApiProvider)
- Middlewares -> cross-cutting concerns (ExceptionHandlingMiddleware)
- Models -> DTOs e tipos de request/response
- DI: Todos servicos e providers registrados como Scoped
- CORS: Allow all origins
- Auth: Nenhuma no momento
3. Mindforge.Cronjob (Background Worker)
- Tipo: Kubernetes CronJob
- Schedule: Sabados as 9:00 AM
- Pipeline:
- Clona repositorio Git via SSH
- Encontra arquivos modificados nos ultimos 7 dias (
.md, exceto Conteudos.md)
- Filtra commits de "refactor" via
git log
- Ranqueia por linhas alteradas, seleciona top N (default 10)
- Gera resumo em texto com IA para cada arquivo
- Formata resumo em Markdown
- Envia para Discord via webhook (chunked em 1800 chars)
- Error handling: Reporta ao Haven Notify
Decisoes de Arquitetura (Architecture Decisions)
- Sem banco de dados: Totalmente stateless. Conteudo de estudo vive em repositorios Git, acessados via Gitea API em tempo de request.
- Git como content store: Nao ha upload de arquivos - o conteudo e lido diretamente do repositorio Git.
- IA como engine de processamento: Toda validacao e geracao e delegada ao LLM via OpenRouter.
- Provider abstraction:
ILlmApiProvider permite trocar o backend de IA sem alterar a logica de negocio.
- Monorepo com deploys independentes: Cada servico tem seu proprio Dockerfile, manifesto K8s e pipeline CI.
- Roteamento manual no frontend: Sem lib de router, toggle de visibilidade via estado.
- Preact em vez de React: Bundle size menor.
Estrutura do Projeto (Project Structure)
API Endpoints
File Controller (/api/v1/file)
| Metodo |
Rota |
Descricao |
| POST |
/api/v1/file/check |
Valida linguagem ou conteudo de um arquivo |
Flashcard Controller (/api/v1/flashcard)
| Metodo |
Rota |
Descricao |
| POST |
/api/v1/flashcard/generate |
Gera flashcards em CSV |
Repository Controller (/api/v1/repository)
| Metodo |
Rota |
Descricao |
| GET |
/api/v1/repository/info |
Nome do repositorio |
| GET |
/api/v1/repository/tree |
Arvore de arquivos do repositorio |
| GET |
/api/v1/repository/file?path=... |
Conteudo de um arquivo especifico |
Convencoes de Desenvolvimento (Development Conventions)
Frontend (Preact/TypeScript)
- Componentes: Funcoes nomeadas exportadas com
export function Nome(). Sem export default.
- Props: Interfaces TypeScript definidas no mesmo arquivo do componente.
- Hooks:
useState, 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: Alternancia de componentes via
display: block/none com estado activeModule. Nao usa react-router.
- API: Chamadas via
MindforgeApiService (objeto singleton com metodos estaticos usando fetch).
- TypeScript: Strict mode,
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 servicos registrados como
Scoped em Program.cs.
- Controllers: Atributo
[Route("api/v1/...")]. Metodos retornam IActionResult.
- Tratamento de erros:
ExceptionHandlingMiddleware captura UserException (400) e excecoes genericas (500).
UI/UX
- Idioma: Todo texto em portugues brasileiro.
- Tema: Escuro com efeito vidro (glassy).
backdrop-filter: blur(), fundos rgba semitransparentes.
- Botoes: Estilo iOS-like, modernos. Variantes
primary (com blur) e secondary (transparente).
- Tipografia: Lato (Google Fonts), pesos 300/400/700.
- Background:
#005873 (azul petroleo escuro). Nao muito escuro.
CSS Variables (definidas em index.css)
Git
- Branches:
main (producao)
- CI/CD: Gitea Actions dispara no push para main, build com Docker Buildx multi-arch, push para Gitea Container Registry, deploy no K8s.
Configuracao & Environment Variables
API (Mindforge.API)
| Variavel |
Descricao |
OPENAI_API_URL |
URL do endpoint OpenAI-compatible (OpenRouter) |
OPENAI_TOKEN |
Token de autenticacao da API |
OPENAI_MODEL |
Modelo LLM a ser usado |
GITEA_REPO_URL |
URL do repositorio Gitea |
GITEA_ACCESS_TOKEN |
Token de acesso ao Gitea |
Web (Mindforge.Web)
| Variavel |
Descricao |
VITE_API_BASE_URL |
URL base da API (default: http://localhost:5123) |
Cronjob
| Variavel |
Descricao |
GIT_REPOSITORY |
URL do repo Git a clonar |
DISCORD_WEBHOOK_URL |
Webhook do Discord para notificacoes |
OPENAI_API_URL |
URL do endpoint OpenAI |
OPENAI_TOKEN |
Token de autenticacao |
HAVEN_NOTIFY_URL |
URL do servico 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/Analise e Engenharia de Dados/Data Lake e Data Warehouse.md
- [base]/Concursos/TI/Rede/VLAN.md
- [base]/Concursos/TI/Rede/Email/IMAP e POP3.md
Atualizacao - Flashcards Persistidos (2026-05-30)
Mudancas de Arquitetura
- A API deixa de ser totalmente stateless para o dominio de flashcards.
- Flashcards agora sao persistidos em PostgreSQL (
mindforge) via Dapper + Npgsql.
- O schema e criado de forma idempotente no startup da API.
Tabelas de Flashcard
flashcard_libraries: id, file_path (unico), file_name, subject, difficulty, card_count, created_at, updated_at.
flashcards: id, library_id, front, back, position, created_at.
API de Flashcards (v1)
POST /api/v1/flashcard/generate
Request: { filePaths: string[], amount: 10-30, difficulty: "Easy" | "Hard" }
Comportamento: gera por arquivo selecionado, substitui biblioteca anterior do mesmo file_path e retorna bibliotecas com cards.
GET /api/v1/flashcard/libraries
Lista todas as bibliotecas persistidas, com subject para agrupamento na UI.
GET /api/v1/flashcard/libraries/{id}
Retorna detalhes de uma biblioteca com seus cards.
POST /api/v1/flashcard/review-session
Request: { libraryIds: number[] }
Retorna os cards combinados para sessao de revisao (sem repeticao espaciada nesta fase).
Frontend
- Modulo
Flashcards atualizado para:
- selecionar multiplos arquivos;
- definir quantidade fixa por arquivo (10-30);
- definir dificuldade (
Facil/Dificil);
- gerar e exibir resumo das bibliotecas salvas (sem download CSV).
- Novo modulo
Revisao Flashcards:
- lista bibliotecas agrupadas por materia (
subject);
- permite selecionar multiplas bibliotecas;
- inicia sessao estilo Anki simplificada (frente, revelar verso, anterior/proximo, progresso visual).
Novas Configuracoes
ConnectionStrings:MindforgeDb para conexao PostgreSQL.
- Fallback local/default:
Host=localhost;Port=3307;Database=mindforge;Username=root;Password=root.