Kamaankamaan

API de blog : récupérer et afficher du contenu CMS headless

Une API de blog portable renvoie du REST JSON brut, alors Next.js, Nuxt, SvelteKit, Astro et React tirent tous du même endpoint sans SDK propre à un fournisseur. Cet article montre la forme de réponse et le code de fetch

Junaid Khalid
Junaid Khalid
29 mai 2026 · 12 min read

API de blog : comment récupérer et afficher du contenu d'un CMS headless dans n'importe quel framework

Chaque framework a son propre tutoriel de SDK CMS. La doc Next.js vous montre Contentful. La doc Nuxt vous montre Sanity. La doc SvelteKit vous montre Storyblok. La doc Astro vous montre Strapi. Aucune ne vous montre ce que vous voulez vraiment : un endpoint, une forme JSON, cinq frontends qui le consomment sans aucun SDK propre à un fournisseur. Le résultat, ce sont des équipes qui choisissent un CMS, restent prisonnières de sa bibliothèque client, puis re-plateforment à chaque changement de framework. Une API de blog qui renvoie du REST JSON brut casse ce schéma. Cet article parcourt un tel endpoint, la forme qu'il renvoie, et le code de fetch exact pour Next.js, Nuxt, SvelteKit, Astro et React pur.

Points clés rapides

  • Une API de blog est juste un endpoint REST qui renvoie des articles en JSON. Aucun SDK requis.
  • Le même endpoint peut alimenter Next.js, Nuxt, SvelteKit, Astro et React avec moins de 15 lignes de fetch par framework.
  • Une forme de réponse propre inclut id, title, slug, content (markdown ou HTML), excerpt, featured_image_url, language et parent_article_id pour les traductions.
  • Kamaan est le centre de commande pour les fondateurs multi-produits et les agences qui gèrent de nombreux blogs SaaS : pilotez chaque blog depuis un seul tableau de bord, et menez chaque opération sur tous depuis Claude, ChatGPT, Cursor ou n'importe quel client MCP.
  • Le câblage initial prend 40 à 60 minutes à un développeur. Les blogs suivants réutilisent le même schéma de fetch.

Pourquoi une API de blog portable compte plus qu'un nouveau SDK

Le travail d'un CMS, c'est de stocker du contenu et de le restituer. Les SDK ajoutent une enveloppe autour de ce travail. Les enveloppes paraissent utiles au départ, puis deviennent une friction. Vous mettez à jour le framework, le SDK casse. Vous changez de framework, le SDK n'existe pas. Vous lancez un second produit, vous payez par space et par siège pour un SDK autour duquel vous avez déjà écrit du code de liaison. Une simple API REST contourne tout cela. Si votre CMS renvoie du JSON, votre frontend sait l'afficher.

Cet article utilise l'API REST de Kamaan comme exemple fil rouge parce qu'elle renvoie une forme JSON plate et prévisible et parce que le même endpoint sert chaque site de votre compte. Le schéma ci-dessous fonctionne avec n'importe quel CMS exposant du REST. Si vous voulez une introduction plus profonde à ce choix d'architecture, le pilier sur comment ajouter un blog à un SaaS couvre quand préférer le headless à un blog intégré à l'app. L'article complémentaire sur qu'est-ce qu'un CMS headless explique la séparation entre stockage de contenu et rendu.

Voici à quoi ressemble le même fetch en un coup d'oeil sur les cinq frameworks :

Carte de tutoriel API de blog montrant un endpoint REST Kamaan rendu par Next.js, Nuxt, SvelteKit, Astro et React pur

L'endpoint d'exemple et la forme de réponse

Voici l'appel que chaque framework ci-dessous effectue :

GET https://api.kamaan.io/v1/sites/{site_id}/articles?language=en&status=published
Authorization: Bearer kmn_pk_live_xxxxxxxxxxxxxxxx

La réponse est un tableau JSON d'articles. Chaque entrée ressemble à ceci :

{
  "id": "art_2k1nB7Vy8q",
  "title": "Blog API: How to Fetch and Render Headless CMS Content in Any Framework",
  "slug": "blog-api",
  "content": "# Blog API\n\nEvery framework has its own CMS SDK tutorial...",
  "excerpt": "One Kamaan endpoint, rendered five different ways.",
  "featured_image_url": "https://cdn.kamaan.io/img/km0013_featured.png",
  "language": "en",
  "parent_article_id": null,
  "status": "published",
  "published_at": "2026-05-29T10:14:00Z",
  "updated_at": "2026-05-29T10:14:00Z",
  "meta_title": "Blog API: One Endpoint, Five Frontends",
  "meta_description": "How to fetch and render headless CMS content...",
  "tags": ["headless-cms", "blog-api", "developer-integration"]
}

Pour obtenir un seul article par slug :

GET https://api.kamaan.io/v1/sites/{site_id}/articles/blog-api?language=en

Les traductions pointent vers la source via parent_article_id. Pour demander la version française du même billet, changez language=en en language=fr. Il n'y a pas d'endpoint de traduction supplémentaire. L'objet article a la même forme dans toutes les langues, ce qui veut dire que votre couche de routage n'a pas à se ramifier sur la locale.

Fetch numéro un : Next.js App Router

Composant serveur, s'exécute au build ou à la demande avec contrôle du cache :

// app/blog/page.tsx
const SITE_ID = process.env.KAMAAN_SITE_ID!;
const TOKEN = process.env.KAMAAN_TOKEN!;

async function getArticles() {
  const res = await fetch(
    `https://api.kamaan.io/v1/sites/${SITE_ID}/articles?language=en&status=published`,
    {
      headers: { Authorization: `Bearer ${TOKEN}` },
      next: { revalidate: 600 },
    },
  );
  if (!res.ok) throw new Error("Kamaan fetch failed");
  return res.json();
}

export default async function BlogIndex() {
  const articles = await getArticles();
  return (
    <ul>
      {articles.map((a: any) => (
        <li key={a.id}>
          <a href={`/blog/${a.slug}`}>{a.title}</a>
          <p>{a.excerpt}</p>
        </li>
      ))}
    </ul>
  );
}

La ligne next: { revalidate: 600 } indique à Next.js de mettre la réponse en cache pendant 10 minutes. Pour un blog marketing qui publie quelques fois par semaine, c'est la bonne valeur par défaut. Si vous voulez du purement statique, passez à force-cache. Si vous voulez chaque requête fraîche, passez à no-store. Pour le schéma complet, page de détail d'article et régénération statique incrémentale incluses, voyez le guide Next.js pour CMS headless.

Fetch numéro deux : Nuxt 3

Même endpoint, composable useFetch, s'exécute côté serveur pendant le SSR :

<!-- pages/blog/index.vue -->
<script setup lang="ts">
const config = useRuntimeConfig();
const { data: articles } = await useFetch(
  `https://api.kamaan.io/v1/sites/${config.kamaanSiteId}/articles`,
  {
    query: { language: "en", status: "published" },
    headers: { Authorization: `Bearer ${config.kamaanToken}` },
    server: true,
  },
);
</script>

<template>
  <ul>
    <li v-for="a in articles" :key="a.id">
      <NuxtLink :to="`/blog/${a.slug}`">{{ a.title }}</NuxtLink>
      <p>{{ a.excerpt }}</p>
    </li>
  </ul>
</template>

useFetch déduplique automatiquement l'appel entre le rendu serveur et l'hydratation client. La runtime config garde le token hors du bundle client.

Fetch numéro trois : SvelteKit

La fonction load côté serveur vous donne le contrôle total des en-têtes de cache :

// routes/blog/+page.server.ts
import { KAMAAN_SITE_ID, KAMAAN_TOKEN } from "$env/static/private";

export async function load({ fetch, setHeaders }) {
  const res = await fetch(
    `https://api.kamaan.io/v1/sites/${KAMAAN_SITE_ID}/articles?language=en&status=published`,
    { headers: { Authorization: `Bearer ${KAMAAN_TOKEN}` } },
  );
  setHeaders({ "cache-control": "public, max-age=600" });
  return { articles: await res.json() };
}
<!-- routes/blog/+page.svelte -->
<script lang="ts">
  export let data;
</script>

<ul>
  {#each data.articles as a (a.id)}
    <li>
      <a href={`/blog/${a.slug}`}>{a.title}</a>
      <p>{a.excerpt}</p>
    </li>
  {/each}
</ul>

Fetch numéro quatre : Astro

Astro fetch par défaut au moment du build, ce qui colle parfaitement à un blog riche en contenu :

---
// src/pages/blog/index.astro
const SITE_ID = import.meta.env.KAMAAN_SITE_ID;
const TOKEN = import.meta.env.KAMAAN_TOKEN;

const res = await fetch(
  `https://api.kamaan.io/v1/sites/${SITE_ID}/articles?language=en&status=published`,
  { headers: { Authorization: `Bearer ${TOKEN}` } },
);
const articles = await res.json();
---

<ul>
  {articles.map((a) => (
    <li>
      <a href={`/blog/${a.slug}`}>{a.title}</a>
      <p>{a.excerpt}</p>
    </li>
  ))}
</ul>

Si vous basculez Astro en mode SSR, le même code s'exécute à chaque requête. Aucun changement de code.

Fetch numéro cinq : React pur (Vite)

Fetch côté client dans une app React simple. Utile quand le blog vit dans un tableau de bord SaaS authentifié :

// src/pages/Blog.tsx
import { useEffect, useState } from "react";

const SITE_ID = import.meta.env.VITE_KAMAAN_SITE_ID;
const TOKEN = import.meta.env.VITE_KAMAAN_TOKEN;

export function Blog() {
  const [articles, setArticles] = useState<any[]>([]);
  useEffect(() => {
    fetch(
      `https://api.kamaan.io/v1/sites/${SITE_ID}/articles?language=en&status=published`,
      { headers: { Authorization: `Bearer ${TOKEN}` } },
    )
      .then((r) => r.json())
      .then(setArticles);
  }, []);
  return (
    <ul>
      {articles.map((a) => (
        <li key={a.id}>
          <a href={`/blog/${a.slug}`}>{a.title}</a>
          <p>{a.excerpt}</p>
        </li>
      ))}
    </ul>
  );
}

Pour une app React côté client, exposez un token public en lecture seule. N'envoyez jamais un token avec droits d'écriture au navigateur.

Voici la même image en une seule carte de référence : un endpoint en haut, le chemin de fichier où vit le fetch de chaque framework en dessous.

Infographie montrant un endpoint REST Kamaan récupéré par Next.js, Nuxt, SvelteKit, Astro et React, avec le chemin de fichier de chaque framework

Deux scénarios réels

Scénario un : un fondateur solo avec trois produits SaaS. Chaque produit a son propre site marketing sur un stack différent, choisi à des moments différents. Le produit A est sur Next.js, le produit B sur Astro, le produit C sur un tableau de bord React pur. Sans API de blog portable, le fondateur maintient trois intégrations CMS, trois workflows de contenu et trois factures. Avec un seul compte Kamaan et trois sites dedans, le même schéma de fetch ci-dessus tourne sur les trois. Les nouveaux articles rédigés dans Claude atterrissent dans le bon site via le MCP Server, et chaque frontend les récupère à la prochaine revalidation. Temps total d'intégration sur les trois frontends : moins de trois heures.

Scénario deux : une petite agence avec sept blogs SaaS clients. L'agence ne veut pas former sept interfaces CMS à sept clients. Ils opèrent les sept blogs depuis un seul tableau de bord Kamaan, donnent à chaque client un siège éditeur cantonné à son site, et laissent leur équipe contenu écrire en lot sur les sept depuis une seule fenêtre ChatGPT. Chaque site client utilise le framework dans lequel l'agence l'a bâti, en récupérant la même forme JSON.

Où Kamaan s'inscrit

Kamaan est le centre de commande pour les fondateurs multi-produits et les agences qui gèrent de nombreux blogs SaaS : pilotez chaque blog depuis un seul tableau de bord, et menez chaque opération sur tous depuis Claude, ChatGPT, Cursor ou n'importe quel client MCP. L'endpoint REST montré ci-dessus a la même forme sur chaque site de votre compte. Auto-Multilingual Delivery signifie que les traductions apparaissent automatiquement à la publication, renvoyées par le même endpoint articles avec language=de, language=fr, et ainsi de suite. Le champ parent_article_id relie chaque traduction à sa source anglaise, pour que votre couche de routage résolve les variantes de locale sans seconde requête.

Le prix est de 19 dollars par mois, forfait, sites illimités, sans frais par site, par space ou par siège. Le premier mois est gratuit, sans carte de crédit pour démarrer, résiliable à tout moment. Un plan à vie est disponible pour les équipes qui préfèrent payer une fois. Les crédits de traduction IA ne sont consommés que si Kamaan traduit. Si vous collez vos propres traductions depuis Claude ou ChatGPT, le téléversement ne coûte rien.

Le côté CMS de la première publication tient autour de 14 minutes de l'inscription au premier billet en ligne. L'intégration développeur, la partie traitée par cet article, prend honnêtement 40 à 60 minutes pour le premier câblage incluant variables d'environnement, route index, route détail et sitemap. Après ça, chaque nouveau site réutilise le même fetch.

FAQ

Qu'est-ce qu'une API de blog ?

Une API de blog est un endpoint HTTP qui renvoie des articles de blog sous forme de données structurées, en général du JSON. Votre code frontend appelle l'endpoint, reçoit les articles et les affiche comme vous voulez. Le CMS gère le stockage, l'édition et la publication. Le frontend gère la présentation.

Ai-je besoin d'un SDK propre à un fournisseur pour utiliser une API de blog ?

Non. La fonction fetch native intégrée à chaque runtime JavaScript moderne suffit. Les SDK peuvent ajouter du confort (réponses typées, logique de retry, transformations d'images) mais ils enferment aussi. Un endpoint REST qui renvoie du JSON brut fonctionne avec n'importe quel framework, n'importe quelle année, n'importe quelle version.

La même API de blog peut-elle alimenter plusieurs frontends ?

Oui. C'est tout l'intérêt du headless. Vous pouvez afficher les mêmes articles sur un site marketing Next.js, un site de doc Astro et un tableau de bord React en même temps, tous depuis un seul endpoint. Le CMS se moque de la façon dont le contenu est rendu.

Comment gérer les traductions depuis une API de blog ?

Cherchez un CMS qui renvoie les traductions comme des objets articles séparés reliés à la source par un champ parent. Kamaan utilise parent_article_id. Pour récupérer la version allemande, passez language=de sur le même endpoint articles. Évitez les CMS qui imbriquent les traductions dans un seul objet article, parce que cela force chaque frontend à parser la logique de locale.

Devrais-je mettre les réponses de l'API de blog en cache ?

Oui, dans presque tous les cas. Le contenu d'un blog marketing ne change pas souvent. Pour les frameworks à export statique comme Astro ou Next.js avec revalidate, le fetch se fait au build ou sur un long intervalle. Pour les frameworks SSR, un cache de 5 à 10 minutes est généralement sûr. Ne sautez le cache que si les brouillons de prévisualisation doivent apparaître immédiatement pour les éditeurs connectés.

Et pour les brouillons de prévisualisation ?

Passez status=draft et ajoutez un en-tête d'auth ou un jeton de prévisualisation que vos éditeurs transportent. La plupart des équipes livrent une route /preview/[slug] séparée qui récupère du contenu brouillon, derrière un mur de connexion.

Comment afficher du markdown renvoyé par l'API ?

Choisissez un parseur markdown qui correspond à votre runtime. Pour React, react-markdown fonctionne. Pour Vue, vue-markdown-render. Pour Svelte, svelte-markdown. Pour Astro, le composant intégré. Le CMS devrait renvoyer du markdown brut pour que chaque frontend l'assainisse à sa façon.

En quoi est-ce différent de choisir Contentful ou Sanity ?

Contentful et Sanity exposent tous deux des endpoints REST, donc le schéma de fetch ci-dessus fonctionne aussi contre eux. Les différences tiennent au modèle de prix et à la surface opérationnelle. Kamaan facture un forfait de 19 dollars par mois pour des sites illimités et vous donne une orchestration IA via MCP pour mener chaque opération de blog depuis Claude, ChatGPT ou Cursor.

À lire aussi sur Kamaan

Démarrer avec Kamaan

Kamaan est le centre de commande pour les fondateurs multi-produits et les agences qui gèrent de nombreux blogs SaaS : pilotez chaque blog depuis un seul tableau de bord, et menez chaque opération sur tous depuis Claude, ChatGPT, Cursor ou n'importe quel client MCP. Auto-Multilingual Delivery signifie qu'une traduction apparaît automatiquement sur chaque locale à la publication. Multi-Site Management signifie un compte, une facture, chaque blog que vous opérez. La REST API Delivery montrée dans cet article a la même forme sur chaque site de votre compte.

Le prix est de 19 dollars par mois, forfait, sites illimités, sans frais par site, par space ou par siège. Le premier mois est gratuit, sans carte de crédit pour démarrer, résiliable à tout moment. Un plan à vie est disponible si vous préférez payer une fois. Essayez-le sur votre prochain blog et gardez le code de fetch que vous avez déjà écrit.

Frequently asked

FAQ · 8 ITEMS
Qu'est-ce qu'une API de blog ?

Une API de blog est un endpoint HTTP qui renvoie des articles de blog sous forme de données structurées, en général du JSON. Votre code frontend appelle l'endpoint, reçoit les articles et les affiche comme vous voulez. Le CMS gère le stockage, l'édition et la publication. Le frontend gère la présentation.

Ai-je besoin d'un SDK propre à un fournisseur pour utiliser une API de blog ?

Non. La fonction fetch native intégrée à chaque runtime JavaScript moderne suffit. Les SDK peuvent ajouter du confort (réponses typées, logique de retry, transformations d'images) mais ils enferment aussi. Un endpoint REST qui renvoie du JSON brut fonctionne avec n'importe quel framework, n'importe quelle année, n'importe quelle version.

La même API de blog peut-elle alimenter plusieurs frontends ?

Oui. C'est tout l'intérêt du headless. Vous pouvez afficher les mêmes articles sur un site marketing Next.js, un site de doc Astro et un tableau de bord React en même temps, tous depuis un seul endpoint. Le CMS se moque de la façon dont le contenu est rendu.

Comment gérer les traductions depuis une API de blog ?

Cherchez un CMS qui renvoie les traductions comme des objets articles séparés reliés à la source par un champ parent. Kamaan utilise `parent_article_id`. Pour récupérer la version allemande, passez `language=de` sur le même endpoint articles. Évitez les CMS qui imbriquent les traductions dans un seul objet article, parce que cela force chaque frontend à parser la logique de locale.

Devrais-je mettre les réponses de l'API de blog en cache ?

Oui, dans presque tous les cas. Le contenu d'un blog marketing ne change pas souvent. Pour les frameworks à export statique comme Astro ou Next.js avec revalidate, le fetch se fait au build ou sur un long intervalle. Pour les frameworks SSR, un cache de 5 à 10 minutes est généralement sûr. Ne sautez le cache que si les brouillons de prévisualisation doivent apparaître immédiatement pour les éditeurs connectés.

Et pour les brouillons de prévisualisation ?

Passez `status=draft` et ajoutez un en-tête d'auth ou un jeton de prévisualisation que vos éditeurs transportent. La plupart des équipes livrent une route `/preview/[slug]` séparée qui récupère du contenu brouillon, derrière un mur de connexion.

Comment afficher du markdown renvoyé par l'API ?

Choisissez un parseur markdown qui correspond à votre runtime. Pour React, `react-markdown` fonctionne. Pour Vue, `vue-markdown-render`. Pour Svelte, `svelte-markdown`. Pour Astro, le composant intégré. Le CMS devrait renvoyer du markdown brut pour que chaque frontend l'assainisse à sa façon.

En quoi est-ce différent de choisir Contentful ou Sanity ?

Contentful et Sanity exposent tous deux des endpoints REST, donc le schéma de fetch ci-dessus fonctionne aussi contre eux. Les différences tiennent au modèle de prix et à la surface opérationnelle. Kamaan facture un forfait de 19 dollars par mois pour des sites illimités et vous donne une orchestration IA via MCP pour mener chaque opération de blog depuis Claude, ChatGPT ou Cursor.

Junaid Khalid
Written by
Junaid Khalid

Junaid Khalid is the founder of Kamaan, a headless blog CMS that auto-publishes in five languages and lets you manage every product blog from one dashboard.