Communitygithub.com

EthanPlusAI/Kit de Conversão de Sites

Ferramenta para rastrear e capturar um site ao vivo, de forma somente leitura e com ritmo controlado, salvando HTML, texto, cabeçalhos, redirecionamentos, links, scripts, mídia, estilos e capturas de tela em múltiplas larguras para converter ou reconstruir o site. Também suporta retomada após bloqueios.

O que é Kit de Conversão de Sites?

O EthanPlusAI/astro-conversion-kit é uma skill especializada em rastrear e capturar sites de produção de forma segura e não intrusiva, projetada principalmente para ser usada durante conversões ou reconstruções. Ela opera seguindo a 'regra de ouro': o site ao vivo é somente leitura e a captura gerada também é somente leitura. A ferramenta coleta uma variedade extensa de informações, incluindo HTML de cada página, texto extraído, cabeçalhos, todos os redirecionamentos com cada salto, links internos e externos, scripts de terceiros, conjunto de mídia (imagens, vídeos, etc.), folhas de estilo, fontes, logotipo, ícones, feeds RSS/Atom, modelos de página e capturas de tela ao vivo em três larguras (390, 768 e 1440 pixels). Ele gerencia automaticamente o ritmo das requisições para evitar bloqueios, aumentando atrasos e reduzindo a concorrência em caso de respostas 429 ou 503, e recuperando-se gradualmente após períodos de respostas bem-sucedidas. A skill suporta vários scripts – como `capture`, `media`, `assets`, `fingerprint` e `templates` – cada um com finalidades e códigos de saída específicos. Ela é particularmente útil para inventariar completamente um site, como etapa preparatória para conversão (ex.: WordPress para Astro) e pode retomar capturas interrompidas por bloqueios usando a flag `--resume` ou o modo `--polite`. O kit também gera um resumo da captura em README.md e opcionalmente realiza auditorias Lighthouse nos templates representativos.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ethanplusai/astro-conversion-kit/tree/HEAD/skills/capture-site

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

capture-site

Salve tudo que o site ao vivo serve, uma vez, para que cada etapa posterior funcione a partir da captura.

A regra de ouro

O site ao vivo é somente leitura, e a captura é somente leitura depois. Os scripts apenas fazem requisições GET e HEAD ritmadas; nunca enviam um formulário, fazem login ou buscam manualmente para preencher uma lacuna. Depois que as notas são escritas, nada em capture/ é editado: é a evidência que cada verificação lê.

Quando usar

Etapa 2 de uma conversão (convert-site a executa), ou sempre que um site ao vivo precisa ser inventariado (um site de staging ou novo é tarefa do launch-audit). Uma captura que saiu com código 3 é retomada, conforme abaixo.

Ritmo

Cada script envia um user agent do Chrome desktop. Os scripts de captura (capture, media, assets, fingerprint) compartilham um limitador por host: por padrão, os inícios de requisição são espaçados em 400 ms com até 4 voos simultâneos (media: 6), para que um host que responde rapidamente seja lido em minutos. As etapas do Chromium (shoot, css-coverage, styles) carregam uma página por vez, com 500 ms de intervalo, e launch-audit e pre-launch mantêm seu próprio ritmo. O limitador se adapta automaticamente:

  • um 429 ou 503 dobra o atraso desse host (até 32 vezes) e reduz para uma requisição por vez; após cada 30 s de respostas limpas, ele recupera um passo (metade do atraso, mais um voo) até voltar aos padrões;
  • uma resposta que leva mais de 5 s reduz pela metade os voos simultâneos nesse host (não novamente enquanto reduzido), e ele se recupera da mesma forma, um voo a mais a cada 30 s de respostas limpas;
  • um 403 ou erro de rede conta para a parada de 3 consecutivos abaixo, como antes.

--polite é o ritmo antigo: uma requisição por vez, com 2500 ms de intervalo (capture, media, assets). Use-o desde o início em hospedagem compartilhada com uma barreira de bot (o /.well-known/sgcaptcha/ do SiteGround, hosts que respondem 429 ou 503 a algumas requisições rápidas), ou quando uma execução parou em bloqueios: retome com --polite. --delay <ms> e --concurrency <n> substituem os padrões ou --polite. Mantenha os padrões ou --polite contra um site ao vivo (--delay 0 é apenas para fixtures locais), e nunca mude --ua para contornar um bloqueio.

  • capture busca até --concurrency URLs da fila adiantadas e as registra na ordem da fila, para que a captura seja igual a um rastreamento um-a-um. Ele tenta cada URL 3 vezes. Uma URL ainda bloqueada após isso (403, 429, 503 ou erro de rede) é registrada com seu status e attempts em inventory.json (uma lista de sitemap ou REST em meta.json discoveryErrors) e o rastreamento continua. Ele para apenas depois que 3 URLs diferentes em sequência esgotaram suas tentativas sem sucesso entre elas, com estado salvo, essas três enfileiradas novamente com novas tentativas. Ele nunca requisita wp-admin, wp-login, xmlrpc.php ou buscas ?s=.
  • media tenta cada arquivo 3 vezes: um 429 ou 503 persistente o interrompe imediatamente; um 403 ou erro de rede é registrado como status desse arquivo, e 3 desses arquivos em sequência (na ordem em que as respostas chegam) o interrompem. Arquivos já sendo baixados quando ele para são deixados terminar. Ele salva media.json a cada 100 arquivos, para que uma execução interrompida retome perto de onde parou.
  • fingerprint não tenta novamente: uma página inicial bloqueada, ou que seja um desafio de bot, resulta em saída 3. assets e shoot recuam e param após 3 respostas bloqueadas consecutivas.

A sequência de comandos

Execute a partir da pasta que conterá capture/ (a raiz do repositório do site). <skill-dir> é o caminho absoluto da pasta desta skill, em uma cópia do kit onde npm install foi executado (os scripts importam seus pacotes). Cada script imprime --help; execute-o em vez de ler o código-fonte. Execute cada etapa como seu próprio comando, nesta ordem:

  1. Fingerprint, então leia a referência da plataforma para o que ele nomeia (tabela abaixo):

    node <skill-dir>/scripts/fingerprint.mjs https://www.example.com
    
  2. Capture. A descoberta são os sitemaps (cada linha Sitemap: em robots.txt, mais o índice padrão da plataforma), as listas REST (WordPress, quando o fingerprint encontra REST; --no-rest pula), o rastreamento de links, e --seed <path> ou --seed-file <file> (um caminho ou URL por linha, comentários #) para caminhos que o rastreamento não alcança (URLs antigas, um .htaccess antigo). Após o rastreamento, caminhos do Wayback que ele não encontrou vão para wayback-unverified.txt (--no-wayback pula; uma listagem que falha é solicitada novamente 10 s depois antes de meta.json wayback registrar failed). Shortlinks ?p= são registrados não verificados e nunca buscados, a menos que você passe --verify-shortlinks. Após o rastreamento, ele solicita um caminho que não pode existir (/<32 hex>/) uma vez, para que a página 404 do próprio site seja salva como pages/404.html (meta.json notFound; um site que responde 200 ou redireciona para lá é registrado sem página), e solicita /favicon.ico e /apple-touch-icon.png uma vez cada, redirecionamentos seguidos (meta.json icons: caminho para { status, file, contentType, bytes }); um que responde 200 é salvo byte a byte como assets/root-favicon.ico ou assets/root-apple-touch-icon.png (uma resposta HTML não é salva e tem uma note; um com mais de 5 MB tem status "too-large"), e assets.mjs o lista em assets/index.json como tipo "root-icon" com seu path, para que a construção o envie para lá. URLs são indexadas com escapes percentuais maiúsculos (%c3%a9 e %C3%A9 são uma URL), para que uma página vinculada com ambas as grafias seja capturada uma vez. Um sitemap que robots.txt nomeia e que responde 404 (ou qualquer não-200) é listado em sitemaps/index.json com seu status e em meta.json discoveryErrors. Um sitemap em outro host (robots.txt nomeando um de um site irmão, ou um índice listando um; www e apex contam como um host) é listado lá como { url, host, skipped: "other host" } e nunca buscado, para que nenhuma de suas URLs entre no rastreamento. Duas URLs de sitemap com o mesmo nome de arquivo nunca se sobrescrevem: a segunda é salva com um sufixo do seu caminho de diretório (page-sitemap-es.xml). --exclude <prefix>[,<prefix>...] deixa partes do host de fora (sub-sites de um WordPress multisite como /president/, ou uma seção que o proprietário mantém): uma URL cujo caminho começa com um nunca é solicitada, seja um sitemap, as listas REST, um link ou um redirecionamento que leve até lá. Um sitemap sob um é listado em sitemaps/index.json como { url, skipped: "excluded" }; um redirecionamento para um é registrado com esse destino, não solicitado; links para um permanecem no HTML salvo e são listados em links.json excluded, não internal; meta.json excluded nomeia os prefixos e a linha de base os carrega. Prefixos e caminhos são comparados em uma forma, então /présidence/, /pr%c3%a9sidence/ e /pr%C3%A9sidence/ são o mesmo prefixo. Uma folha de estilo ou ícone raiz que redireciona para um não é seguido lá (a folha é listada com status "excluded"). --resume os mantém; um prefixo adicionado em --resume remove o que já foi capturado sob ele (suas páginas com seus arquivos pages/ e text/, redirecionamentos dele, feeds e sitemaps sob ele, e folhas de estilo e scripts usados apenas por essas páginas) e imprime o que removeu. media.mjs e assets.mjs também pulam arquivos sob eles.

    node <skill-dir>/scripts/capture.mjs https://www.example.com --out capture
    

    Em seguida, a segunda passada do Wayback, quando wayback-unverified.txt não está vazio: ele solicita cada caminho arquivado uma vez, para que os que ainda redirecionam caiam em capture/redirects.json com origem seed (os redirecionamentos da linha de base os pegam) e o restante seja registrado com seu status em inventory.json. --seed, --seed-file e --include-query todos se aplicam em --resume, e o Wayback Machine não é consultado novamente:

    node <skill-dir>/scripts/capture.mjs https://www.example.com --out capture --resume --seed-file capture/wayback-unverified.txt
    
  3. Media. Lista cada arquivo de mídia em capture/media.json e o salva em .conversion/media-cache/, o diretório de trabalho da conversão, que fica fora do git:

    node <skill-dir>/scripts/media.mjs --capture capture --download .conversion/media-cache
    

    Ele baixa seis arquivos por vez. Por padrão (--sizes referenced) busca os originais e cada tamanho que o site usa: aquele para o qual uma página, folha de estilo, srcset, tag og ou sitemap aponta, ou cujo nome de arquivo aparece em qualquer lugar nas páginas, folhas de estilo ou scripts capturados (data-thumb, data-bg, configurações JSON, scripts de slider). Um tamanho do WordPress que apenas a lista de mídia REST nomeia é listado com downloaded: false, reason: "unreferenced size" e não solicitado. Ele imprime a divisão, ex. 920 originals + referenced sizes (downloaded), 4,520 unreferenced sizes (listed only): repita essa linha para a pessoa. Use --sizes all quando o proprietário disser que e-mails antigos ou outros sites podem linkar para esses tamanhos.

    Hosts que redimensionam por query string (WordPress VIP, Jetpack Photon: photo.jpg?w=1024, ?resize=300,200) servem cada tamanho no mesmo caminho. O original é o caminho simples, então é o que é solicitado e salvo; cada query string vista é listada sob variants (não solicitada; --sizes all as salva como <path>%3F<query> sob uma pasta irmã, .conversion/media-cache-variants/, para que o cache de mídia que é enviado ou copiado para o repo contenha apenas caminhos simples). Quando o caminho simples responde um erro (4xx ou 5xx; um redirecionamento é registrado com sua localização, e um arquivo muito grande é solicitado novamente uma vez que o limite é aumentado), uma variante é salva em seu lugar e a entrada downloadedFrom é a URL de onde veio. Uma query de cache-busting (sem parâmetro w, h, resize, crop, fit, quality, format ou s, ex. ?ver=3) é o mesmo arquivo, então é preferida e nada mais é marcado; caso contrário, a variante mais larga é salva e a entrada também diz resized: true. A execução imprime uma linha por arquivo e uma contagem (2 originals unavailable (resized: true) ...), baseline/media.json mantém ambos os campos, e a verificação de mídia repete a contagem como N resized (original unavailable on live) sem falhar, já que compara com os bytes realmente salvos. Repita essa contagem para a pessoa e liste esses arquivos no plano e runbook como originais que o site ao vivo não serve mais.

  4. Templates. Agrupa as páginas que responderam 200 em capture/templates.json. No WordPress, as páginas agrupam primeiro pela classe body do template (home, page, single-post, archive, classes de template) e uma página cuja marcação é claramente diferente (Jaccard abaixo de 0.5) se separa como page-2; outras plataformas mesclam por marcação com Jaccard 0.6, como template-<n>:

    node <skill-dir>/scripts/templates.mjs --capture capture
    
  5. Assets. Logotipo, favicon, apple-touch-icon, o manifesto web <link rel=manifest> e cada fonte @font-face em capture/assets/, mais o /favicon.ico e /apple-touch-icon.png raiz (root-favicon.*, root-apple-touch-icon.*) quando meta.json icons os registrou com 200:

    node <skill-dir>/scripts/assets.mjs --capture capture
    

    O logotipo é procurado na página inicial dentro do <header> primeiro, depois dentro de qualquer outro elemento cuja classe ou id nomeie um logotipo (.logo, .site-logo, #logo-wrap). Em cada um: um <img> cujo src, alt, class ou id tenha a palavra "logo" (não "logout"), depois um <svg> inline com "logo" em sua class, id, aria-label ou <title> (salvo como logo.svg, url: null em assets/index.json; sua nota diz isso quando apenas <use> um símbolo definido em outro lugar na página, que renderiza vazio por conta própria), depois o primeiro <img> em um link para a página inicial, depois o primeiro <img>. Verifique assets/logo.* visualmente: um avatar de conta ou marca de patrocinador ainda pode vencer em um cabeçalho incomum. O favicon e apple-touch-icon são salvos como servidos a partir de seu href <link>, query string incluída, para que um que aponte para um redimensionamento (?w=32, ?w=180) de um arquivo de uploads difira em bytes da entrada desse arquivo em media.json: mantenha o ícone salvo, não o original.

  6. Capturas de tela ao vivo, uma por template em 390, 768 e 1440, com o shooter de revisão visual:

    node <skill-dir>/../visual-review/scripts/shoot.mjs --base https://www.example.com --routes capture/templates.json --widths 390,768,1440 --out capture/screens/live
    
  7. Lighthouse (opcional). Apenas quando npx --no-install lighthouse --version responder; nunca instale sem ser solicitado; se estiver faltando, diga isso nas notas (um salto, não uma aprovação). Execute mkdir -p capture/lighthouse-live, depois uma execução por representative em templates.json, por vez:

    npx --no-install lighthouse https://www.example.com/ --quiet --chrome-flags="--headless=new" --output json --output html --output-path capture/lighthouse-live/home
    
  8. README. Resume a captura em capture/README.md; sua seção ## Notes abre com linhas geradas, reescritas em cada execução (quantos caminhos do Wayback a segunda passada verificou e o que cada um respondeu: status, destino do redirecionamento; uma listagem do Wayback que falhou ou foi recusada por tamanho; cada URL ainda falhando após suas tentativas). Execute por último, e após qualquer reexecução:

    node <skill-dir>/scripts/readme.mjs --capture capture
    
ScriptSaída
fingerprint0 concluído, 2 uso ou inalcançável, 3 bloqueio ou desafio de bot
capture0 concluído, 2 uso, 3 parou em bloqueios, inalcançável, desafio de bot (tudo retomável), ou nenhuma página respondeu 200
media0 concluído (com arquivos ausentes incluídos), 2 uso, sem captura ou sem página que respondeu 200, 3 parou em bloqueios
assets0 concluído (com arquivos ausentes incluídos), 2 uso ou sem captura, 3 parou em bloqueios
templates0 concluído, 2 uso, sem inventory.json, ou "nenhuma página capturada" (nenhuma respondeu 200)
readme0 concluído, 2 uso ou sem inventory.json
shoot0 todas capturadas, 1 uma rota falhou, 2 uso, 3 parou em bloqueios

Em saída 3

O site está bloqueando requisições ou não pode ser alcançado. Aguarde (minutos, não segundos), então:

  • fingerprint: execute novamente.
  • capture: execute o mesmo comando com --resume. As URLs ainda na fila são repetidas

…

[truncado para tradução]

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

ethanplusai/astro-conversion-kit

Convert a live website (WordPress first; Drupal, Webflow, Squarespace, Wix and static sites too) into a static Astro site with the same URLs, content, head tags, media, redirects and look, proven by parity gates and a pixel-level visual review, ending in one pull request, a noindexed staging deploy and a launch runbook. Use when asked to convert, rebuild, migrate or clone a site to Astro, when handed a site URL with this kit's link, to resume a conversion from .conversion/state.json, or with --apply <id> to apply one suggestion as a proposal.

ethanplusai/astro-conversion-kit

Audit a live or staging website and report what would go wrong at launch — crawl and inventory, indexability, redirects for a domain cutover, links, images, forms, accessibility, performance, analytics, content sanity, and full-page screenshots for a visual pass. Use before or right after a site launch, when asked to QA, audit, or review a website, when a site is moving to a new domain, or when somebody asks whether a site is ready to go live. Read-only: it never submits a form, clicks a control, or edits anything.

ethanplusai/astro-conversion-kit

Freeze a site capture into baseline/ and prove an Astro build matches it — every route, redirect (one hop, through a simulation of the host), SEO head field, visible text, internal link, media file, sitemap entry, feed, form, third-party script and security header — with approved differences in exceptions.json and improvements in proposals.json. Use after a capture to build the baseline, when compiling redirects.csv for Vercel or Cloudflare, before calling any conversion page done, when a gate fails and needs reading, or to check a staging deploy against the baseline.

ethanplusai/astro-conversion-kit

The moment DNS moves and for the thirty days after — verifies the cutover (DNS propagation, certificate, http and www redirects, the noindex, robots and sitemap on the live host, every redirect the audit mapped, forms, analytics, the staging copy, the old host, security headers), diffs production against the pre-launch baseline, and schedules the watch. Use when asked did the launch work, is the site live, what should I check after launch, the domain just switched, or when a site went live in the last month and something looks wrong. It is read-only and exits 0 whatever it finds.

Habilidades Relacionadas