Migrating Blog Content: From Contentful to Static Markdown in Next.js
August 12, 2025 development notes Next.js Contentful Markdown Data Migration

Migrating blog content from a Headless CMS like Contentful to static Markdown files in a Next.js project can offer benefits like simplified deployment and reduced external dependencies. This post details the process of extracting data from Contentful and transforming it into a static Markdown format.
Understanding Contentful Data Structure
Before migration, it's crucial to understand how your blog data is structured in Contentful. Key fields typically include:
- Title: The post's title.
- Published Date: The date the post was published.
- Slug: A URL-friendly identifier for the post.
- Description/Excerpt: A brief summary of the post.
- Tags: Categories or keywords associated with the post.
- Content: The main body of the post, often in a rich text format.
Fetching Data from Contentful
Contentful provides a Content Delivery API to retrieve your content. You'll need your Space ID and an Access Token.
GET https://cdn.contentful.com/spaces/{SPACE_ID}/environments/master/entries?access_token={ACCESS_TOKEN}&content_type=pageBlogPost&order=-fields.publishedDate&select=fields.title,fields.publishedDate,fields.slug,fields.shortDescription,fields.content,fields.tags
Important Note on Content: Contentfulのリッチテキストフィールドは、プレーンなMarkdownやHTMLではなく、特定のJSON形式でコンテンツを返します。contentフィールドがプレーンテキストの場合、埋め込み画像や複雑な書式設定が含まれていない可能性があります。リッチテキストの場合、通常はHTMLやMarkdownに変換するためにライブラリ(例:@contentful/rich-text-html-renderer)が必要になります。私たちの場合、contentフィールドはプレーンテキストであったため、変換が簡素化されました。
Converting to Markdown Format
Each Contentful entry needs to be converted into a Markdown file with a YAML front matter。
Front Matter Structure: The front matter is a block of YAML at the beginning of your Markdown file, containing metadata.
title: "Your Post Title"
date: "YYYY-MM-DD"
description: "A brief description of your post."
tags: ["tag1", "tag2"]
---
Content Body: The main content of your post follows the front matter. If your Contentful content is already plain textであれば、そのまま使用できます。適切な改行が維持されていることを確認してください。
Automating the Migration
Node.jsスクリプトでこのプロセスを自動化できます。
- Contentfulから関連するすべてのエントリを取得します。
- 各エントリを反復処理します。
- フロントマターのデータを抽出します。
- ファイル名には
slugを使用します。 - Markdownファイルの内容(フロントマター+本文)を構築します。
- 目的のディレクトリ(例:
src/app/blog/en/)にファイルを書き込みます。
スクリプトの例(概念):
const fs = require('fs');
const path = require('path');
// ... (Contentfulデータ配列) ...
posts.forEach(post => {
const frontMatter = `---
title: ${JSON.stringify(post.frontMatter.title)}
date: ${post.frontMatter.date}
description: ${JSON.stringify(post.frontMatter.description)}
tags: [${post.frontMatter.tags.map(tag => JSON.stringify(tag)).join(', ')}]
---
`;
const markdownContent = `${frontMatter}
${post.content}`;
const filePath = path.join(postsDirectory, post.lang, `${post.slug}.md`);
fs.writeFileSync(filePath, markdownContent, 'utf8');
});
画像の処理
Contentfulのリッチテキストフィールドに埋め込まれた画像は、テキストコンテンツの一部ではありません。それらは別のアセットです。
- 課題: APIを介して画像を直接取得し、Markdownに埋め込むには、リッチテキストJSONの解析、アセットURLの取得、画像のダウンロード、そしてMarkdownの更新が必要です。
- 実用的な解決策: よりシンプルなセットアップの場合、画像を手動でダウンロードして
public/imagesディレクトリに配置し、Markdownで相対パスを使用して参照できます(例:)。
これらの手順に従うことで、ブログコンテンツを動的なCMSから静的なファイルベースのシステムに正常に移行し、Next.jsのデプロイを簡素化できます。