GuideAutomatisationGratuit

Blog automatisé avec l'IA — 2/3 : Génération automatique avec Claude

Le cœur du système : configure Claude pour générer un article SEO complet à partir d'un mot-clé, et planifie 2 crons Vercel pour orchestrer génération + publication.

Publié le 28 avril 2026· 3 min de lecture
Télécharger le pack

Partie 2/3 — Génération automatique avec Claude

Pré-requis : avoir terminé la Partie 1 (tables Supabase + .env.local).

Ce que tu vas obtenir à la fin de cette partie

  • Une fonction qui transforme un mot-clé en article SEO complet (titre, HTML, meta, JSON-LD)
  • Un cron Vercel qui génère 4 articles/semaine
  • Un 2e cron qui les publie automatiquement après 24h
  • Une liste de mots-clés stratégique en 3 phases

Temps estimé : 30 minutes
Pré-requis : une clé API Anthropic (console.anthropic.com)


Étape 1 — Récupérer ta clé Claude

  1. Va sur console.anthropic.comSettings → API Keys
  2. Create Key → copie la clé sk-ant-...
  3. Ajoute-la dans .env.local :
ANTHROPIC_API_KEY=sk-ant-api03-xxxxxxxx
  1. Installe le SDK Anthropic :
npm install @anthropic-ai/sdk

💰 Coût : Claude Opus à ~0,02 € par article. Pour 16 articles/mois ≈ 0,30 €/mois.


Étape 2 — Le générateur d'articles

Crée le fichier src/lib/seo/article-generator.ts. C'est lui qui appelle Claude avec le bon prompt et parse le JSON renvoyé.

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

export async function generateSEOArticle(
  keyword: string,
  existingArticles: { title: string; slug: string }[]
) {
  // Liste des articles déjà publiés → Claude peut faire des liens internes
  const internalLinksContext = existingArticles
    .map(a => `- ${a.title} : /blog/${a.slug}`)
    .join("\n");

  const response = await client.messages.create({
    model: "claude-opus-4-7",
    max_tokens: 4096,
    messages: [{
      role: "user",
      content: [
        {
          type: "text",
          text: `Tu es un expert SEO et copywriter en français.

Génère un article de blog SEO optimisé pour le mot-clé : "${keyword}"

Articles déjà publiés (utilise-les pour des liens internes pertinents) :
${internalLinksContext}

Contraintes :
- 800-1100 mots
- Structure H2/H3 claire avec une intro et une conclusion
- Inclure 2-3 liens internes vers les articles existants
- Ton professionnel mais accessible

Réponds UNIQUEMENT en JSON valide, sans texte avant/après, avec EXACTEMENT cette structure :`,
          cache_control: { type: "ephemeral" }
        },
        {
          type: "text",
          text: `{
  "title": "Titre SEO 50-65 chars contenant le mot-clé",
  "slug": "slug-url-friendly-en-tirets",
  "meta_description": "150-160 chars, contient le mot-clé, donne envie de cliquer",
  "excerpt": "2-3 phrases qui résument l'article",
  "content_html": "<article>...HTML sémantique avec h2, h3, p, ul, blockquote...</article>",
  "target_keywords": ["mot-clé principal", "variante 1", "variante 2"],
  "internal_links": [{ "text": "ancre", "href": "/blog/slug-existant" }],
  "schema_json": {
    "@context": "https://schema.org",
    "@type": "Article",
    "headline": "Titre",
    "description": "Meta description",
    "inLanguage": "fr-FR",
    "wordCount": 950
  }
}`
        }
      ]
    }]
  });

  const text = response.content[0].type === "text" ? response.content[0].text : "";
  const match = text.match(/\{[\s\S]*\}/);
  if (!match) throw new Error("Claude n'a pas renvoyé de JSON valide");
  return JSON.parse(match[0]);
}

Pourquoi cache_control: ephemeral ? Anthropic met en cache la première partie du prompt. Si tu génères plusieurs articles dans la même session, les générations 2+ coûtent 90 % moins cher.


Étape 3 — La liste de mots-clés stratégique

La stratégie qui marche : commence par la longue traîne (faible concurrence → indexation rapide), puis monte vers les mots-clés piliers quand ton domaine a de l'autorité.

Crée src/lib/seo/seed-keywords.ts :

export const KEYWORDS = [
  // ─── Phase 1 : longue traîne (priority 90-99) ──────────────
  // Indexation rapide, faible concurrence, premiers trafics
  { keyword: "comment automatiser ses tâches avec l'ia",
    cluster: "tutoriels", volume_est: 200, difficulty: 20, priority: 95 },
  { keyword: "configurer claude api en 5 minutes",
    cluster: "tutoriels", volume_est: 150, difficulty: 18, priority: 93 },

  // ─── Phase 2 : intention d'achat (priority 80-89) ─────────
  // Conversion : la personne cherche déjà une solution
  { keyword: "meilleurs outils ia productivité 2026",
    cluster: "comparaison", volume_est: 500, difficulty: 35, priority: 85 },
  { keyword: "alternative chatgpt pour entreprise",
    cluster: "comparaison", volume_est: 400, difficulty: 32, priority: 82 },

  // ─── Phase 3 : piliers (priority 70-79) ───────────────────
  // Fort volume, forte concurrence — à attaquer en dernier
  { keyword: "intelligence artificielle entreprise",
    cluster: "pilier", volume_est: 8000, difficulty: 70, priority: 72 },
];

Comment trouver tes propres mots-clés ?

  • Outils gratuits : Google Keyword Planner, Ubersuggest (3 recherches/jour)
  • Cible des difficulty ≤ 30 pour la phase 1
  • Vise 20-30 mots-clés au total pour avoir 5-6 mois de contenu

Étape 4 — Cron 1 : générer un article

Crée src/app/api/cron/seo-blog/generate/route.ts. Ce cron tourne lun/mer/ven/sam à 6h UTC : il prend le mot-clé prioritaire, génère l'article, le sauvegarde en scheduled avec 24h de délai.

import { createClient } from "@supabase/supabase-js";
import { generateSEOArticle } from "@/lib/seo/article-generator";

export const maxDuration = 300; // Vercel Pro : 5 min

export async function GET(request: Request) {
  // 1. Sécurité : seul Vercel Cron peut appeler cette route
  const auth = request.headers.get("authorization");
  if (auth !== `Bearer ${process.env.CRON_SECRET}`) {
    return Response.json({ error: "Unauthorized" }, { status: 401 });
  }

  const supabase = createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
  );

  // 2. Pioche le mot-clé pending avec la priority la plus haute
  const { data: keyword } = await supabase
    .from("seo_keywords")
    .select("*")
    .eq("status", "pending")
    .order("priority", { ascending: false })
    .limit(1)
    .single();

  if (!keyword) {
    return Response.json({ message: "Plus aucun mot-clé en attente" });
  }

  // 3. Récupère les 20 derniers articles publiés (pour les liens internes)
  const { data: existing } = await supabase
    .from("seo_articles")
    .select("title, slug")
    .eq("status", "published")
    .order("published_at", { ascending: false })
    .limit(20);

  // 4. Appel à Claude
  const article = await generateSEOArticle(keyword.keyword, existing || []);

  // 5. Sauvegarde en "scheduled" avec 24h de délai
  const scheduledAt = new Date(Date.now() + 24 * 60 * 60 * 1000);

  await supabase.from("seo_articles").insert({
    ...article,
    status: "scheduled",
    scheduled_at: scheduledAt,
    keyword_id: keyword.id,
    lang: "fr",
  });

  // 6. Marque le mot-clé comme utilisé
  await supabase.from("seo_keywords")
    .update({ status: "used", used_at: new Date() })
    .eq("id", keyword.id);

  return Response.json({ success: true, title: article.title });
}

💡 Pourquoi 24h de délai ? Pour te laisser le temps de relire avant publication automatique. Si l'article est nul, tu le supprimes (on verra l'interface admin en partie 3).


Étape 5 — Cron 2 : publier les articles prêts

Crée src/app/api/cron/seo-blog/publish/route.ts. Ce cron tourne tous les jours à 7h UTC : il publie tous les articles scheduled dont la date est passée.

import { createClient } from "@supabase/supabase-js";

export const maxDuration = 60;

export async function GET(request: Request) {
  const auth = request.headers.get("authorization");
  if (auth !== `Bearer ${process.env.CRON_SECRET}`) {
    return Response.json({ error: "Unauthorized" }, { status: 401 });
  }

  const supabase = createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.SUPABASE_SERVICE_ROLE_KEY!
  );
  const now = new Date().toISOString();

  // Tous les articles dont la date de publication est passée
  const { data: articles } = await supabase
    .from("seo_articles")
    .select("id, slug, schema_json")
    .eq("status", "scheduled")
    .lte("scheduled_at", now);

  for (const article of articles || []) {
    // Met à jour les dates dans le JSON-LD
    const schema = {
      ...article.schema_json,
      datePublished: now,
      dateModified: now
    };

    await supabase.from("seo_articles").update({
      status: "published",
      published_at: now,
      schema_json: schema,
    }).eq("id", article.id);

    // En partie 3 : ping Google Indexing API ici
  }

  return Response.json({ published: articles?.length || 0 });
}

Étape 6 — Planifier les crons sur Vercel

Crée un fichier vercel.json à la racine de ton projet :

{
  "crons": [
    {
      "path": "/api/cron/seo-blog/generate",
      "schedule": "0 6 * * 1,3,5,6"
    },
    {
      "path": "/api/cron/seo-blog/publish",
      "schedule": "0 7 * * *"
    }
  ]
}

Lecture des cron expressions :

Schedule Signification
0 6 * * 1,3,5,6 Tous les lundis, mercredis, vendredis, samedis à 6h00 UTC
0 7 * * * Tous les jours à 7h00 UTC

⚠️ Vercel : les crons nécessitent un plan Pro ($20/mois). Alternative gratuite : GitHub Actions avec un schedule workflow qui fait un curl vers tes routes.


Étape 7 — Tester en local

Avant de déployer, teste tes routes en local. Lance Next.js :

npm run dev

Dans un autre terminal, simule l'appel de Vercel Cron :

# Test génération
curl -H "Authorization: Bearer ton-cron-secret" \
  http://localhost:3000/api/cron/seo-blog/generate

# Test publication
curl -H "Authorization: Bearer ton-cron-secret" \
  http://localhost:3000/api/cron/seo-blog/publish

Tu devrais voir un JSON { "success": true, "title": "..." } et un nouvel article apparaître dans Supabase (Table Editor → seo_articles).


✅ Récap : ce que tu as maintenant

  • Générateur d'articles connecté à Claude
  • Liste de mots-clés stratégique (3 phases)
  • Cron de génération (4×/semaine)
  • Cron de publication (1×/jour)
  • vercel.json prêt pour le déploiement

📦 Ce que contient le pack à télécharger

  • README.md — ce guide
  • install.sh — commande d'installation du SDK
  • article-generator.ts — appel à Claude (Étape 2)
  • seed-keywords.ts — exemple de mots-clés (Étape 3)
  • cron-generate.ts — cron de génération (Étape 4)
  • cron-publish.ts — cron de publication (Étape 5)
  • vercel.json — config des crons (Étape 6)
  • test-local.sh — script de test (Étape 7)

Suite → Partie 3/3 : interface admin, Google Indexing API, déploiement final

← Partie précédenteBlog automatisé avec l'IA — 1/3 : Setup & base de donnéesPartie suivante →Blog automatisé avec l'IA — 3/3 : Admin, Google Indexing & déploiement
← Retour aux ressources