Migrating Blog Content: From Contentful to Static Markdown in Next.js

August 12, 2025 development notes Next.js Contentful Markdown Data Migration

Development Image

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:

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スクリプトでこのプロセスを自動化できます。

  1. Contentfulから関連するすべてのエントリを取得します。
  2. 各エントリを反復処理します。
    • フロントマターのデータを抽出します。
    • ファイル名には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のリッチテキストフィールドに埋め込まれた画像は、テキストコンテンツの一部ではありません。それらは別のアセットです。

これらの手順に従うことで、ブログコンテンツを動的なCMSから静的なファイルベースのシステムに正常に移行し、Next.jsのデプロイを簡素化できます。

← Previous Entry: Setting Up a Next.js Blog: Navigating Initial Git & Deployment HurdlesNext Entry: Mastering Next.js Deployment on Cloudflare Pages: Overcoming Edge Runtime & Static Generation Challenges
← Back to Blog List