📁 Plano: Reestruturação — Mover os 40 Cursos para /cursos/

Status: ANÁLISE — nada foi executado ainda. Este documento existe para decidir se e como fazer a mudança antes de tocar em qualquer arquivo.


1. Objetivo da Mudança

Hoje a raiz do repositório tem 40 pastas de curso (mod_01_... a mod_14_..., spec_* ×18, extra_* ×7, proj_aplicacoes_full_stack) misturadas com arquivos de configuração, documentação e as páginas raiz (index.md, indice_geral.md, README.md). A proposta é criar /cursos/ e mover as 40 pastas para dentro dela, deixando a raiz só com infraestrutura do site + páginas de entrada.

Ganho: raiz do repositório muito mais legível ao navegar no GitHub ou num editor. Custo: veja a Seção 5 (trade-off de URLs quebradas).


2. Como o site está montado hoje (o que descobri auditando, não supondo)

Antes de estimar o impacto, confirmei como os links realmente funcionam neste repositório — não são todos do mesmo tipo:

Tipo de link Exemplo real encontrado Quem usa
Entre irmãos dentro de um curso (capítulo→capítulo, capítulo→índice do curso) [Próximo Capítulo](02_x.html) Praticamente todo arquivo de capítulo
Entre cursos diferentes (módulo→próximo módulo, “compare em outra linguagem”) [Próximo Módulo ➡️](../mod_02_logica_e_algoritmos/index.html) escrito dentro de mod_01_.../index.md Rodapés de index.md de cada curso, links “compare em outras linguagens” dos projetos multilíngues
Da raiz do site para dentro de um curso [164 Projetos](proj_aplicacoes_full_stack/projetos_status.html) em README.md; centenas de links assim em index.md e indice_geral.md index.md, indice_geral.md, README.md
De dentro de um curso para a raiz do site [🏠 Início do Portal](../../index.html) Só as páginas index.md de cada curso e de cada subpasta (topicos/index.md, exemplos/index.md etc.) — não os capítulos individuais
_data/navigation.yml (menu lateral) url: /mod_01_fundamentos_da_computacao/index.html Toda entrada do menu, sempre caminho absoluto a partir da raiz do site
_config.yml exclude: - proj_aplicacoes_full_stack/projetos/.../index.html Lista de 7 exclusões de build

O insight que simplifica tudo

Um link entre dois arquivos que vão mover juntos (qualquer coisa dentro de dois cursos, ou dentro do mesmo curso) não precisa mudar em nada — porque ../mod_02_x/index.html escrito dentro de mod_01_x/index.md continua correto depois que os dois passam a morar em cursos/mod_01_x/ e cursos/mod_02_x/: a distância relativa entre os dois é a mesma, só ganharam um prefixo comum novo. Isso cobre a esmagadora maioria dos ~4.595 arquivos do site.

Só existem duas fronteiras reais que quebram:

  1. Um link de dentro de um curso apontando pra fora dele, para um arquivo que não vai mudar de lugar (a home index.html, o indice_geral.html).
  2. Um link de um arquivo que não muda de lugar (raiz) apontando para dentro de um curso.

3. Escopo exato do que precisa mudar (contado, não estimado)

Item Onde Quantidade real Tipo de correção
Links raiz → dentro de curso indice_geral.md ~1.040 links Prefixar com cursos/
Links raiz → dentro de curso index.md 41 links Prefixar com cursos/
Links raiz → dentro de curso README.md 1 link Prefixar com cursos/
Links de dentro de um curso → raiz (../index.html, ../indice_geral.html, ../../index.html etc., rótulo sempre “🏠 … Início do Portal”) */index.md (raiz de cada curso) + */topicos\|exemplos\|exercicios\|quizzes\|slides/index.md 119 arquivos (confirmado: capítulos individuais não têm esse link, só os index.md de seção) Adicionar mais um ../ — a quantidade certa depende da profundidade de cada arquivo, não é uma substituição de texto única
Menu lateral _data/navigation.yml 840 URLs, 100% delas apontam pra dentro de algum dos 40 cursos (confirmado, zero exceção) Substituição global url: /url: /cursos/
Build excludes _config.yml 7 caminhos Prefixar com cursos/
Breadcrumbs _includes/breadcrumbs.html 0 — já é construído dinamicamente a partir de page.url, se adapta sozinho Nenhuma
Assets (imagens/CSS relativos) busquei (../)*assets/ dentro dos cursos 0 ocorrências Nenhuma — assets são referenciados via caminho absoluto com baseurl
Scripts históricos (_scripts/generate_*.py, fix_*.py) vários não contados Baixa prioridade — são scripts de uso pontual já executados, não rodam em CI; só valeria atualizar se algum for reexecutado no futuro

O item genuinamente delicado é o de 119 arquivos — não é substituição de texto simples porque o mesmo padrão ../index.html significa coisas diferentes dependendo de quem escreveu: dentro de topicos/01_x.md (capítulo) ele aponta pro índice do próprio curso (correto, não muda); dentro de topicos/index.md (índice de seção) ele aponta pro site inteiro (precisa de mais um ../). A correção certa não pode ser feita por um único sed cego — precisa ser guiada por qual arquivo contém o link, não só pelo texto do link.

4. Estratégia de execução recomendada

  1. git mv das 40 pastas para cursos/ — um único commit mecânico, sem editar conteúdo ainda. Isso já move corretamente todos os links “entre cursos” e “dentro do mesmo curso” sem precisar tocar neles (ver Seção 2).
  2. Script dedicado e não-genérico para os 119 arquivos de root-link: para cada um, identificar sua profundidade real a partir da nova raiz (cursos/mod_01/index.md = profundidade 2, cursos/mod_01/topicos/index.md = profundidade 3, etc.) e substituir apenas a ocorrência de (../)^N index.html / (../)^N indice_geral.html onde N bate exatamente com essa profundidade — nunca uma substituição cega de string.
  3. Substituição global seguros (sem ambiguidade, podem ser feitos com um replace simples):
    • _data/navigation.yml: url: /url: /cursos/ (840 ocorrências, todas corretas por construção — já confirmei que não há nenhuma URL nesse arquivo fora dos 40 cursos).
    • _config.yml: prefixar as 7 linhas de exclude:.
    • indice_geral.md, index.md, README.md: prefixar cursos/ nos links que apontam pra pastas de curso (usar os 4 prefixos mod_|spec_|extra_|proj_ como âncora do regex, já validados como suficientes nesta auditoria).
  4. Validar exclusivamente via CI (igual ao padrão já usado o resto desta sessão — não há Jekyll local): _scripts/test_links.py já é um crawler real que parte de index.html do build final e segue todo <a href> recursivamente, checando se o arquivo de destino existe — é exatamente a rede de segurança certa pra pegar qualquer link relativo que eu tenha deixado errado, incluindo no menu lateral (que aparece em toda página, logo é alcançado pelo crawler mesmo sem estar em indice_geral.md).
  5. Se o CI apontar quebras, corrigir e re-push — mesmo ciclo iterativo já usado nesta sessão pra outras mudanças grandes.

5. Trade-off que precisa de decisão do usuário: URLs ao vivo vão quebrar

Isso é uma mudança de estrutura de pastas do Jekyll, e o Jekyll espelha a estrutura de pastas na URL final. Hoje uma aula vive em: https://ricardotecpro.github.io/portal_jekyll/mod_01_fundamentos_da_computacao/topicos/01_x.html

Depois da mudança, a mesma aula passa a viver em: https://ricardotecpro.github.io/portal_jekyll/cursos/mod_01_fundamentos_da_computacao/topicos/01_x.html

Toda URL de todo capítulo do site muda. Isso quebra:

Três opções, preciso que você escolha uma:

  1. Aceitar a quebra — mais simples, zero trabalho extra. Faz sentido se o site ainda não tem tráfego externo relevante ou links compartilhados que importem manter.
  2. Adicionar redirects reais via plugin jekyll-redirect-from — como o build já roda num GitHub Actions próprio (não no build padrão limitado do GitHub Pages), não há restrição de plugin aqui, esse plugin funcionaria normalmente. Precisaria gerar uma entrada de redirect por página movida (as ~800 páginas de capítulo + as ~200 de índice de seção) — mais trabalho, mas nenhuma URL antiga quebra de verdade pro usuário final.
  3. Meio-termo: redirects só nas 40 páginas-raiz de curso (as mais prováveis de estar salvas/linkadas externamente), aceitando que URLs de capítulo individual quebram.

6. Estimativa de esforço

Etapa Esforço
git mv das 40 pastas Baixo — mecânico, um comando
Script de correção dos 119 arquivos de root-link Médio — precisa ser escrito com cuidado (profundidade por arquivo), mas é um script pequeno e testável
Substituições globais (navigation.yml, _config.yml, index.md, indice_geral.md, README.md) Baixo — regex simples e bem delimitado
Ciclo de validação via CI (push → checar test_links.py → corrigir se preciso) Médio — 1-3 iterações prováveis, dado o tamanho do site (4.595 arquivos)
Redirects (se a Opção 2 ou 3 da Seção 5 for escolhida) Médio-Alto — trabalho adicional não trivial, mas separável do resto

No geral: escopo bem menor do que a primeira impressão de “mover 40 pastas de um site com 4.595 arquivos” sugere, graças ao insight da Seção 2 — a esmagadora maioria dos links não precisa de nenhuma alteração porque move junto.

7. Perguntas em aberto antes de executar

  1. Qual das 3 opções da Seção 5 (aceitar quebra / redirect completo / redirect só nas 40 raízes)?
  2. Confirma que todas as 40 pastas devem mover (incluindo proj_aplicacoes_full_stack, que tem uma estrutura um pouco diferente com projetos/ aninhado e os excludes do _config.yml)?
  3. Executar tudo em um único PR grande, ou em etapas (ex: git mv + fixes globais primeiro, depois os 119 arquivos de root-link em um PR separado)?

⬅️ Voltar ao Índice de Documentação 🗺️ Ver Roadmap Geral