Skip to content

Latest commit

 

History

History
279 lines (207 loc) · 11.7 KB

File metadata and controls

279 lines (207 loc) · 11.7 KB

Contribuindo

Adoraríamos a sua ajuda para tornar o Roadmap DSA ainda melhor! É um projeto gratuito e open source, feito pela comunidade Craft & Code Club, para a comunidade: o código e o conteúdo estão todos aqui, e qualquer pessoa pode ler, estudar, adaptar e propor mudança. Este guia explica como contribuir com o mínimo de atrito.

Ficou com dúvida em qualquer ponto? Chama a gente no Discord, é o jeito mais rápido de destravar.

Código de Conduta

Leia e siga o nosso Código de Conduta.

Como rodar o projeto

Requer Node.js 22+.

npm install
npm run dev      # http://localhost:3000
npm run build    # gera o site estático em ./out (SSG)
npm run serve    # serve o ./out localmente
npm test         # testes de navegação (Playwright)

Stack: Next.js 16 (App Router) + React 19, export estático (output: "export"), conteúdo em MDX. As partes interativas (visualizadores, checkboxes de progresso) são ilhas client; o resto é estático.

Adicionar ou completar um tópico

O conteúdo mora em content/, na raiz do projeto (irmão de src/, que guarda só o código de estrutura). Os nomes dos campos são em inglês; os valores exibidos ficam em português.

Um tópico é uma pasta com dois arquivos, e ele não pertence a lugar nenhum: quem monta sequência são os roadmaps, que o citam pelo slug.

  1. O dado — crie content/topicos/<slug>/index.ts. Campos úteis: youtube (id do vídeo), article (link do artigo no blog), extraVideos (mais vídeos), viz (visualizador). Os problemas e as referências vão no pratica, que é um export à parte no mesmo arquivo.

    import type { Pratica, Topic } from "@/content/tipos";
    
    export const topico: Topic = {
      slug: "kadane", name: "Kadane", group: "Arrays e Strings",
      level: "Médio", status: "soon", youtube: "VIDEO_ID",
      description: "Maior soma contígua, o clássico.",
    };
    
    export const pratica: Pratica = {
      problems: [{ id: "lc-53", name: "Maximum Subarray", number: "53",
                   source: "LeetCode", level: "Médio", url: "https://leetcode.com/…" }],
      references: [{ title: "Kadane's Algorithm", source: "GeeksforGeeks", url: "https://…" }],
    };

    O group é o assunto do tópico, não um endereço. Escreva-o igual ao dos outros tópicos do mesmo assunto: duas grafias viram duas seções em /topicos/, com o mesmo título e a mesma âncora.

    O selo "NOVO" do menu lateral é uma tag manual: isNew: true. Como não tem data, ele não sai sozinho — marque o tópico que você está publicando e tire a marca dos anteriores no mesmo PR.

  2. Os registros — o tópico só existe no site depois de registrado, porque a lista é escrita à mão (o índice é importado por código de cliente, e cliente não tem fs). São dois lugares: o import nomeado + a entrada em MODULOS, em content/topicos/index.ts; e o import da pratica, em content/topicos/pratica.ts. O teste tests/roadmaps.spec.ts compara a pasta com os registros nos dois sentidos e reprova se faltar.

  3. Artigo — para virar status: "ready", crie content/topicos/<slug>/artigo.mdx. Dentro do MDX já dá para usar, sem importar: <Callout>, <Colunas>, <Cartao> e os visualizadores (ver mdx-components.tsx).

    Sempre declare a linguagem na cerca do bloco de código (```python). O destaque de sintaxe é gerado no build (Shiki), não no navegador, e é a cerca que também põe o selo discreto de linguagem no canto do bloco. Cerca sem linguagem fica sem cor e sem selo: é o certo para diagrama em ASCII.

  4. Ligue o artigo — o import do .mdx em content/topicos/artigos.ts, o sumario no index.ts do tópico e status: "ready". O sumario alimenta o índice "Nesta página" e precisa repetir os títulos h2 do artigo no texto exato:

    export const sumario = ["O problema", "A ideia, em uma frase", "Por que funciona"];
  5. Cite num roadmap, se o tópico fizer parte de algum percurso: em content/roadmaps/<slug>.ts, no grupo certo, { topic: "kadane" }. Pode citar em quantos roadmaps quiser — a página é a mesma, o que muda é a ordem em volta. Tópico que ninguém cita continua publicado, em /topicos/<slug>/, e aparece no índice completo.

Os tipos ficam em src/content/tipos.ts: na raiz, content/ é só conteúdo.

Sem travessão: na copy do site, use pontuação simples (vírgula, ponto, dois pontos), nunca o caractere —.

Adicionar um visualizador

Os visualizadores ficam em content/visualizers/. O padrão vive em SlidingWindowVisualizer.tsx e TwoPointersVisualizer.tsx: um gerador puro de passos + a mesma casca de UI (células, código sincronizado, painel de variáveis, controles e o botão Expandir). Para uma técnica nova:

  1. Copie o componente, troque gerarPassos e a constante CODIGO.
  2. Exponha-o em mdx-components.tsx.
  3. Use no .mdx do tópico: <MeuVisualizador />.

A casca — como a peça se adapta à altura da tela, o que fica parado e o que rola no modo expandido, e o que o teclado faz ali dentro — não se escreve à mão: ela vem do hook useVisualizer (src/lib/visualizer.tsx), com VizHeader e VizFooter. O contrato está em content/visualizers/README.md, com o uso, as opções e as armadilhas já medidas. Leia antes de mexer nela.

Idioma do código: identificador em inglês, tela em português. Variáveis, tipos, campos e props em inglês; tudo que o aluno lê em português. Comentário em português quando explicar melhor, e o nome do componente como fizer sentido.

Repare que a fronteira não é o arquivo, é a string: o trecho de código que aparece na tela do visualizador, os rótulos das variáveis e as notas do passo a passo são conteúdo didático em português, mesmo morando dentro do .tsx. Renomear em lote traduz a aula junto — já produziu "O array precisa estar sorted" aqui. O procedimento para conferir isso está no §0 do contrato.

Passos gerais (fork e PR)

  1. Veja se já existe uma issue aberta sobre o assunto.
  2. Abra uma issue para discutir mudanças maiores.
  3. Faça um fork do repositório.
  4. Crie sua branch: git checkout -b feat/minha-melhoria.
  5. Faça commits atômicos (veja Conventional Commits abaixo).
  6. git push origin feat/minha-melhoria.
  7. Abra um Pull Request.

Commits e Pull Requests

  • ✅ FAÇA commits atômicos, para facilitar a revisão.
  • ✅ FAÇA PRs pequenos e focados.
  • ✅ FAÇA commits no padrão Conventional Commits.
  • ❌ EVITE quebrar o build da integração contínua.

Conventional Commits

Usamos Conventional Commits. Um workflow de CI (commitlint) valida as mensagens em cada Pull Request, então vale seguir o padrão desde o primeiro commit.

Formato:

<tipo>(<escopo opcional>): <resumo no imperativo>

<corpo opcional: explica o porquê da mudança, não o como>

<rodapé opcional: BREAKING CHANGE, referência a issue>

Tipos:

Tipo Quando usar
feat recurso novo para quem usa (tópico, visualizador, página)
fix correção de bug
docs só documentação (README, CONTRIBUTING, comentários)
style formatação, sem mudar comportamento (espaços, ponto e vírgula)
refactor muda o código sem corrigir bug nem adicionar recurso
perf melhora de desempenho
test adiciona ou ajusta testes
ci pipelines, GitHub Actions, deploy
build build, dependências, config do bundler
chore manutenção que não se encaixa nas de cima
revert reverte um commit anterior

Escopos sugeridos (a área tocada): roadmap, topics, viz, nav, ui, apoie, home, seo, test, deps, ci. O escopo é opcional; use quando ajuda a localizar a mudança.

Regras:

  • Resumo no imperativo e em minúsculas: "adiciona", não "adicionado" nem "Adiciona".
  • Sem ponto final no resumo. Até ~72 caracteres.
  • Em português (inglês só para os nomes técnicos consagrados, como no resto do site).
  • Um commit, uma mudança. Commits atômicos facilitam a revisão e o revert.
  • Mudança incompatível: use feat!: (o !) ou um rodapé BREAKING CHANGE: <descrição>.

Exemplos:

feat(roadmap): adiciona tópico de Kadane
fix(viz): corrige overflow do painel de código no mobile
refactor(apoie): puxa apoiadores da APOIA.se no build
docs: melhora o guia de contribuição
ci: valida mensagens de commit com commitlint

Para conferir sua última mensagem localmente, sem instalar nada:

npx --yes --package @commitlint/cli --package @commitlint/config-conventional \
  commitlint --from HEAD~1

Testes

  • ✅ FAÇA npm run build passar (o site inteiro precisa compilar).
  • ✅ FAÇA npm test passar (navegação, links e âncoras).
  • ✅ CONSIDERE adicionar um teste quando o PR resolve um bug ou adiciona algo navegável (nav, links, âncoras do índice).
  • ℹ️ A suíte sobe um servidor estático servindo o ./out, na porta 3000 por padrão (PORT muda). Se a porta estiver ocupada (um npm run dev esquecido, outra suíte rodando), o Playwright falha dizendo isso em vez de testar o que está lá — rode com outra: PORT=3101 npm test.

CI e Pull Requests de forks

Por segurança, os pipelines que usam segredos (deploy no Cloudflare Pages) não rodam em PRs vindos de forks. Além disso, o repositório exige aprovação de um admin para rodar os workflows de PRs de colaboradores externos (configuração de Actions do repositório). Um mantenedor vai revisar e liberar a execução.

Licença

O repositório tem duas licenças, e a sua contribuição entra sob a que corresponde ao que você escreveu:

  • Código → MIT. Componentes, hooks, testes, scripts, configuração, e toda a maquinaria dos visualizadores.
  • Conteúdo → CC BY-NC-SA 4.0. Artigos MDX, descrições de tópico, e o material didático que mora dentro dos visualizadores: as notas de passo, o código exibido na tela, os rótulos que explicam.

Ao abrir um PR, você concorda com isso para as duas partes — a maioria dos PRs daqui mexe nas duas ao mesmo tempo, porque um visualizador é as duas coisas no mesmo arquivo.

A fronteira não é por diretório. Ela atravessa arquivos individuais, e está definida com exemplos na seção "Onde passa a fronteira" do LICENSE. A pergunta que decide: se esta linha sumisse, quebraria o programa (código) ou a aula (conteúdo)?

Na prática, é o que garante as duas coisas de uma vez: o código é open source de verdade, e o conteúdo intelectual segue gratuito para quem quer aprender, sem virar produto de ninguém.

Você continua sendo autor do que escreveu. A licença é permissão para o projeto e para quem o usa, não transferência de copyright.