Use Cases

Implémentation de Contentful CMS avec Claude Code

Découvrez l'implémentation de Contentful CMS avec Claude Code. Conseils pratiques et exemples de code inclus.

Optimiser l’intégration de Contentful CMS avec Claude Code

Contentful est le leader des CMS headless, offrant une gestion de contenu basée sur les API. Grâce à ses modèles de contenu structurés et ses riches API de diffusion, le contenu est accessible depuis n’importe quel frontend. Avec Claude Code, vous pouvez progresser efficacement de la conception du modèle de contenu à l’intégration frontend.

Conception du modèle de contenu

> Conçois un modèle de contenu pour un site blog avec Contentful.
> Avec 3 types de contenu : article, catégorie et auteur.
// scripts/setup-content-model.ts
import contentful from 'contentful-management';

const client = contentful.createClient({
  accessToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN!,
});

async function setupContentModel() {
  const space = await client.getSpace(process.env.CONTENTFUL_SPACE_ID!);
  const env = await space.getEnvironment('master');

  // Type de contenu Auteur
  const author = await env.createContentTypeWithId('author', {
    name: 'Author',
    fields: [
      { id: 'name', name: 'Name', type: 'Symbol', required: true },
      { id: 'slug', name: 'Slug', type: 'Symbol', required: true },
      { id: 'bio', name: 'Bio', type: 'Text' },
      { id: 'avatar', name: 'Avatar', type: 'Link', linkType: 'Asset' },
    ],
  });
  await author.publish();

  // Catégorie
  const category = await env.createContentTypeWithId('category', {
    name: 'Category',
    fields: [
      { id: 'name', name: 'Name', type: 'Symbol', required: true },
      { id: 'slug', name: 'Slug', type: 'Symbol', required: true },
      { id: 'description', name: 'Description', type: 'Text' },
    ],
  });
  await category.publish();

  // Article de blog
  const blogPost = await env.createContentTypeWithId('blogPost', {
    name: 'Blog Post',
    fields: [
      { id: 'title', name: 'Title', type: 'Symbol', required: true },
      { id: 'slug', name: 'Slug', type: 'Symbol', required: true },
      { id: 'excerpt', name: 'Excerpt', type: 'Text' },
      { id: 'body', name: 'Body', type: 'RichText' },
      { id: 'featuredImage', name: 'Featured Image', type: 'Link', linkType: 'Asset' },
      { id: 'author', name: 'Author', type: 'Link', linkType: 'Entry' },
      { id: 'category', name: 'Category', type: 'Link', linkType: 'Entry' },
      { id: 'tags', name: 'Tags', type: 'Array', items: { type: 'Symbol' } },
      { id: 'publishedAt', name: 'Published At', type: 'Date' },
    ],
  });
  await blogPost.publish();
}

Récupération du contenu

> Crée un client pour récupérer les articles de blog via
> l'API Content Delivery de Contentful. Génère aussi les types TypeScript.
// src/lib/contentful.ts
import { createClient, type Entry, type Asset } from 'contentful';

const client = createClient({
  space: process.env.CONTENTFUL_SPACE_ID!,
  accessToken: process.env.CONTENTFUL_ACCESS_TOKEN!,
});

// Client pour la prévisualisation
const previewClient = createClient({
  space: process.env.CONTENTFUL_SPACE_ID!,
  accessToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,
  host: 'preview.contentful.com',
});

function getClient(preview = false) {
  return preview ? previewClient : client;
}

// Définitions de types
interface BlogPostFields {
  title: string;
  slug: string;
  excerpt: string;
  body: any; // Rich Text Document
  featuredImage: Asset;
  author: Entry<AuthorFields>;
  category: Entry<CategoryFields>;
  tags: string[];
  publishedAt: string;
}

interface AuthorFields {
  name: string;
  slug: string;
  bio: string;
  avatar: Asset;
}

interface CategoryFields {
  name: string;
  slug: string;
  description: string;
}

// Récupération de la liste des articles
export async function getBlogPosts(options?: {
  limit?: number;
  skip?: number;
  category?: string;
  preview?: boolean;
}) {
  const { limit = 10, skip = 0, category, preview = false } = options || {};

  const query: any = {
    content_type: 'blogPost',
    order: ['-fields.publishedAt'],
    limit,
    skip,
    include: 2,
  };

  if (category) {
    query['fields.category.sys.contentType.sys.id'] = 'category';
    query['fields.category.fields.slug'] = category;
  }

  const entries = await getClient(preview).getEntries<BlogPostFields>(query);

  return {
    posts: entries.items,
    total: entries.total,
  };
}

// Récupération d'un article individuel
export async function getBlogPost(slug: string, preview = false) {
  const entries = await getClient(preview).getEntries<BlogPostFields>({
    content_type: 'blogPost',
    'fields.slug': slug,
    include: 2,
    limit: 1,
  });

  return entries.items[0] || null;
}

Implémentation ISR avec Next.js

// app/blog/[slug]/page.tsx
import { getBlogPost, getBlogPosts } from '@/lib/contentful';
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';
import { notFound } from 'next/navigation';

export const revalidate = 60; // Revalidation toutes les 60 secondes

export async function generateStaticParams() {
  const { posts } = await getBlogPosts({ limit: 100 });
  return posts.map((post) => ({ slug: post.fields.slug }));
}

export default async function BlogPostPage({
  params,
}: {
  params: { slug: string };
}) {
  const post = await getBlogPost(params.slug);
  if (!post) notFound();

  return (
    <article className="max-w-3xl mx-auto p-6">
      <h1 className="text-4xl font-bold">{post.fields.title}</h1>
      <p className="text-gray-500 mt-2">
        {new Date(post.fields.publishedAt).toLocaleDateString('fr-FR')}
      </p>
      <div className="prose mt-8">
        {documentToReactComponents(post.fields.body)}
      </div>
    </article>
  );
}

Résumé

En combinant l’approche API-first de Contentful avec Claude Code, vous pouvez construire efficacement un système de gestion de contenu flexible. Consultez aussi le guide de construction de CMS blog et la comparaison SSR/SSG.

Pour plus de détails sur Contentful, consultez la documentation officielle de Contentful.

#Claude Code #Contentful #CMS #CMS headless #gestion de contenu