# 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 | ```json // Request { "fileContent": "string (conteudo do arquivo)", "fileName": "string", "checkType": "language" | "content" } // Response { "result": "string (resultado da validacao)" } ``` ### 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`) ```css --color-bg: #005873; --color-header: #0f0f0f; --color-sidebar: #013a4c; --color-text-creamy: #f4f5f5; --color-accent: #00b4d8; --color-accent-rgb: 0, 180, 216; --color-accent-hover: #0096c7; --font-main: 'Lato', sans-serif; ``` ### 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