Guia de Contribuição
Obrigado pelo interesse em contribuir para o APAH Assistant! Este guia explica como participar no desenvolvimento do projeto.
Código de Conduta
Ao contribuir, concorda em manter um ambiente respeitoso e inclusivo para todos os participantes.
Pré-requisitos
- Node.js 20+
- pnpm 9+
- Docker
- Git
- VS Code (recomendado)
Setup do Ambiente de Desenvolvimento
1. Fork e Clone
# Fork via GitHub UI, depois:
git clone https://github.com/SEU-USERNAME/apah-assistant.git
cd apah-assistant
2. Configurar Upstream
git remote add upstream https://github.com/Visual-Thinking/apah-assistant.git
3. Instalar Dependências
pnpm install
4. Configurar Ambiente
cp .env.example .env
# Editar .env com as suas configurações
5. Iniciar Base de Dados
docker-compose up -d
pnpm db:migrate
6. Iniciar Desenvolvimento
pnpm dev
Workflow de Contribuição
1. Criar Branch
# Atualizar main
git checkout main
git pull upstream main
# Criar branch de feature
git checkout -b feature/nome-da-feature
Convenção de Nomes de Branches
| Tipo | Formato | Exemplo |
|---|---|---|
| Feature | feature/descricao | feature/chat-history |
| Bug fix | fix/descricao | fix/login-error |
| Docs | docs/descricao | docs/api-reference |
| Refactor | refactor/descricao | refactor/auth-service |
2. Desenvolver
Faça as suas alterações seguindo as guidelines abaixo.
3. Testar
# Verificar tipos
pnpm typecheck
# Verificar linting
pnpm check
4. Commit
git add .
git commit -m "feat: descrição da alteração"
Convenção de Commits
Usamos Conventional Commits:
| Tipo | Descrição |
|---|---|
feat | Nova funcionalidade |
fix | Correção de bug |
docs | Documentação |
style | Formatação (sem alteração de código) |
refactor | Refatoração |
test | Testes |
chore | Manutenção |
Exemplos:
feat: adicionar histórico de chat
fix: corrigir erro de autenticação no login
docs: atualizar guia de instalação
refactor: extrair lógica de embeddings
5. Push
git push origin feature/nome-da-feature
6. Pull Request
- Abra um PR no GitHub
- Preencha o template
- Aguarde review
Guidelines de Código
TypeScript
// ✅ Bom: Tipos explícitos
interface User {
id: string;
name: string;
email: string;
}
function getUser(id: string): Promise<User | null> {
// ...
}
// ❌ Evitar: any
function getUser(id: any): any {
// ...
}
React Components
// ✅ Bom: Componentes funcionais com tipos
interface ButtonProps {
children: React.ReactNode;
onClick: () => void;
variant?: "primary" | "secondary";
}
export function Button({ children, onClick, variant = "primary" }: ButtonProps) {
return (
<button onClick={onClick} className={cn(buttonVariants({ variant }))}>
{children}
</button>
);
}
Imports
// ✅ Organização de imports
// 1. Bibliotecas externas
import { useState } from "react";
import { z } from "zod";
// 2. Imports internos (alias @/)
import { Button } from "@/components/ui/button";
import { api } from "@/lib/trpc/client";
// 3. Imports relativos
import { UserCard } from "./user-card";
Naming
| Tipo | Convenção | Exemplo |
|---|---|---|
| Componentes | PascalCase | UserProfile |
| Funções | camelCase | getUserById |
| Variáveis | camelCase | isLoading |
| Constantes | UPPER_SNAKE | MAX_FILE_SIZE |
| Ficheiros | kebab-case | user-profile.tsx |
| Tipos/Interfaces | PascalCase | UserProfile |
shadcn/ui
Usar componentes do shadcn/ui sempre que possível:
// ✅ Usar shadcn/ui
import { Button } from "@/components/ui/button";
import { Dialog } from "@/components/ui/dialog";
// ❌ Evitar componentes custom quando shadcn tem equivalente
Estrutura de Ficheiros
src/app/[lang]/(app)/feature/
├── page.tsx # Página principal
├── layout.tsx # Layout (se necessário)
├── _components/ # Componentes específicos
│ ├── feature-list.tsx
│ └── feature-form.tsx
├── actions.ts # Server Actions
└── types.ts # Tipos específicos
Documentação
- Documente funções públicas com JSDoc
- Atualize a documentação quando alterar APIs
- Inclua exemplos de uso
/**
* Pesquisa documentos por similaridade semântica.
*
* @param query - Texto de pesquisa
* @param limit - Número máximo de resultados (default: 5)
* @returns Array de documentos ordenados por relevância
*
* @example
* const docs = await searchDocuments("sintomas HAP", 10);
*/
export async function searchDocuments(
query: string,
limit = 5
): Promise<Document[]> {
// ...
}
Review Process
O que procuramos
- ✅ Código limpo e legível
- ✅ Tipos TypeScript corretos
- ✅ Sem erros de linting
- ✅ Segue as convenções do projeto
- ✅ Documentação atualizada
- ✅ Sem breaking changes não anunciados
Responder a Feedback
- Seja receptivo a sugestões
- Explique decisões técnicas quando necessário
- Faça alterações solicitadas ou discuta alternativas
Reportar Issues
Bugs
Inclua:
- Descrição do problema
- Passos para reproduzir
- Comportamento esperado vs atual
- Screenshots (se aplicável)
- Ambiente (OS, browser, versões)
Feature Requests
Inclua:
- Descrição da funcionalidade
- Caso de uso
- Possível implementação (opcional)
Recursos
Contacto
Para questões sobre contribuição:
- Abra uma Issue no GitHub
- Discussões no repositório
Obrigado por contribuir! 🎉