Communitygithub.com

0xDarkMatter/claude-mods

Modèles de développement Astro : architecture en îlots, collections de contenu, stratégies de rendu et déploiement. Convient pour : Astro, architecture en îlots, collections de contenu, Astro Cloudflare, transitions de vue, hydratation partielle, AstroJS, SSG, SSR, rendu hybride, adaptateur Astro.

Qu'est-ce que claude-mods ?

Cette compétence est un guide complet pour le framework Astro, conçu pour être utilisé avec des outils tels que Claude Code, Cursor ou Codex. Elle couvre les aspects essentiels du développement avec Astro, y compris l'architecture d'îlots pour l'hydratation partielle des composants, la gestion des collections de contenu avec validation Zod, et le choix entre les stratégies de rendu statique (SSG), serveur (SSR) ou hybride. La compétence fournit des arbres de décision pratiques pour sélectionner la bonne approche de rendu et de déploiement, des configurations prêtes à l'emploi, ainsi que des exemples de code pour les transitions de vue et les adaptateurs Cloudflare, Vercel, Netlify ou Node. Elle inclut également une checklist de sécurité pour la production et traite les pièges courants (comme les erreurs d'hydratation, les variables d'environnement manquantes, ou les problèmes de type).

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/0xDarkMatter/claude-mods/tree/HEAD/skills/astro-ops

Demander à votre IA préférée

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

Documentation

Opérations Astro

Faits vérifiés en date de juillet 2026.

Modèles complets pour le développement avec le framework Astro : architecture en îlots, collections de contenu, stratégies de rendu, transitions de vue et déploiement multi-plateforme.

Arbre de décision pour la stratégie de rendu

Quelle stratégie de rendu ?
│
├─ Le contenu est-il principalement statique (blog, docs, marketing) ?
│  ├─ OUI → Change-t-il moins d'une fois par jour ?
│  │  ├─ OUI → SSG (output: 'static')
│  │  │        TTFB le plus rapide, compatible CDN, coût d'exécution nul
│  │  └─ NON → Hybride (output: 'hybrid')
│  │           Par défaut statique + SSR par route
│  └─ NON → Chaque page a-t-elle besoin de personnalisation ?
│     ├─ OUI → SSR (output: 'server')
│     │        Dynamique par requête, conscient de l'authentification, données en temps réel
│     └─ NON → Hybride (output: 'hybrid')
│              Coquille statique + îlots serveur pour les parties dynamiques
│
├─ L'application a-t-elle besoin d'interactivité en temps réel (tableau de bord, SPA) ?
│  ├─ OUI → Est-ce une SPA complète avec routage côté client ?
│  │  ├─ OUI → Envisager une SPA React/Vue, ou Astro + client:only
│  │  └─ NON → Hybride + architecture en îlots
│  │           Îlots interactifs dans des pages statiques
│  └─ NON → SSG (output: 'static')
│
├─ Problèmes de temps de construction (>10 000 pages) ?
│  ├─ OUI → Hybride avec rendu à la demande
│  │        Prérendu des pages populaires, SSR pour la longue traîne
│  └─ NON → SSG gère bien
│
└─ Besoin d'edge computing (faible latence globalement) ?
   ├─ OUI → SSR + adaptateur Cloudflare/Vercel Edge
   └─ NON → SSR + adaptateur Node ou SSG

Configuration

// astro.config.mjs
import { defineConfig } from 'astro/config';

// SSG (par défaut) - toutes les pages pré-rendues à la construction
export default defineConfig({
  output: 'static',
});

// SSR - toutes les pages rendues sur demande
export default defineConfig({
  output: 'server',
  adapter: cloudflare(), // ou vercel(), netlify(), node()
});

// Hybride - statique par défaut, SSR par page
export default defineConfig({
  output: 'hybrid',
  adapter: cloudflare(),
});
---
// En mode hybride, désactiver le pré-rendu pour des pages spécifiques :
export const prerender = false;
// En mode SSR, activer le pré-rendu :
export const prerender = true;
---

Référence rapide de l'architecture en îlots

DirectiveHydrate QuandJS EnvoyéCas d'utilisation
client:loadImmédiatement au chargement de la pageBundle completInteractivité au-dessus de la ligne de flottaison (navigation, CTA du héros)
client:idleUne fois la page inactive (requestIdleCallback)Bundle completInteractivité en dessous de la ligne de flottaison (formulaire de commentaire, chat)
client:visibleLorsque défilé dans la zone visibleBundle completÉléments en bas de page (widget de pied, carrousel)
client:mediaLorsque la requête média correspondBundle completNavigation mobile uniquement, composants responsifs
client:only="react"Immédiatement, saute complètement le SSRBundle completComposants qui ne peuvent pas utiliser SSR (canvas, WebGL)
(aucune)Jamais - HTML statique uniquementZéro JSContenu statique, cartes, en-têtes
---
import NavBar from '../components/NavBar.tsx';
import CommentForm from '../components/CommentForm.tsx';
import ImageCarousel from '../components/ImageCarousel.svelte';
import MobileMenu from '../components/MobileMenu.vue';
import ThreeScene from '../components/ThreeScene.tsx';
---

<!-- Charge immédiatement - interactivité critique -->
<NavBar client:load />

<!-- Charge une fois la page inactive - non critique -->
<CommentForm client:idle />

<!-- Charge lorsque défilé dans la zone visible - paresseux -->
<ImageCarousel client:visible />

<!-- Charge uniquement sur mobile -->
<MobileMenu client:media="(max-width: 768px)" />

<!-- Uniquement côté client, pas de SSR (WebGL ne peut pas s'exécuter sur serveur) -->
<ThreeScene client:only="react" />

Démarrage rapide des collections de contenu

Définir le schéma

// src/content.config.ts (Astro 5) ou src/content/config.ts (Astro 4)
import { defineCollection, z, reference } from 'astro:content';
import { glob } from 'astro/loaders';

const blog = defineCollection({
  loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }),
  schema: z.object({
    title: z.string(),
    description: z.string().max(160),
    pubDate: z.coerce.date(),
    updatedDate: z.coerce.date().optional(),
    heroImage: z.string().optional(),
    tags: z.array(z.string()).default([]),
    draft: z.boolean().default(false),
    author: reference('authors'), // Référence à une autre collection
  }),
});

const authors = defineCollection({
  loader: glob({ pattern: '**/*.json', base: './src/content/authors' }),
  schema: z.object({
    name: z.string(),
    avatar: z.string(),
    bio: z.string(),
    socials: z.object({
      twitter: z.string().optional(),
      github: z.string().optional(),
    }).optional(),
  }),
});

export const collections = { blog, authors };

Interroger les collections

---
import { getCollection, getEntry } from 'astro:content';

// Obtenir tous les articles de blog non-brouillons, triés par date
const posts = (await getCollection('blog', ({ data }) => !data.draft))
  .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());

// Obtenir une seule entrée
const post = await getEntry('blog', 'my-first-post');

// Résoudre une référence
const author = await getEntry(post.data.author);

// Rendre le contenu
const { Content, headings } = await post.render();
---

<Content />

Collections de contenu vs CMS externe

CritèreCollections de contenuCMS externe (Payload, etc.)
Type de contenuMarkdown/MDX local, docs, blogsModèles de données relationnels
AuteursDéveloppeurs (versionné)Éditeurs (admin UI, authentification multi-utilisateur)
ValidationType-safe via Zod à la constructionSchémas côté CMS + contrats API
Fréquence de mise à jourDéployé avec le siteIndépendant des déploiements
Besoin d'APIAucun (requêtes à la construction)REST/GraphQL pour d'autres consommateurs
Flux de travailPRs Git, révision simpleFlux éditoriaux, brouillons, rôles

Règle générale : commencez avec les Collections de contenu ; optez pour un CMS uniquement lorsque des non-développeurs doivent publier sans déploiement, ou lorsque le contenu est véritablement relationnel.

Référence de la structure du projet

project-root/
├── astro.config.mjs          # Configuration Astro
├── tsconfig.json              # Configuration TypeScript (étend astro/tsconfigs)
├── package.json
├── public/                    # Actifs statiques (copiés tels quels)
│   ├── favicon.svg
│   ├── robots.txt
│   └── og-image.png
├── src/
│   ├── pages/                 # Routage basé sur les fichiers
│   │   ├── index.astro        # → /
│   │   ├── about.astro        # → /about
│   │   ├── blog/
│   │   │   ├── index.astro    # → /blog
│   │   │   └── [slug].astro   # → /blog/:slug (dynamique)
│   │   ├── api/
│   │   │   └── search.ts      # → /api/search (point de terminaison API)
│   │   └── [...slug].astro    # → attrape-tout/404
│   ├── layouts/
│   │   ├── BaseLayout.astro   # Coquille HTML, <head>, styles globaux
│   │   └── BlogPost.astro     # Mise en page d'article de blog
│   ├── components/
│   │   ├── Header.astro       # Composant Astro statique
│   │   ├── Footer.astro
│   │   ├── NavBar.tsx         # Îlot React
│   │   └── Counter.svelte     # Îlot Svelte
│   ├── content/               # Fichiers sources des collections de contenu
│   │   ├── blog/
│   │   │   ├── post-one.md
│   │   │   └── post-two.mdx
│   │   └── authors/
│   │       └── jane.json
│   ├── content.config.ts      # Schémas de collection (Astro 5)
│   ├── middleware.ts           # Middleware requête/réponse
│   ├── styles/
│   │   └── global.css
│   └── lib/                   # Utilitaires partagés
│       ├── utils.ts
│       └── constants.ts
└── .env                       # Variables d'environnement

Référence rapide des transitions de vue

---
// src/layouts/BaseLayout.astro
import { ViewTransitions } from 'astro:transitions';
---

<html>
  <head>
    <ViewTransitions />
  </head>
  <body>
    <slot />
  </body>
</html>

Directives de transition

<!-- Conserver l'élément entre les pages (conserve l'état, évite le re-rendu) -->
<audio transition:persist id="player">
  <source src="/music.mp3" />
</audio>

<!-- Transition nommée pour l'appairage d'animation -->
<img transition:name="hero" src={post.heroImage} />

<!-- Animation personnalisée -->
<div transition:animate="slide">Contenu</div>
<div transition:animate="fade">Contenu</div>
<div transition:animate="none">Pas d'animation</div>

<!-- Persister avec un nom (pour plusieurs éléments persistants) -->
<video transition:persist="media-player" />

Événements du cycle de vie

<script>
  document.addEventListener('astro:before-preparation', (e) => {
    // Avant que la nouvelle page ne soit récupérée - annuler la navigation, afficher le chargement
  });

  document.addEventListener('astro:after-preparation', (e) => {
    // Nouvelle page récupérée, avant l'échange
  });

  document.addEventListener('astro:before-swap', (e) => {
    // Personnaliser le comportement de l'échange DOM
  });

  document.addEventListener('astro:after-swap', () => {
    // DOM mis à jour - réinitialiser les scripts
  });

  document.addEventListener('astro:page-load', () => {
    // Page entièrement chargée (se déclenche au premier chargement et à chaque navigation)
    // Utilisez ceci au lieu de DOMContentLoaded avec View Transitions
  });
</script>

Gestion avant/arrière

// astro.config.mjs
export default defineConfig({
  prefetch: {
    prefetchAll: true,         // Précharger tous les liens au survol
    defaultStrategy: 'hover',  // 'hover' | 'tap' | 'viewport' | 'load'
  },
});
<!-- Contrôle de préchargement par lien -->
<a href="/about" data-astro-prefetch>Précharger au survol (par défaut)</a>
<a href="/blog" data-astro-prefetch="viewport">Précharger lorsqu'il est visible</a>
<a href="/contact" data-astro-prefetch="load">Précharger immédiatement</a>
<a href="/external" data-astro-prefetch="false">Pas de préchargement</a>

Arbre de décision pour le déploiement

Où déployer ?
│
├─ Besoin d'edge computing + écosystème Cloudflare (KV, D1, R2) ?
│  └─ Cloudflare Pages/Workers
│     Adaptateur : @astrojs/cloudflare
│     Idéal pour : Edge global, liaisons Workers, économique
│
├─ Besoin de serverless + écosystème Vercel (ISR, analytics) ?
│  └─ Vercel
│     Adaptateur : @astrojs/vercel
│     Idéal pour : Migration Next.js, optimisation d'images, ISR
│
├─ Besoin de serverless + écosystème Netlify (formulaires, identité) ?
│  └─ Netlify
│     Adaptateur : @astrojs/netlify
│     Idéal pour : JAMstack, formulaires intégrés, tests fractionnés
│
├─ Besoin de contrôle total du serveur (Docker, runtime personnalisé) ?
│  └─ Node.js (autonome ou Express/Fastify)
│     Adaptateur : @astrojs/node
│     Idéal pour : Auto-hébergé, WebSocket, processus longs
│
└─ Site purement statique (pas besoin de SSR) ?
   └─ N'importe quel hébergeur statique (GitHub Pages, S3, Cloudflare Pages)
      Pas d'adaptateur nécessaire, output: 'static'
      Idéal pour : Blogs, docs, sites marketing

Installation des adaptateurs

# Cloudflare
npx astro add cloudflare

# Vercel
npx astro add vercel

# Netlify
npx astro add netlify

# Node.js
npx astro add node

Pièges courants

PiègePourquoiCorrectif
Erreurs d'hydratationHTML serveur différent du rendu client (dates, ID aléatoires, API navigateur)Utiliser client:only pour les composants dépendant du navigateur, ou assurer un rendu déterministe
import.meta.env indéfini côté clientSeules les variables préfixées par PUBLIC_ sont exposées au code côté clientRenommer en PUBLIC_MY_VAR ou passer via les props depuis le serveur
Routes dynamiques 404 en SSGgetStaticPaths() ne retourne pas tous les paramètres possiblesAssurer que getStaticPaths() retourne chaque chemin valide, ou passer en hybride/SSR
Images non optimiséesUtilisation de <img> au lieu du composant <Image /> d'AstroImporter depuis astro:assets : import { Image } from 'astro:assets' et utiliser des imports locaux pour src
SSR échoue sans adaptateuroutput: 'server' ou 'hybrid' nécessite un adaptateur de déploiementInstaller l'adaptateur : npx astro add cloudflare (ou vercel, netlify, node)
Composants MDX non rendusComposants personnalisés non passés au contenu MDXPasser les composants via <Content components={{ MyComponent }} /> ou utiliser la config MDX dans astro.config.mjs
Modifications du schéma de collection non reflétéesLa génération de types est mise en cache, les types .astro sont obsolètesExécuter astro sync pour régénérer les types, redémarrer le serveur de développement
client:* sur les composants AstroLes directives client fonctionnent uniquement sur les composants framework (React, Vue, Svelte)Les composants Astro sont uniquement statiques; extraire les parties interactives vers un composant framework
document / window non définiLe code côté serveur ne peut pas accéder aux globaux du navigateurProtéger avec if (typeof window !== 'undefined') ou déplacer dans client:only
Fuites de styles entre composantsUtilisation de CSS global au lieu de styles scopésUtiliser <style> (scopé par défaut dans .astro) ou <style is:global> intentionnellement
View Transitions interrompt les scriptsDOMContentLoaded ne se déclenche qu'une fois avec View TransitionsUtiliser l'événement astro:page-load, qui se déclenche à chaque navigation
Variables d'environnement manquantes en production.env non chargé ou variables de plateforme non configuréesUtiliser envField dans astro.config.mjs pour la validation; définir les variables dans le tableau de bord de la plateforme

Checklist de sécurité pour la production

Pour chaque déploiement en production, traiter :

  • En-têtes CSP - configurer une Content-Security-Policy restrictive (voir les motifs de middleware dans references/deployment.md)
  • Restrictions d'images distantes - appliquer des listes d'autorisation explicites image.domains / remotePatterns ; ne jamais dériver les URL d'images d'une entrée utilisateur (risque SSRF)
  • Validation de l'en-tête Host - vérifier que l'hôte de la requête correspond aux domaines attendus dans le middleware (SSR/hybride uniquement)
  • Gestion des secrets - sur Cloudflare, utiliser les Workers Bindings (wrangler secret put), pas de variables d'environnement intégrées dans le code ; ailleurs, utiliser les magasins de secrets de la plateforme
  • HTTPS uniquement - assurer que toutes les ressources externes (scripts, images, polices) sont chargées via HTTPS
  • Validation des entrées - nettoyer toute entrée utilisateur dans les contextes SSR (paramètres de requête, corps de formulaire, cookies)

Fichiers de référence

FichierContenuLignes
references/content-collections.mdMotifs de schéma, types Zod, interrogation, MDX, API de couche de contenu, migrations~500
references/islands-rendering.mdMotifs avancés d'îlots, interactive island, island map, API de rendu hybride, optimisation~350
references/view-transitions.mdMotifs de transition, défilement par ancre, router SPA, animations personnalisées, état partagé~300
references/deployment.mdMotifs de middleware, configuration CSP, proxy, multi-région, revalidation, rolling deploys~400
references/testing.mdTests de rendu, tests d'îlots, tests e2e, habillage D1, tests de snapshot~250

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills associés