Changer le thème

Créer un blog Astro de zéro : guide complet de la page d'accueil au déploiement en 1 heure

Easton editorial illustration: deployment dock

Un blog technique se charge en 0,8 s, la navigation est fluide. Mon WordPress ? Trois secondes d’écran blanc — envie de fermer l’onglet. J’ai testé Hexo, Hugo, même Gatsby ; à chaque fois un blocage : docs floues, tutos éclatés, un maillon manquant entre install et déploiement. Astro est rapide, agréable à développer, et le parcours complet est plus simple que prévu.

Cet article vous mène de zéro au déploiement en environ 1 h : accueil, listes, tags, RSS. Des étapes concrètes, pas de blabla.

Chapitre 1 : Pourquoi Astro ? (Pas une pub — c’est vraiment bien)

La performance fait-elle vraiment la différence ?

Franchement, j’étais sceptique au début. « ~40 % plus rapide que React », « zéro JavaScript par défaut » — ça sonne marketing, non ? Après migration WordPress → Astro, les chiffres parlent :

  • Premier affichage: de 3,2 s à 0,8 s
  • Score Lighthouse: 100 (WordPress vorher nur 65)
  • Volume JavaScript: de 280 Ko à moins de 20 Ko
0,8 s
Temps de premier affichage
De 3,2 s à 0,8 s
100
Score Lighthouse
WordPress plafonnait à 65
93 %
Réduction du volume JS
De 280 Ko à moins de 20 Ko

Le secret : contenu d’abord, JavaScript à la demande. Astro sort du HTML+CSS pur ; le JS ne charge que là où vous voulez de l’interactivité. L’inverse du « tout charger » à la React.

Même article sur Next.js et Astro : Next.js embarque le runtime (~100 Ko) au premier écran ; Astro, un HTML propre. Pour un blog orienté lecture, l’écart est énorme.

Et l’expérience de développement ?

Mon point fort d’Astro : l’architecture Islands — « JS uniquement là où c’est nécessaire ».

Exemple page article :

  • Corps de l’article → HTML statique (rapide)
  • Commentaires → composant React (interactif)
  • Navigation → composant Vue (oui, on peut mélanger !)

Pas besoin de transformer tout le site en SPA pour une petite fonction. Et vous écrivez en Markdown, sans base ni back-office : VSCode, push GitHub, déploiement auto.

Comparé aux autres frameworks ?

Voici les faits en tableau :

FrameworkCas d’usageCourbePerformanceMaintenance
AstroBlog / docsFaible (HTML suffit)⭐⭐⭐⭐⭐Faible
Next.jsApps complexesMoyenne (React)⭐⭐⭐⭐Moyenne (API)
HexoBlog statique purFaible (peu extensible)⭐⭐⭐Faible
WordPressCMS nécessaireMoyenne⭐⭐Élevée

Mes conseils :

  • Blog ou docs techniques → Astro
  • E-commerce ou app très interactive → Next.js
  • Blog statique minimal → Hexo
  • Équipe non technique qui publie → WordPress

En 2025, Astro dépasse 3 millions de téléchargements npm, ~18 % de parts — ce n’est plus un framework de niche.

Chapitre 2 : Préparation de l’environnement (5 minutes)

Installer Node.js

Astro requiert Node.js v18+. Vérifiez :

node -v
npm -v

Sinon, Node.js en LTS.

Sous Windows : cochez « Add to PATH ». Certains antivirus bloquent npm — redémarrez le terminal après install.

Créer le projet Astro

Plus simple que vous ne le pensez :

npm create astro@latest

Options recommandées :

  1. Nom: z. B. my-blog
  2. Modèle: Blog (Pfeiltasten + Enter)
  3. Dépendances: Yes
  4. TypeScript : Strict ou Strictest (la vérification de types évite bien des bugs)
  5. Git: Yes

~1-2 minutes.

Pourquoi le modèle Blog ? Listes, tags et RSS déjà inclus — j’ai perdu 2 h sur la pagination avec un template vide.

Lancer le serveur de dev

cd my-blog
npm run dev

Local: http://localhost:4321 → ouvrez dans le navigateur.

Pièges fréquents:

  • Port 4321 occupé → server.port dans astro.config.mjs
  • EACCESsudo npm run dev (Mac/Linux)
  • Caractères illisibles → encodage UTF-8 du terminal

Environnement prêt. Voyons la structure.

Chapitre 3 : Structure du projet (chaque dossier expliqué)

Arborescence

Ouvrez my-blog dans VS Code :

my-blog/
├── src/
│   ├── pages/           # Routes — le nom de fichier = URL
│   ├── layouts/         # Layouts (header, footer…)
│   ├── components/      # Composants réutilisables
│   └── content/         # Articles Markdown
├── public/              # Assets statiques
├── astro.config.mjs
└── package.json

Comme un projet frontend classique, avec quelques spécificités Astro.

pages/ : routing par fichiers

Pas de routing séparé :

  • pages/index.astro/
  • pages/about.astro/about
  • pages/blog/index.astro/blog
  • pages/blog/[...slug].astro/blog/xxx

[...slug].astro = route dynamique pour toutes les URLs /blog/.

Plus simple que Next.js — j’ai adoré en migrant.

content/ : vos articles

Exemples dans src/content/blog/ :


---

title: 'Mon premier article'
description: 'Article de test'
pubDate: 'Dec 02 2025'
heroImage: '/blog-placeholder.jpg'
tags: ['Astro', 'Tutoriel']

---

Contenu ici…

Astro expose post.data.title avec validation au build.

layouts/ et components/

Layouts pour header/footer ; modèle Blog : BaseLayout.astro, BlogPost.astro.

Composants Astro, React ou Vue.

public/

Copié tel quel : public/favicon.ico/favicon.ico.

Images, polices, robots.txt.

astro.config.mjs

export default defineConfig({
  site: 'https://votre-domaine.com',
  integrations: [mdx()],
  server: {
    port: 4321
  }
})

Peu de changements au départ.

5 minutes ici vous en font gagner une heure ensuite.

Chapitre 4 : Fonctionnalités principales (le cœur du projet)

4.1 Page d’accueil : derniers articles

Ajustez src/pages/index.astro :


---

import { getCollection } from 'astro:content';
import BaseLayout from '../layouts/BaseLayout.astro';

// Tous les articles, tri par date, 5 derniers
const allPosts = (await getCollection('blog'))
  .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf())
  .slice(0, 5);

---

<BaseLayout>
  <h1>Bienvenue sur mon blog</h1>
  <ul>
    {allPosts.map((post) => (
      <li>
        <a href={`/blog/${post.slug}/`}>{post.data.title}</a>
        <time>{post.data.pubDate.toDateString()}</time>
      </li>
    ))}
  </ul>
</BaseLayout>

Que fait ce code ?

  1. getCollection('blog') charge tous les articles
  2. Tri par pubDate décroissant
  3. slice(0, 5) — les 5 plus récents
  4. Rendu en liste

Piège : tri des dates avec .valueOf(), pas en chaîne.

4.2 Liste avec pagination

src/pages/blog/index.astro :


---

import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';

const allPosts = (await getCollection('blog'))
  .sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());

const pageSize = 10;
const currentPage = 1;
const totalPages = Math.ceil(allPosts.length / pageSize);
const posts = allPosts.slice(0, pageSize);

---

<BaseLayout title="Liste d'articles">
  <h1>Tous les articles</h1>

  <div class="post-list">
    {posts.map((post) => (
      <article>
        <h2><a href={`/blog/${post.slug}/`}>{post.data.title}</a></h2>
        <p>{post.data.description}</p>
        <time>{post.data.pubDate.toLocaleDateString('fr-FR')}</time>
        <div class="tags">
          {post.data.tags?.map(tag => <span>#{tag}</span>)}
        </div>
      </article>
    ))}
  </div>

  {totalPages > 1 && (
    <div class="pagination">
      <span>Page {currentPage} / {totalPages}</span>
    </div>
  )}
</BaseLayout>

Pagination simplifiée — utilisez paginate() pour les gros sites. Moins de 100 articles : une page suffit.

Idées UX:

  • Temps de lecture (mots ÷ 400/min)
  • Extrait (150 caractères + …)
  • Vignette via heroImage

4.3 Page détail

src/pages/blog/[...slug].astro :


---

import { getCollection } from 'astro:content';
import BlogPost from '../../layouts/BlogPost.astro';

// Chemins statiques pour chaque article
export async function getStaticPaths() {
  const posts = await getCollection('blog');
  return posts.map(post => ({
    params: { slug: post.slug },
    props: { post },
  }));
}

const { post } = Astro.props;
const { Content } = await post.render();

---

<BlogPost {...post.data}>
  <Content />
</BlogPost>

Mécanique:

  • getStaticPaths() au build, HTML par article
  • post.render() convertit le Markdown
  • <Content /> = corps de l’article

Points difficiles:

  1. Pas de coloration → Shiki (souvent inclus)
  2. Style Markdown plat@tailwindcss/typography
  3. Chemins imagespublic/, référence /images/xxx.jpg

Table des matières avec remark-toc :

import { defineConfig } from 'astro/config';
import remarkToc from 'remark-toc';

export default defineConfig({
  markdown: {
    remarkPlugins: [remarkToc],
  },
});

4.4 Système de tags

src/pages/tags/[tag].astro:


---

import { getCollection } from 'astro:content';
import BaseLayout from '../../layouts/BaseLayout.astro';

export async function getStaticPaths() {
  const allPosts = await getCollection('blog');

  const allTags = [...new Set(allPosts.flatMap(post => post.data.tags || []))];

  return allTags.map(tag => ({
    params: { tag },
    props: {
      posts: allPosts.filter(post =>
        post.data.tags?.includes(tag)
      ).sort((a, b) =>
        b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
      ),
    },
  }));
}

const { tag } = Astro.params;
const { posts } = Astro.props;

---

<BaseLayout title={`Tag : ${tag}`}>
  <h1>#{tag} — articles ({posts.length})</h1>

  <ul>
    {posts.map((post) => (
      <li>
        <a href={`/blog/${post.slug}/`}>{post.data.title}</a>
      </li>
    ))}
  </ul>
</BaseLayout>

Une page par tag, ex. /tags/astro.

Bonus : nuage de tags sur tags/index.astro.

4.5 Flux RSS

Installez le plugin :

npx astro add rss

src/pages/rss.xml.js:

import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';

export async function GET(context) {
  const posts = await getCollection('blog');

  return rss({
    title: 'Mon blog technique',
    description: 'Expériences frontend et notes d'apprentissage',
    site: context.site,
    items: posts.map((post) => ({
      title: post.data.title,
      pubDate: post.data.pubDate,
      description: post.data.description,
      link: `/blog/${post.slug}/`,
    })),
  });
}

URL : https://votre-domaine.com/rss.xml. Peu d’utilisateurs RSS, mais professionnel pour un blog tech.

Fonctionnalités principales en place. Prochaine étape : SEO.

Chapitre 5 : SEO (pour être trouvé)

Un blog invisible ne sert à rien. Astro : HTML statique, chargement rapide, balises sémantiques — idéal pour le SEO.

Meta tags dans BaseLayout.astro

Dans le <head> :


---

interface Props {
  title: string;
  description?: string;
  image?: string;
}

const { title, description = 'Mon blog technique', image = '/og-image.jpg' } = Astro.props;
const canonicalURL = new URL(Astro.url.pathname, Astro.site);

---

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width" />
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />

  <title>{title} | Mon blog</title>
  <meta name="description" content={description} />
  <link rel="canonical" href={canonicalURL} />

  <!-- Open Graph -->
  <meta property="og:title" content={title} />
  <meta property="og:description" content={description} />
  <meta property="og:image" content={new URL(image, Astro.site)} />
  <meta property="og:url" content={canonicalURL} />

  <!-- Twitter Card -->
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:title" content={title} />
  <meta name="twitter:description" content={description} />
  <meta name="twitter:image" content={new URL(image, Astro.site)} />
</head>

Meta complètes pour un bel aperçu au partage.

Sitemap

Une commande :

npx astro add sitemap

Domaine dans astro.config.mjs :

export default defineConfig({
  site: 'https://votre-domaine.com',
  integrations: [sitemap()],
});

Soumettez https://votre-domaine.com/sitemap-index.xml à Google Search Console.

Performance et SEO

Astro est déjà rapide — quelques leviers en plus :

1. Images

Composant <Image> :


---

import { Image } from 'astro:assets';
import myImage from '../assets/photo.jpg';

---

<Image src={myImage} alt="Description" />

WebP/AVIF, tailles responsives, lazy loading automatiques.

2. Minification CSS/JS

Build prod auto-minifié. Supprimez les dépendances inutiles.

3. Polices

Google Fonts ou polices custom : font-display: swap.

@font-face {
  font-family: 'MyFont';
  src: url('/fonts/myfont.woff2') format('woff2');
  font-display: swap;
}

Lighthouse 95+ est réaliste. Chez moi, seul « Best Practices » baisse un peu à cause de scripts tiers.

Chapitre 6 : Déploiement (plateformes gratuites)

Code prêt — mise en ligne. Deux plateformes gratuites.

Option 1 : Vercel (recommandé débutants)

Support Astro natif, quasi zéro config.

Étape 1 : push GitHub

git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/votre-utilisateur/my-blog.git
git push -u origin main

Étape 2 : importer sur Vercel

  1. vercel.com — connexion GitHub
  2. « New Project »
  3. Choisir le repo my-blog
  4. Astro détecté — laisser les réglages par défaut
  5. « Deploy » — attendre 1-2 min

Étape 3 : accéder au blog

URL xxx.vercel.app — c’est en ligne.

Domaine personnalisé (optionnel)

Ajoutez le domaine dans Vercel, CNAME chez le registrar — instructions dans l’UI.

Remarques:

  • Configurer site dans astro.config.mjs
  • Variables d’environnement dans Vercel, pas dans le code
  • Premier deploy : jusqu’à 5 min

Option 2 : Netlify

Similaire à Vercel, parfois plus stable selon la région.

Étape 1 : GitHub (comme ci-dessus)

Étape 2 : Netlify

  1. netlify.com
  2. « Add new site » → « Import an existing project »
  3. Connecter GitHub, choisir le repo
  4. Build:
    • Build command: npm run build
    • Publish directory: dist
  5. « Deploy »

Étape 3 : tester xxx.netlify.app

Quelle plateforme ?

PlateformeAtoutsInconvénientsPublic
VercelDétection Astro
Edge rapide
Bon CI/CD
Parfois lent selon régionDX maximale
NetlifyAccès stable
Quota généreux
Plugins
Config un peu plus longuePublic EU/global

Conseil : Vercel d’abord, Netlify si accès lent. Push GitHub → build auto.

Magie du déploiement auto

  1. Écrire en Markdown en local
  2. git add .git commit -m "Nouvel article"git push
  3. En ligne en ~2 min

Pas de serveur, pas de build manuel, pas de FTP.

Chapitre 7 : Problèmes fréquents (éviter les pièges)

Pièges réels — les connaître à l’avance fait gagner du temps.

Problème 1 : Tailwind inactif

Symptôme : classes sans effet visuel.

Cause : content dans tailwind.config.mjs ne scanne pas vos fichiers.

Solution:

export default {
  content: [
    './src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Redémarrez le dev server (Ctrl+C, puis npm run dev).

Problème 2 : erreur « Invalid frontmatter »

Symptôme : ok en local, npm run build échoue.

Cause : frontmatter invalide ou champs manquants.

Solution – typische Blog-Anforderungen:


---

title: 'Titre'           # requis
description: 'Description'  # requis
pubDate: 'Dec 02 2025'         # requis, format date
tags: ['Tag1', 'Tag2']         # optionnel

---

Content Collections valide au build.

Problème 3 : 404 en prod, ok en local

Symptôme : pages 404 sur Vercel/Netlify.

Cause : base incorrect ou site absent.

Solution:

export default defineConfig({
  site: 'https://votre-domaine.com',  // requis
  // base: '/blog',  // seulement en sous-répertoire
});

Sans sous-répertoire, ne pas définir base.

Problème 4 : images lentes

Symptôme : images qui ralentissent la page.

Cause : pas d’optimisation ou fichiers trop lourds.

Solution:

  1. Composant Image:

---

import { Image } from 'astro:assets';

---

<Image src="/images/photo.jpg" alt="Description" width={800} height={600} />
  1. Compression : TinyPNG ou Squoosh.app

  2. CDN : Cloudinary, Imgur, etc.

Problème 5 : pas de coloration syntaxique

Symptôme : blocs de code sans couleurs.

Cause : thème ou Shiki non configuré.

Solution:

export default defineConfig({
  markdown: {
    shikiConfig: {
      theme: 'github-dark',  // ou 'dracula', 'nord'
    },
  },
});

Le modèle Blog inclut souvent Shiki — sinon rm -rf node_modules && npm install.

Problème 6 : dev server lent

Symptôme : npm run dev très long.

Cause : trop d’articles ou de plugins.

Solution:

  • Supprimer node_modules et package-lock.json, réinstaller
  • Retirer les intégrations inutiles
  • Mettre à jour Astro (npm install astro@latest)

Astro 5.x démarre bien plus vite — upgrade si vous êtes en 4.x.

Vous ne rencontrerez peut-être jamais la plupart de ces problèmes — gardez ce chapitre sous la main.

Conclusion

Si vous êtes arrivé ici : vous avez un blog Astro complet, performant et prêt pour la prod.

Système complet : accueil, listes, détail, tags, RSS
SEO : meta, sitemap, performance
Déploiement moderne : CI/CD, push = publication
Performance : Lighthouse 95+, premier affichage 0,8 s

Surtout : vous comprenez contenu d’abord, performance d’abord — pas seulement pour les blogs.

Et ensuite ?

Agissez maintenant:

  • 1 h de pratique avec cet article ouvert
  • Publiez un premier vrai article, même test
  • Partagez le lien, collectez des retours

Fonctions avancées (progressivement):

  • Commentaires : Giscus ou Disqus
  • Recherche : Algolia DocSearch ou Pagefind
  • Mode sombre : toggle de thème
  • Analytics : Google Analytics ou Plausible
  • Navigation préc./suiv. : meilleure interconnexion

Ressources:

Communauté:

  • Astro Discord
  • GitHub : « awesome-astro »
  • Présentez votre blog dans le canal Showcase

Pour finir

La technique n’est qu’une étape — écrire régulièrement compte davantage. Astro abaisse la barrière technique ; la continuité vous appartient.

En cas de blocage :

  1. Docs Astro, section Troubleshooting
  2. Rechercher dans les Issues GitHub
  3. Poser la question sur Discord Astro (anglais, canaux multilingues)

Les erreurs sont normales — mon premier blog Astro a pris trois jours. Ensuite, la maintenance est bien plus simple qu’avec WordPress.

Ouvrez votre terminal et lancez-vous ! 💫

Créer un blog Astro de zéro

Parcours complet en 1 h de la préparation au déploiement : page d'accueil, listes, tags, RSS et SEO

⏱️ Estimated time: 1 hr

  1. 1

    Step 1: Préparation de l'environnement et création du projet

    Préparation :
    • Node.js 18+ (vérifiez avec node -v)
    • Sinon, téléchargez sur nodejs.org

    Création :
    • npm create astro@latest my-blog
    • Choisissez le modèle Blog
    • TypeScript : Yes
    • Installer les dépendances : Yes

    Serveur de dev :
    • cd my-blog
    • npm run dev
    • Ouvrez http://localhost:4321
  2. 2

    Step 2: Structure du projet et création des layouts

    Structure :
    • src/pages : pages
    • src/components : composants
    • src/layouts : layouts
    • src/content : articles Markdown

    Layouts :
    • src/layouts/BaseLayout.astro (HTML, nav, footer)
    • src/layouts/BlogLayout.astro (layout article, hérite de BaseLayout)
  3. 3

    Step 3: Page d'accueil et liste d'articles

    Accueil :
    • src/pages/index.astro
    • Derniers articles et catégories

    Liste :
    • Content Collections
    • Lire src/content/posts
    • Tri par date

    Pagination : 10 articles par page si besoin

    Tags :
    • Extraire tags du frontmatter
    • Nuage de tags et pages par tag
  4. 4

    Step 4: Page détail et flux RSS

    Détail :
    • src/pages/posts/[...slug].astro
    • Correspondance slug → Markdown

    Rendu Markdown : surlignage, liens, images

    RSS :
    • @astrojs/rss
    • src/pages/rss.xml.ts
    • Titre, description, date de chaque article
  5. 5

    Step 5: SEO et mise en production

    SEO :
    • meta title, description, og:image
    • sitemap.xml
    • robots.txt

    Performance :
    • composant Image Astro
    • code splitting
    • preload

    Déploiement :
    • Vercel, Netlify ou Cloudflare Pages
    • HTTPS et CDN gratuits

FAQ

Pourquoi choisir Astro ? Quels atouts performance ?
Performance :
• Premier affichage : 3,2 s → 0,8 s
• Lighthouse 100 (WordPress ~65)
• JavaScript : 280 Ko → moins de 20 Ko
• ~40 % plus rapide qu'un framework React

Architecture Islands :
• Contenu d'abord, JS à la demande
• HTML+CSS par défaut
• React et Vue peuvent coexister

Expérience dev : rédiger en Markdown dans VSCode, push GitHub, déploiement auto — sans base de données ni CMS.
Comment créer un blog Astro de zéro ?
Environnement :
• Node.js 18+
• npm create astro@latest my-blog
• Modèle Blog, TypeScript, dépendances
• cd my-blog && npm run dev

Structure : pages, components, layouts, content

Layouts : BaseLayout.astro, BlogLayout.astro

Accueil et listes : Content Collections, tri, pagination, tags

Détail : [...slug].astro

RSS : @astrojs/rss, rss.xml.ts
Comment implémenter les fonctionnalités clés ?
Accueil : index.astro, derniers articles, Content Collections

Liste : tri par date, pagination (10/page), tags

Détail : route dynamique, rendu Markdown

Tags : frontmatter → nuage et pages filtrées

RSS : @astrojs/rss avec titre, description, date
Comment optimiser SEO et performance ?
SEO : meta tags, sitemap, robots.txt

Performance : Image Astro, code splitting, preload

Islands : HTML+CSS par défaut, JS ciblé, ~40 % plus rapide, ~90 % de JS en moins
Comment déployer un blog Astro ?
Vercel : repo GitHub, HTTPS, CDN

Netlify : dist ou Git

Cloudflare Pages : Git auto

npm run build → dist → plateforme choisie
Quelles fonctionnalités avancées ajouter ?
Commentaires : Giscus ou Disqus

Recherche : Algolia DocSearch ou Pagefind

Mode sombre, analytics (GA ou Plausible)

Intégrations Astro simples, impact performance limité

11 min de lecture · Publié le: 2 déc. 2025 · Mis à jour le: 27 juil. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog