Aller au contenu

Astro : pages et routes

Astro utilise le routage par fichiers : chaque fichier de src/pages/ correspond à une URL.

Fichier URL
src/pages/index.astro /
src/pages/a-propos.astro /a-propos/
src/pages/blog/index.astro /blog/
src/pages/blog/premier-article.md /blog/premier-article/
src/pages/404.astro Page d’erreur (voir plus bas)

Types de fichiers acceptés : .astro, .md (et .mdx avec l’intégration), .html, et des points de terminaison .js/.ts.

En mode statique, Astro doit connaître à l’avance toutes les pages : getStaticPaths les énumère.

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

---
const produits = [
{ slug: 'clavier', nom: 'Clavier', prix: 49 },
{ slug: 'souris', nom: 'Souris', prix: 25 },
];
export function getStaticPaths() {
return produits.map((produit) => ({
params: { slug: produit.slug },
props: { produit },
}));
}
const { produit } = Astro.props;
---
<h1>{produit.nom}</h1>
<p>{produit.prix} €</p>

Génère /produits/clavier/ et /produits/souris/. Un paramètre absent de la liste donne une erreur 404.

src/pages/docs/[...chemin].astro # /docs/a, /docs/a/b/c, et /docs/
---
export function getStaticPaths() {
return [
{ params: { chemin: undefined }, props: { titre: 'Accueil' } },
{ params: { chemin: 'a/b' }, props: { titre: 'A puis B' } },
];
}
---

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

---
import { getCollection } from 'astro:content';
export async function getStaticPaths({ paginate }) {
const articles = await getCollection('blog');
return paginate(articles, { pageSize: 10 });
}
const { page } = Astro.props;
---
<ul>
{page.data.map((a) => (
<li>
<a href={`/blog/${a.id}/`}>{a.data.titre}</a>
</li>
))}
</ul>
{page.url.prev && <a href={page.url.prev}>Précédent</a>}
{page.url.next && <a href={page.url.next}>Suivant</a>}

Pour que /blog/ soit la première page, utiliser src/pages/blog/[...page].astro.

Des liens HTML ordinaires suffisent : <a href="/a-propos/">À propos</a>. Avec trailingSlash: 'always', terminer chaque URL interne par /. Pour le lien actif :

---
const chemin = Astro.url.pathname;
const lien = (href) =>
chemin === href || (chemin.startsWith(href) && href !== '/') ? 'actif' : '';
---
<nav>
<a href="/" class={lien('/')}>
Accueil
</a>
<a href="/blog/" class={lien('/blog/')}>
Blog
</a>
</nav>

src/pages/404.astro est servie pour toute URL inconnue :

---
import Base from '../layouts/Base.astro';
---
<Base titre="Page introuvable">
<h1>Page introuvable</h1>
<p>
<a href="/">Retour à l'accueil</a>
</p>
</Base>

Astro produit dist/404.html. Le serveur web doit la renvoyer avec le code 404 (Caddy : voir Rendu et déploiement).

export default defineConfig({
redirects: {
'/ancien-chemin/': '/nouveau-chemin/',
'/blog/[slug]/': '/articles/[slug]/',
},
});

En statique, Astro génère des pages HTML avec une redirection meta refresh ; pour une vraie redirection 301, la déclarer dans le serveur web.

Un fichier .js ou .ts dans src/pages/ produit un fichier (JSON, texte…) à la compilation :

src/pages/api/projets.json.ts :

import type { APIRoute } from 'astro';
export const GET: APIRoute = () =>
new Response(JSON.stringify([{ nom: 'MD Editor' }, { nom: 'Notes' }]), {
headers: { 'Content-Type': 'application/json' },
});

Produit /api/projets.json. En mode serveur (voir Rendu et déploiement), il répond dynamiquement aux requêtes (GET, POST…).

---
const url = Astro.url; // URL complète
const parametres = Astro.params; // paramètres de route
const recherche = url.searchParams.get('q'); // en mode serveur seulement
---

En mode statique, la chaîne de requête n’existe pas à la compilation : la lire côté navigateur avec un script.

Symptôme Piste
getStaticPaths() function is required Route dynamique en mode statique sans getStaticPaths
404 sur une URL dynamique Valeur absente de la liste renvoyée
Liens qui renvoient une redirection /chemin vers /chemin/ Cohérence de trailingSlash
Astro.url.searchParams vide à la compilation Normal en statique
Deux pages pour la même URL Conflit entre .astro et .md : renommer

Ubuntu 24.04 et 26.04 : différences à connaître

Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »

Aucune.