Next.js rewrites : servir un blog sous /blog (guide complet)
Comment utiliser les rewrites de Next.js pour afficher un blog externe sous votre /blog sans changer d'URL : syntaxe, ordre d'évaluation, pièges SEO et vérifications.

Vous voulez afficher un blog sous monsite.com/blog, mais ce blog est hébergé ailleurs ? Dans une application Next.js, la solution tient en quelques lignes : les rewrites.
Ce guide explique comment elles fonctionnent, comment les écrire pour servir un blog externe sous /blog, et surtout comment éviter les pièges qui cassent le rendu ou le référencement.
Rewrite ou redirection : la différence
Les deux paraissent proches, mais leur effet est opposé.
| Rewrite | Redirection | |
|---|---|---|
| URL affichée dans le navigateur | Ne change pas | Change |
| Ce que voit le visiteur | Le contenu d'une autre adresse, sous votre URL | Une nouvelle page, à une nouvelle URL |
| Usage typique | Servir un blog externe sous /blog, renommer une route en interne | Déplacer une page, migrer un ancien site |
Une rewrite fonctionne comme un proxy : Next.js va chercher le contenu à une autre adresse et le renvoie tel quel, sous l'URL demandée. Pour Google comme pour vos lecteurs, la page vit bien sur monsite.com/blog. C'est exactement ce qu'il faut pour qu'un blog renforce votre domaine (voir Blog en sous-domaine ou en /blog : lequel choisir pour le SEO ?).
La syntaxe de base
Les rewrites se déclarent dans next.config.ts, avec une fonction rewrites() qui renvoie une liste de règles. Chaque règle a une source (l'adresse demandée sur votre site) et une destination (l'adresse dont on affiche le contenu).
// next.config.ts
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
async rewrites() {
return [
{ source: "/a-propos", destination: "/about" },
]
},
}
export default nextConfig
Ici, monsite.com/a-propos affiche le contenu de la page /about, sans que l'URL ne change.
Les motifs de chemin
La source accepte des paramètres, que l'on peut réutiliser dans la destination :
/blog/:slugcorrespond à/blog/mon-article, mais pas à/blog/a/b;/blog/:path*correspond à/blog,/blog/mon-articleet/blog/a/b/c(le*signifie « zéro ou plusieurs segments ») ;/blog/:id(\\d+)ne correspond qu'aux identifiants numériques, grâce à une expression régulière.
{ source: "/blog/:path*", destination: "https://exemple.com/blog/:path*" }
Le paramètre :path* capture tout ce qui suit /blog et le recopie dans la destination.
Servir un blog externe sous /blog
C'est le cas le plus courant : votre site est en Next.js, votre blog est hébergé par un autre service, et vous voulez qu'il s'affiche sous votre domaine. La destination peut tout à fait être une URL externe.
Voici la configuration utilisée par bloglet :
// next.config.ts
import type { NextConfig } from "next"
const nextConfig: NextConfig = {
async rewrites() {
return [
{ source: "/blog", destination: "https://bloglet.app/monsite/blog" },
{ source: "/blog/:path*", destination: "https://bloglet.app/monsite/blog/:path*" },
{ source: "/rss.xml", destination: "https://bloglet.app/monsite/rss.xml" },
{ source: "/blog-sitemap.xml", destination: "https://bloglet.app/monsite/sitemap.xml" },
]
},
}
export default nextConfig
Ligne par ligne :
/blogaffiche la liste des articles./blog/:path*affiche chaque article (/blog/mon-article)./rss.xmlsert le flux RSS sous votre domaine./blog-sitemap.xmlsert le sitemap des articles, pour que Google les découvre.
Techniquement, la règle
/blog/:path*couvre aussi/blog. Garder les deux lignes rend simplement la configuration plus lisible.
Si votre next.config.ts contient déjà une fonction rewrites(), ajoutez ces lignes au tableau existant plutôt que d'en créer une seconde.
Déclarer le sitemap du blog
Pour que Google trouve vos articles rapidement, ajoutez le sitemap du blog à votre fichier robots :
// app/robots.ts
import type { MetadataRoute } from "next"
export default function robots(): MetadataRoute.Robots {
return {
rules: { userAgent: "*", allow: "/" },
sitemap: [
"https://monsite.com/sitemap.xml",
"https://monsite.com/blog-sitemap.xml",
],
}
}
Vous pouvez aussi le déclarer directement dans Google Search Console, rubrique Sitemaps.
L'ordre d'évaluation : le piège numéro un
Quand rewrites() renvoie un simple tableau, Next.js applique les règles après avoir vérifié vos fichiers et vos pages, mais avant les routes dynamiques (documentation Next.js).
Conséquence directe : si votre projet contient déjà une page app/blog/page.tsx, c'est elle qui s'affiche, et votre rewrite vers le blog externe est ignorée. Deux solutions :
- supprimer l'ancienne route
/blogde votre projet (la plus simple) ; - ou placer vos règles dans
beforeFiles, qui passe avant les fichiers et les pages :
async rewrites() {
return {
beforeFiles: [
{ source: "/blog/:path*", destination: "https://bloglet.app/monsite/blog/:path*" },
],
}
}
La fonction peut en effet renvoyer un objet avec trois listes :
beforeFiles: appliquées avant les fichiers et les pages ;afterFiles: appliquées après les pages, avant les routes dynamiques (c'est le comportement du simple tableau) ;fallback: appliquées en dernier, juste avant la page 404. Pratique pour migrer progressivement un ancien site vers Next.js.
Les autres pièges fréquents
trailingSlash: true
Si votre site utilise trailingSlash: true, ajoutez la barre finale dans la source, et dans la destination si le serveur de destination l'attend aussi :
{ source: "/blog/:path*/", destination: "https://exemple.com/blog/:path*/" }
basePath
Avec un basePath (par exemple /app), Next.js préfixe automatiquement la source et la destination. Pour une rewrite externe qui ne doit pas être préfixée, ajoutez basePath: false à la règle.
Les ressources du blog distant
La page renvoyée par la rewrite est affichée sous votre domaine. Si elle charge ses feuilles de style, scripts ou images avec des chemins relatifs, le navigateur les cherchera… sur votre site, où ils n'existent pas. Le blog distant doit donc utiliser des URL absolues pour ses ressources. C'est l'une des raisons de passer par un service prévu pour être servi sous votre domaine plutôt que de proxifier n'importe quel site.
L'URL canonique
C'est le point le plus important pour le SEO. Le même article est accessible à deux adresses : monsite.com/blog/mon-article et l'adresse d'origine chez l'hébergeur. Pour éviter le contenu dupliqué, la page doit déclarer comme URL canonique celle de votre domaine :
<link rel="canonical" href="https://monsite.com/blog/mon-article" />
Vérifiez-le dans le code source de la page. Un blog qui annonce sa propre adresse d'origine comme canonique fera travailler votre contenu pour un autre domaine.
Conditions avancées : has et missing
Une règle peut ne s'appliquer que si un en-tête, un cookie, un paramètre d'URL ou un nom de domaine correspond. Par exemple, pour ne servir le blog que sur votre domaine principal :
{
source: "/blog/:path*",
has: [{ type: "host", value: "monsite.com" }],
destination: "https://bloglet.app/monsite/blog/:path*",
}
missing fonctionne à l'inverse : la règle s'applique si l'élément est absent.
Et avec proxy.ts ?
Depuis Next.js 16, l'ancien fichier middleware.ts s'appelle proxy.ts (documentation). Il permet lui aussi de faire des rewrites, avec du code :
// proxy.ts
import { NextResponse, type NextRequest } from "next/server"
export function proxy(request: NextRequest) {
const { pathname, search } = request.nextUrl
// /blog/mon-article → https://bloglet.app/monsite/blog/mon-article
return NextResponse.rewrite(new URL(`/monsite${pathname}${search}`, "https://bloglet.app"))
}
export const config = {
matcher: ["/blog", "/blog/:path*"],
}
C'est utile quand la règle dépend d'une logique dynamique (langue, test A/B, utilisateur connecté). Pour servir un blog sous /blog, les rewrites de next.config.ts suffisent, et Next.js recommande d'ailleurs de ne recourir au proxy qu'en dernier ressort.
Vérifier que tout fonctionne
Une fois déployé :
- Ouvrez
monsite.com/blog: la liste des articles s'affiche, et l'URL reste celle de votre site. - Vérifiez le statut HTTP dans un terminal :
curl -I https://monsite.com/blog
La réponse doit commencer par HTTP/2 200, et non par une redirection (301, 302, 307 ou 308).
- Affichez le code source d'un article et cherchez
rel="canonical": l'adresse doit être sous votre domaine. - Ouvrez
monsite.com/blog-sitemap.xml: les URL listées doivent, elles aussi, être sous votre domaine. - Testez une URL d'article avec l'outil d'inspection d'URL de Google Search Console.
Et si mon site n'est pas en Next.js ?
Si votre site est hébergé sur Vercel sans Next.js, les mêmes règles peuvent se déclarer dans un fichier vercel.json :
{
"rewrites": [
{ "source": "/blog/:path*", "destination": "https://bloglet.app/monsite/blog/:path*" }
]
}
D'autres hébergeurs (Netlify, Cloudflare, Nginx…) proposent des mécanismes équivalents, avec leur propre syntaxe.
En résumé
- Une rewrite affiche le contenu d'une autre adresse sans changer l'URL : idéal pour servir un blog externe sous
/blog. - La
destinationpeut être une URL externe, et:path*recopie la suite du chemin. - Une page
/blogexistante dans votre projet passe avant les rewrites : supprimez-la ou utilisezbeforeFiles. - Le blog distant doit utiliser des URL absolues pour ses ressources et déclarer votre domaine comme URL canonique.
- Déclarez le sitemap du blog dans
robots.tsou dans Search Console.
Avec bloglet, les quatre lignes de rewrites suffisent : le rendu serveur, les balises SEO, l'URL canonique sous votre domaine, le sitemap et le flux RSS sont déjà gérés. Suivez le guide complet ou créez votre blog gratuitement.
Écrit par Bloglet
Retrouvez tous nos articles sur le blog de Bloglet.
À lire aussi

Tutoriels · 6 min de lecture
Comment ajouter un blog SEO-ready à un site Next.js (guide 2026)

SEO · 7 min de lecture
Pourquoi votre site React ou Next.js est mal indexé (et comment corriger)

6 min de lecture
Blog en sous-domaine ou en /blog : lequel choisir pour le SEO ?