Communitygithub.com

ethanplusai/astro-conversion-kit

Explore un site web en direct, en lecture seule et à un rythme adapté, dans un dossier capture/ qu'une reconstruction vérifie — HTML, texte, balises head, redirections avec chaque saut, liens, scripts tiers, médias, feuilles de style, polices, logo, icônes, flux, modèles et captures d'écran en direct à trois largeurs. À utiliser avant de convertir ou reconstruire un site, lorsqu'on demande d'explorer, capturer, photographier ou inventorier un site, ou lorsqu'une capture s'est arrêtée sur des blocages et doit être reprise.

Qu'est-ce que astro-conversion-kit ?

Ce skill (capture-site) capture l'intégralité d'un site web en direct de manière non destructive : il enregistre chaque page HTML, son texte brut, les balises head, les redirections (chaque étape, pas seulement la finale), les liens, les scripts tiers, les fichiers multimédia, les feuilles de style, les polices, le logo, les icônes, les flux RSS/Atom, les modèles de page et des captures d'écran en direct à 390, 768 et 1440 pixels de large pour chaque modèle identifié. Il est conçu pour être utilisé avant la conversion d'un site (par exemple, vers Astro ou un autre générateur statique) ou pour inventorier un site en production. Le skill est réservé à la lecture : il n'envoie que des requêtes GET et HEAD, ralenties et limitées en concurrence pour éviter de surcharger le serveur cible. Il gère intelligemment les blocages (429, 503, 403, erreurs réseau) en doublant progressivement les délais et en réduisant la concurrence, puis en revenant à la normale après 30 secondes de réponses propres. Les sorties sont sauvegardées dans un dossier `capture/` avec une structure claire : `pages/` pour le HTML, `text/` pour le texte brut, `media.json` pour l'inventaire des médias, `assets/` pour les icônes, polices et logo, `templates.json` pour les modèles de page, etc. Un mécanisme de reprise (option `--resume`) permet de reprendre une capture interrompue par des blocages. En sortie, un README.md résume la capture et liste les éventuelles erreurs. Le skill est conçu pour être exécuté script par script dans un ordre précis : fingerprint, capture, récupération Wayback, médias, templates, assets, captures d'écran, et éventuellement Lighthouse.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

capture-site

Enregistrez tout ce que le site en direct sert, une fois, pour que chaque étape ultérieure fonctionne à partir de la capture.

La règle d'or

Le site en direct est en lecture seule et la capture est en lecture seule par la suite. Les scripts effectuent uniquement des requêtes GET et HEAD espacées ; ne soumettez jamais de formulaire, ne vous connectez pas et ne récupérez rien manuellement pour combler une lacune. Une fois les notes écrites, rien sous capture/ n'est modifié : c'est la preuve que chaque porte lit.

Quand l'utiliser

Étape 2 d'une conversion (convert-site l'exécute), ou à tout moment où un site en direct doit être inventorié (un site de staging ou nouveau est le travail de launch-audit). Une capture qui s'est terminée avec le code 3 reprend comme ci-dessous.

Rythme

Chaque script envoie un agent utilisateur Chrome de bureau. Les scripts de capture (capture, media, assets, fingerprint) partagent un limiteur par hôte : par défaut, les démarrages de requêtes sont espacés de 400 ms avec jusqu'à 4 en vol (media : 6), donc un hôte qui répond rapidement est lu en quelques minutes. Les étapes Chromium (shoot, css-coverage, styles) chargent une page à la fois, espacées de 500 ms, et launch-audit et pre-launch conservent leur propre rythme. Le limiteur s'adapte tout seul :

  • un 429 ou 503 double le délai de cet hôte (jusqu'à 32 fois) et le réduit à une requête à la fois ; après 30 s de réponses propres, il récupère un cran (la moitié du délai, un de plus en vol) jusqu'à revenir aux valeurs par défaut ;
  • une réponse qui prend plus de 5 s réduit de moitié les requêtes en vol sur cet hôte (pas de nouveau tant qu'elles sont réduites), et il récupère de la même manière, une de plus en vol par 30 s de réponses propres ;
  • un 403 ou une erreur réseau compte pour l'arrêt de 3 consécutifs ci-dessous, comme avant.

--polite est l'ancien rythme : une requête à la fois, espacées de 2500 ms (capture, media, assets). Utilisez-le dès le départ sur un hébergement partagé avec un mur anti-bot (le /.well-known/sgcaptcha/ de SiteGround, les hôtes qui répondent 429 ou 503 à quelques requêtes rapides), ou lorsqu'une exécution s'est arrêtée sur des blocages : reprenez avec --polite. --delay <ms> et --concurrency <n> remplacent les valeurs par défaut ou --polite. Gardez les valeurs par défaut ou --polite contre un site en direct (--delay 0 est réservé aux fixtures locales), et ne changez jamais --ua pour contourner un blocage.

  • capture récupère jusqu'à --concurrency URL mises en file d'attente à l'avance et les enregistre dans l'ordre de la file, de sorte que la capture est identique à une exploration une par une. Il essaie chaque URL 3 fois. Une URL toujours bloquée après cela (403, 429, 503 ou une erreur réseau) est enregistrée avec son statut et attempts dans inventory.json (une liste de sitemap ou REST dans meta.json discoveryErrors) et l'exploration continue. Il s'arrête seulement après que 3 URL différentes d'affilée aient épuisé leurs tentatives sans succès entre elles, l'état sauvegardé, ces trois remises en file avec de nouvelles tentatives. Il ne demande jamais wp-admin, wp-login, xmlrpc.php ou les recherches ?s=.

  • media essaie chaque fichier 3 fois : un 429 ou 503 persistant l'arrête immédiatement ; une erreur 403 ou réseau est enregistrée comme statut de ce fichier, et 3 fichiers consécutifs (dans l'ordre d'arrivée des réponses) l'arrêtent. Les fichiers en cours de téléchargement lorsqu'il s'arrête sont laissés se terminer. Il sauvegarde media.json tous les 100 fichiers, de sorte qu'une exécution interrompue reprend près de là où elle était.

  • fingerprint ne réessaie pas : une page d'accueil bloquée, ou qui est un défi bot, provoque la sortie de code 3. assets et shoot reculent et s'arrêtent après 3 réponses bloquées consécutives.

La séquence de commandes

Exécuter depuis le dossier qui contiendra capture/ (la racine du dépôt du site). <skill-dir> est le chemin absolu du dossier de ce skill, dans une copie du kit où npm install a été exécuté (les scripts importent ses paquets). Chaque script affiche --help ; exécutez-le plutôt que de lire la source. Exécutez chaque étape comme sa propre commande, dans cet ordre :

  1. Fingerprint, puis lisez la référence de la plateforme pour ce qu'il nomme (tableau ci-dessous) :

    node <skill-dir>/scripts/fingerprint.mjs https://www.example.com
    
  2. Capture. La découverte comprend les sitemaps (chaque ligne Sitemap: dans robots.txt, plus l'index par défaut de la plateforme), les listes REST (WordPress, lorsque l'empreinte trouve REST ; --no-rest saute), l'exploration des liens, et --seed <path> ou --seed-file <file> (un chemin ou URL par ligne, commentaires #) pour les chemins que l'exploration ne peut pas atteindre (anciennes URL, ancien .htaccess). Après l'exploration, les chemins Wayback introuvables vont dans wayback-unverified.txt (--no-wayback saute ; une liste qui échoue est demandée une fois de plus 10 s plus tard avant que meta.json wayback n'enregistre failed). Les shortlinks ?p= sont enregistrés non vérifiés et jamais récupérés à moins de passer --verify-shortlinks. Après l'exploration, il demande une fois un chemin qui ne peut pas exister (/<32 hex>/), de sorte que la page 404 du site est enregistrée comme pages/404.html (meta.json notFound ; un site qui répond 200 ou redirige y est enregistré sans page), et demande /favicon.ico et /apple-touch-icon.png une fois chacun, les redirections suivies (meta.json icons : chemin vers { status, file, contentType, bytes } ; une réponse 200 est enregistrée octet par octet comme assets/root-favicon.ico ou assets/root-apple-touch-icon.png (une réponse HTML n'est pas enregistrée et a une note ; un fichier de plus de 5 Mo a le statut "too-large"), et assets.mjs le liste dans assets/index.json comme type "root-icon" avec son path , pour que la construction l'y envoie. Les URL sont indexées avec des échappements de pourcentage en majuscules (%c3%a9 et %C3%A9 sont une seule URL), de sorte qu'une page liée avec les deux orthographes est capturée une fois. Un sitemap nommé par robots.txt qui répond 404 (ou tout non-200) est listé dans sitemaps/index.json avec son statut et dans meta.json discoveryErrors. Un sitemap sur un autre hôte (robots.txt nommant celui d'un site sœur, ou un index en listant un ; www et apex comptent comme un seul hôte) y est listé comme { url, host, skipped : "other host" } et jamais récupéré, de sorte qu'aucune de ses URL n'entre dans l'exploration. Deux URL de sitemap avec le même nom de fichier ne se remplacent jamais l'une l'autre : la seconde est enregistrée avec un suffixe de son chemin de répertoire (page-sitemap-es.xml). --exclude <prefix>[,<prefix>...] laisse de côté des parties de l'hôte (les sous-sites d'un WordPress multisite comme /president/, ou une section que le propriétaire conserve) : une URL dont le chemin commence par l'un d'eux n'est jamais demandée, qu'un sitemap, les listes REST, un lien ou une redirection y mène. Un sitemap sous l'un d'eux est listé dans sitemaps/index.json comme { url, skipped : "excluded" } ; une redirection vers l'un d'eux est enregistrée avec cette cible, non demandée ; les liens vers l'un d'eux restent dans le HTML sauvegardé et sont listés dans links.json excluded, pas internal ; meta.json excluded nomme les préfixes et la base de référence les porte. Les préfixes et chemins sont comparés sous une seule forme, donc /présidence/, /pr%c3%a9sidence/ et /pr%C3%A9sidence/ sont le même préfixe. Une feuille de style ou icône racine qui redirige sous l'un d'eux n'est pas suivie là (la feuille est listée avec le statut "excluded"). --resume les conserve ; un préfixe ajouté sur --resume supprime ce qui a déjà été capturé en dessous (ses pages avec leurs fichiers pages/ et text/ , les redirections qui en proviennent, les flux et sitemaps en dessous, et les feuilles de style et scripts que seules ces pages utilisaient) et affiche ce qui a été supprimé. media.mjs et assets.mjs ignorent également les fichiers en dessous.

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

    Puis le second passage Wayback, lorsque wayback-unverified.txt n'est pas vide : il demande chaque chemin archivé une fois, de sorte que ceux qui redirigent encore atterrissent dans capture/redirects.json avec la source seed (les redirections de la base de référence les récupèrent) et le reste sont enregistrés avec leur statut dans inventory.json. --seed, --seed-file et --include-query s'appliquent tous sur --resume, et la Wayback Machine n'est pas sollicitée à nouveau :

    node <skill-dir>/scripts/capture.mjs https://www.example.com --out capture --resume --seed-file capture/wayback-unverified.txt
    
  3. Médias. Liste chaque fichier média dans capture/media.json et le sauvegarde sous .conversion/media-cache/, le répertoire de travail de la conversion, qui reste hors de git :

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

    Il télécharge six fichiers à la fois. Par défaut (--sizes referenced), il récupère les originaux et toutes les tailles que le site utilise : celles vers lesquelles pointent une page, une feuille de style, un srcset, une balise og ou un sitemap, ou dont le nom de fichier apparaît n'importe où dans les pages, feuilles de style ou scripts capturés (data-thumb, data-bg, paramètres JSON, scripts de slider). Une taille WordPress que seule la liste média REST nomme est listée avec downloaded : false, reason : "unreferenced size" et n'est pas demandée. Il affiche la répartition, par ex. 920 originals + referenced sizes (downloaded), 4,520 unreferenced sizes (listed only) : répétez cette ligne à la personne. Utilisez --sizes all lorsque le propriétaire dit que d'anciens e-mails ou d'autres sites peuvent lier à ces tailles.

    Les hôtes qui redimensionnent par chaîne de requête (WordPress VIP, Jetpack Photon : photo.jpg?w=1024, ?resize=300,200) servent toutes les tailles au même chemin. L'original est le chemin nu, donc c'est ce qui est demandé et sauvegardé ; chaque chaîne de requête vue est listée sous variants (non demandée ; --sizes all les sauvegarde sous forme de <path>%3F<query> dans un dossier frère, .conversion/media-cache-variants/, de sorte que le cache média qui est téléchargé ou copié dans le dépôt ne contient que les chemins nus). Lorsque le chemin nu répond par une erreur (4xx ou 5xx ; une redirection est enregistrée avec son emplacement, et un fichier trop volumineux est redemandé une fois le plafond relevé), une variante est sauvegardée à sa place et l'entrée downloadedFrom est l'URL d'où elle provient. Une requête de vidage de cache (sans paramètre w, h, resize, crop, fit, quality, format ou s, par exemple ?ver=3) est le même fichier, donc elle est préférée et rien d'autre n'est marqué ; sinon, la variante la plus large est sauvegardée et l'entrée indique également resized : true. L'exécution affiche une ligne par fichier et un décompte (2 originals unavailable (resized : true) ...), baseline/media.json conserve les deux champs, et la porte média répète le décompte comme N resized (original unavailable on live) sans échouer, puisqu'elle compare les octets réellement sauvegardés. Répétez ce décompte à la personne et listez ces fichiers dans le plan et le runbook comme des originaux que le site en direct ne sert plus.

  4. Modèles. Regroupe les pages qui ont répondu 200 dans capture/templates.json. Sur WordPress, les pages se regroupent d'abord par classe de corps de modèle (home, page, single-post, archive, classes de modèle) et une page dont le balisage est clairement différent (Jaccard inférieur à 0,5) se sépare en page-2 ; les autres plates-formes fusionnent par balisage à Jaccard 0,6, en tant que template-<n> :

    node <skill-dir>/scripts/templates.mjs --capture capture
    
  5. Actifs. Logo, favicon, apple-touch-icon, le manifeste web <link rel=manifest> et chaque police @font-face dans capture/assets/, plus le /favicon.ico racine et /apple-touch-icon.png (root-favicon.*, root-apple-touch-icon.*) lorsque meta.json icons les a enregistrés à 200 :

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

    Le logo est recherché sur la page d'accueil à l'intérieur du <header> d'abord, puis à l'intérieur de tout autre élément dont la classe ou l'id nomme un logo (.logo, .site-logo, #logo-wrap). Dans chacun : une <img> dont le src, alt, class ou id contient le mot "logo" (pas "logout"), puis un <svg> en ligne avec "logo" dans sa class, id , aria-label ou <title> (sauvegardé sous logo.svg, url : null dans assets/index.json ; sa note l'indique lorsqu'il <use> uniquement un symbole défini ailleurs sur la page, qui s'affiche vide tout seul), puis la première <img> dans un lien vers la page d'accueil, puis la première <img>. Vérifiez assets/logo.* à l'œil : un avatar de compte ou une marque de sponsor peut encore gagner sur un en-tête inhabituel. Le favicon et l'apple-touch-icon sont sauvegardés tels que servis depuis leur href <link>, chaîne de requête incluse, de sorte que celui qui pointe vers un redimensionnement (?w=32, ?w=180) d'un fichier téléchargé diffère en octets de l'entrée de ce fichier dans media.json : conservez l'icône sauvegardée, pas l'original.

  6. Captures d'écran en direct, une par modèle à 390, 768 et 1440, avec le tireur de révision visuelle :

    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 (optionnel). Seulement lorsque npx --no-install lighthouse --version répond ; ne l'installez jamais sans demande ; s'il manque, dites-le dans les notes (un saut, pas un succès). Exécutez mkdir -p capture/lighthouse-live, puis une exécution par representative dans templates.json, à tour de rôle :

    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. Résume la capture dans capture/README.md ; son ## Notes s'ouvre avec des lignes générées, réécrites à chaque exécution (combien de chemins Wayback le second passage a vérifiés et ce que chacun a répondu : statut, cible de redirection ; une liste Wayback qui a échoué ou a été refusée pour taille ; chaque URL qui échoue toujours après ses tentatives). Exécutez-le en dernier, et après toute réexécution :

    node <skill-dir>/scripts/readme.mjs --capture capture
    
ScriptSortie
fingerprint0 terminé, 2 utilisation ou inaccessible, 3 blocage ou défi bot
capture0 terminé, 2 utilisation, 3 arrêté sur blocages, inaccessible, défi bot (tout reprenable), ou aucune page n'a répondu 200
media0 terminé (fichiers manquants inclus), 2 utilisation, pas de capture ou aucune page ayant répondu 200, 3 arrêté sur blocages
assets0 terminé (fichiers manquants inclus), 2 utilisation ou pas de capture, 3 arrêté sur blocages
templates0 terminé, 2 utilisation, pas de inventory.json, ou "aucune page capturée" (aucune n'a répondu 200)
readme0 terminé, 2 utilisation ou pas de inventory.json
shoot0 toutes prises, 1 une route a échoué, 2 utilisation, 3 arrêté sur blocages

Sur sortie 3

Le site bloque les requêtes ou est inaccessible. Attendez (minutes, pas secondes), puis :

  • fingerprint : exécutez-le à nouveau.
  • capture : exécutez la même commande avec --resume. Les URL encore en file d'attente sont réessayées.

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.

Skills associés