はじめに
Futuristic Imagination LLC 代表の佐藤琢也です。
弊社では、最先端のGenerative AIを活用し、Webコンテンツの自動生成・運用を徹底的に追求しています。現在、私一人でAIオウンドメディアを18サイト(9言語展開)運用しており、年間6,570記事を自動生成するシステムを構築・稼働させています。
「どうやってそんな大量の記事を自動で、しかもSEOに強い形で生成・運用しているんですか?」
この質問をよくいただきます。そこで本記事では、その中核をなす「Next.js + Gemini API でSEO記事を毎日自動生成するパイプライン」の設計思想と具体的な実装について、深掘りして解説していきます。
この記事が、コンテンツマーケティングの自動化や、Generative AIを活用した新しいビジネスモデルを検討されているエンジニアの皆さんにとって、具体的なヒントになれば幸いです。
この記事でわかること
- Next.jsとGemini APIを組み合わせた記事自動生成パイプラインの全体像
- SEOに強い記事を生成するためのプロンプトエンジニアリングの考え方
- Vercel CronやGitHub連携を活用した自動化ワークフローの実装方法
- 大規模コンテンツ運用における技術的な課題と解決策
- 弊社での具体的な実装事例とコードスニペット
1. なぜ「Next.js + Gemini API」なのか?
私たちがこの技術スタックを選定したのには、明確な理由があります。
-
Next.js (App Router, SSG/ISR):
- パフォーマンスとSEO: 静的生成(SSG)や増分静的再生成(ISR)により、高速なページ表示とSEOに有利な構造を両立できます。これはGoogleの評価基準にも直結します。
- 開発体験と保守性: TypeScriptとの親和性も高く、堅牢で大規模なアプリケーション開発に適しています。
- Vercelとの連携: Vercel CronなどのCI/CDと非常に相性が良く、デプロイや自動化が容易です。
-
Gemini API:
- 高品質なコンテンツ生成: 最新のモデルは、SEO要件を満たす自然で情報量豊富な記事を生成する能力に優れています。
- APIの柔軟性: プロンプトエンジニアリングによって、特定のトピック、キーワード、文体、構造など、詳細な指示を出すことが可能です。
- 多言語対応: 9言語での記事生成を実現する上で、多言語対応能力は必須でした。
これらの技術を組み合わせることで、「補給不要の自販機型SaaS」という弊社のビジョン、つまり最小限の介入で持続的に価値を生み出し続けるシステムを実現しています。
2. パイプラインの全体設計
弊社のSEO記事自動生成パイプラインは、以下の主要なフェーズで構成されています。
各フェーズを自動化することで、毎日、毎週、あるいは特定のトリガーで一連のプロセスが実行されるように設計しています。
3. 具体的な実装とコード例
ここからは、実際に私がどのように実装しているかを、コードスニペットを交えながら解説します。
3.1. キーワード選定とプロンプトエンジニアリング
記事生成の最も重要なフェーズは、高品質なプロンプトを作成することです。Gemini APIに投げるプロンプトは、以下の要素を網羅するように設計しています。
- ターゲットキーワードと関連キーワード: 記事の核となるキーワードと、SEOで上位表示を狙うための関連キーワードを明確に指示します。
- 読者ターゲット: どのような読者に向けた記事か(初心者、専門家など)。
- 記事の目的: 読者の疑問解決、商品の紹介、情報提供など。
- 記事の構成: タイトル、導入、見出し構成(H2, H3)、結論、FAQ、参考文献(任意)など。SEOに強い記事は論理的な構成が不可欠です。
- 文体とトーン: 丁寧語、カジュアル、専門的など。
- 具体的な情報源(任意): 必要に応じて、信頼できる情報源のURLなどを指定します。
- 文字数指定: 記事のボリュームを指定します。
// src/lib/prompts/seoArticleGenerator.ts
interface ArticlePromptOptions {
keyword: string;
targetAudience: string;
wordCount: number;
relatedKeywords?: string[];
tone?: 'formal' | 'casual' | 'expert';
}
export function generateSeoArticlePrompt(options: ArticlePromptOptions): string {
const { keyword, targetAudience, wordCount, relatedKeywords, tone = 'formal' } = options;
const relatedKeywordsStr = relatedKeywords && relatedKeywords.length > 0
? `以下の関連キーワードも自然に含めてください: ${relatedKeywords.join(', ')}。`
: '';
return `あなたは、SEOに強く、読者の疑問を完全に解決する専門家ライターです。
以下の指示に従い、高品質なSEO記事を生成してください。
---
# 記事生成指示
## 1. 記事のテーマとキーワード
メインキーワード: 「${keyword}」
${relatedKeywordsStr}
## 2. 読者ターゲット
「${targetAudience}」をターゲット読者としてください。彼らが知りたい情報、抱える課題を解決する内容にしてください。
## 3. 記事の構成
以下の構成で記事を作成してください。各セクションは見出し(H2, H3)を適切に利用し、論理的に展開してください。
- タイトル (読者の興味を引く魅力的なタイトルを3パターン提案してください)
- 導入 (記事の概要と読者のメリットを簡潔に説明)
- メインコンテンツ (H2で複数セクションに分け、H3も適宜使用)
- 読者の疑問を解決する具体的な情報
- 関連キーワードを自然に盛り込む
- 具体的な事例やデータがあれば、それを想起させる内容
- まとめ (記事全体の要約と今後の行動を促す内容)
- FAQ (読者が抱きそうな3つの質問とその回答)
## 4. 文体とトーン
「${tone}」で、信頼性と専門性を感じる文章にしてください。
語尾は「です・ます」調を基本とします。
## 5. 文字数
約${wordCount}文字程度になるように記述してください。
## 6. その他
- 箇条書きやリスト、コードブロック(架空のものでも良い)などを活用し、読みやすい記事構造にしてください。
- 引用元や参考URLは不要です。
---
上記指示に基づいて、SEOに強く、読者の検索意図を深く満たす記事本文を生成してください。`;
}
このプロンプトをGemini APIに渡し、記事コンテンツを取得します。
3.2. Gemini APIとの連携とコンテンツ生成
Next.jsのAPIルート (app/api/generate-article/route.ts) からGemini APIを呼び出します。
// app/api/generate-article/route.ts (抜粋)
import { GoogleGenerativeAI } from '@google/generative-ai';
import { NextResponse } from 'next/server';
import { generateSeoArticlePrompt } from '@/lib/prompts/seoArticleGenerator';
export async function POST(req: Request) {
try {
const { keyword, targetAudience, wordCount, relatedKeywords } = await req.json();
if (!keyword || !targetAudience || !wordCount) {
return NextResponse.json({ error: 'Missing required parameters' }, { status: 400 });
}
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
const model = genAI.getGenerativeModel({ model: 'gemini-pro' });
const prompt = generateSeoArticlePrompt({
keyword,
targetAudience,
wordCount,
relatedKeywords,
});
const result = await model.generateContent(prompt);
const response = await result.response;
const text = response.text();
// ここで生成されたテキストを整形し、ファイルとして保存するロジックを呼び出す
// (後述のファイル保存処理へ)
return NextResponse.json({ success: true, articleContent: text });
} catch (error) {
console.error('Error generating article:', error);
return NextResponse.json({ error: 'Failed to generate article' }, { status: 500 });
}
}
3.3. 記事コンテンツの整形とファイル保存
Gemini APIから返されたテキストは、マークダウン形式で整形されていますが、さらに弊社のNext.jsプロジェクトの形式に合うように調整します。そして、記事のパスとファイル名を決定し、.md または .mdx ファイルとしてプロジェクト内に保存します。
この保存処理は、直接ディスクに書き込むのではなく、GitHub API経由でリポジトリにコミットする形をとっています。これにより、VercelがGitHubの変更を検知し、自動的にデプロイしてくれるワークフローが確立されます。
// src/utils/githubFileOperations.ts (抜粋)
import { Octokit } from '@octokit/rest';
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const owner = process.env.GITHUB_REPO_OWNER!;
const repo = process.env.GITHUB_REPO_NAME!;
export async function commitFileToRepo(filePath: string, content: string, commitMessage: string) {
try {
// まず、既存のファイルがあるか確認
let sha: string | undefined;
try {
const { data: fileData } = await octokit.repos.getContent({
owner,
repo,
path: filePath,
});
if ('sha' in fileData) {
sha = fileData.sha;
}
} catch (error: any) {
if (error.status !== 404) { // ファイルがない場合は404なのでOK
throw error;
}
}
const base64Content = Buffer.from(content).toString('base64');
await octokit.repos.createOrUpdateFileContents({
owner,
repo,
path: filePath,
message: commitMessage,
content: base64Content,
sha: sha, // 更新の場合は既存のSHAが必要
branch: 'main', // デフォルトブランチ
});
console.log(`File committed to GitHub: ${filePath}`);
return true;
} catch (error) {
console.error('Failed to commit file to GitHub:', error);
return false;
}
}
// 例:記事生成後の呼び出し
async function saveGeneratedArticle(title: string, content: string) {
const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-*|-*$/g, '');
const filePath = `src/articles/${slug}.mdx`;
const fullContent = `---
title: "${title}"
date: "${new Date().toISOString()}"
author: "AI Writer"
keywords: "SEO, 自動化, Gemini AI"
---
${content}
`;
await commitFileToRepo(filePath, fullContent, `feat: Add new article - ${title}`);
}
このプロセスにより、Gemini APIが生成した記事がGitHubリポジトリに自動的にコミットされ、Next.jsプロジェクトの新しいコンテンツとして認識されます。
3.4. Vercel Cronによるデプロイと自動化
Vercel Cronは、特定のスケジュールでAPIルートを実行できる非常に強力な機能です。私たちはこれを利用して、毎日決まった時間に記事生成パイプラインを起動しています。
vercel.json に設定を記述します。
// vercel.json
{
"crons": [
{
"path": "/api/generate-article",
"schedule": "0 0 * * *" // 毎日UTC 00:00 (日本時間 午前9時) に実行
}
]
}
この設定により、毎日Vercelが /api/generate-article エンドポイントを叩き、記事生成処理が実行されます。
記事がGitHubにコミットされると、Vercelは自動的にデプロイを開始し、新しい記事が公開されるという流れです。
3.5. SEO自動改善と効果測定
記事公開後のPDCAも自動化しています。
- Google Search Console API & GA4 API: これらのAPIを連携し、公開した記事のパフォーマンス(検索順位、クリック数、表示回数、PV数、離脱率など)を定期的に取得します。
- 低品質記事の自動検出とリライト: パフォーマンスが低い(例: 検索順位が低い、クリック率が悪い)と判断された記事を自動で検出し、Gemini APIに「この記事を改善するための提案」や「リライト」を指示します。
- アフィリエイトCTAの自動挿入: A8.net, Amazonアソシエイト, 楽天アフィリエイトなどのCTAを、記事内容に合わせて自動で挿入するロジックも組み込んでいます。
- SNS自動投稿パイプライン: 生成された記事の概要やURLを、LinkedIn, Note, Qiita, Zennなどの複数のSNSプラットフォームに自動で投稿するパイプラインも構築しています。
これら全てを自動化することで、人的リソースを最小限に抑えつつ、継続的な記事の改善と露出拡大を図っています。
4. 複数メディア運用における工夫
AIオウンドメディア18サイト(9言語展開)を一人で運用するには、さらなる効率化が必要です。
- モノレポ構成: 複数のメディアを一つのリポジトリで管理し、共通のコンポーネントやロジックを共有することで、開発・運用コストを削減しています。
- 環境変数の動的切り替え: 各メディア固有のAPIキーや設定は、環境変数で動的に切り替えるように設計しています。
- AI Session Manager (AG Hub): 複数エージェントが同時に動く複雑なシステムにおいて、それぞれのセッションや状態を管理するための内製ツールを活用しています。これにより、並列処理の安定性と効率を向上させています。
5. まとめ
本記事では、Next.jsとGemini APIを核としたSEO記事自動生成パイプラインの設計と実装についてご紹介しました。
Generative AIとWeb開発の最新技術を組み合わせることで、一人でも大規模なコンテンツ運用と事業展開が可能になることをご理解いただけたかと思います。重要なのは、単に記事を自動生成するだけでなく、SEOを意識したプロンプトエンジニアリング、堅牢な自動化パイプライン、そして公開後のPDCAサイクルまでを設計・実装することです。
弊社Futuristic Imagination LLCでは、このようなNext.jsへのWordPressからの移行、Generative AIを活用した自動化パイプライン構築、そしてコンテンツ生成から運用までを一貫してサポートする「MediaForge AI」といったB2B受託サービスも展開しています。
- 今回紹介したようなシステムの構築代行も行っています → https://www.futuristicimagination.co.jp/service/
- AIを活用したオウンドメディア構築にご興味があれば、ぜひご相談ください → https://mediaforge-ai.vercel.app/
また、転職・副業・キャリアに関するShorts動画を毎日配信しています。こちらもぜひご覧ください。
→ https://www.youtube.com/channel/UCFobIbWz1KDKaIdDqXpTPAA
最後までお読みいただきありがとうございました。この記事が皆さんの技術開発の一助となれば幸いです。