6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

microCMSを「HTML置き場」にしてAI生成記事をNext.jsで表示してみた

Last updated at Posted at 2025-12-03

要約: Genspark等のAIツールが生成した完成形HTMLとCSSを、microCMSのテキストエリアにそのまま格納し、Next.js App Routerで表示する実装パターンを紹介します。CSSスコーピングでスタイル衝突を防ぎつつ、記事ごとに異なるデザインを実現できます。

この記事でわかること

  • microCMSにAI生成HTML(Genspark等)を「そのまま格納」するアプローチ
  • Next.jsでCSSスコーピングを使ってスタイル衝突を防ぐ実装
  • このアプローチのメリット・デメリットと適用判断

はじめに

microCMSをはじめとするヘッドレスCMSの一般的な使い方といえば、構造化されたデータをAPIで取得し、フロントエンドで整形して表示するというパターンです。

たとえばブログ記事なら、タイトル・本文・サムネイル画像・カテゴリなどを別々のフィールドに保存し、Next.jsなどのフロントエンドで見た目を組み立てるかと思います。

【一般的なmicroCMSの使い方】

microCMS側:
  - タイトル: テキストフィールド
  - 本文: リッチエディタ
  - サムネイル: 画像フィールド
  - カテゴリ: コンテンツ参照

フロントエンド側:
  - APIでデータ取得
  - コンポーネントで整形・表示

しかし、あるメディアサイトの開発で、この「常識」とは真逆のアプローチを取る機会がありました。

AIが生成した完成形のHTMLとCSSを、そのままmicroCMSに格納する

という方法です。

本記事では、このアプローチに至った背景、具体的な実装方法、そしてメリット・デメリットを紹介します。


背景: AIが生成したHTMLをそのままNext.jsのWebアプリに表示させたい

あるメディアサイトの開発で、以下のような要望が出てきました。

  1. Gensparkを使って図解入りの記事を自由に生成したい(サイトのトンマナは維持しつつ)
  2. エンジニアの手を借りずに記事を公開したい(デプロイ作業なしで)
  3. 既存のNext.jsアプリにスムーズに組み込みたい

これを実現する方法を検討した結果、以下の流れにたどり着きました。

Gensparkが生成したHTMLを、CMSからAPI経由で取得してそのまま表示できないか?

社内で利用実績のあるmicroCMSなら、既存のNext.jsアプリに少ない工数で組み込めるかも!

Gensparkが生成する「完成形のHTML」

Gensparkは、プロンプトを入力するだけでデザイン込みの完成形HTMLを生成してくれます。

<!-- Gensparkが生成するHTMLの例 -->
<div class="article-container">
    <span class="category-badge">カテゴリ名</span>
    <h1>記事タイトル</h1>
    <p class="lead-text">リード文がここに入ります...</p>
    <!-- 以下、本文が続く -->
</div>

このHTMLには、対応するCSSも含まれています。

/* Gensparkが生成するCSSの例 */
:root { --primary-color: #2563eb; }
.article-container { max-width: 800px; margin: 0 auto; }
.category-badge { background: var(--primary-color); color: white; }

方針: HTMLとCSSをそのままmicroCMSに格納する

microCMSには「テキストエリア」というフィールドタイプがあり、複数行のプレーンテキストを格納できます。少し強引にも思えるかもしれませんが、これを使えばHTMLもCSSもそのまま保存できると考えました。

【実装方針】

Genspark生成HTML → microCMSのテキストエリア(そのまま格納)
Genspark生成CSS → microCMSのテキストエリア(そのまま格納)
    ↓
Next.jsで取得してそのまま表示

一般的なヘッドレスCMSの使い方(構造化データを管理してフロントで整形)とは異なりますが、「完成形をそのまま表示する」という目的には、このシンプルなアプローチが最適でした。


AI生成HTML埋め込み: 他のアプローチとの比較

AI生成HTMLを既存サイトに埋め込む方法はいくつかあります。今回のアプローチを選んだ理由を、他の選択肢との比較で説明します。

アプローチ メリット デメリット 採用判断
<style>タグ + スコーピング 実装シンプル、SEO影響なし @media内のセレクタは未対応 採用
Shadow DOM 完全なスタイル分離 SEOに悪影響、実装が複雑 不採用
iframe 完全な分離 高さ調整が困難、SEOに悪影響 不採用
CSS Modules Next.jsとの親和性が高い 動的CSSには不向き 不採用

採用したアプローチの制限事項

今回採用した「<style>タグ + スコーピング」には以下の制限があります。

  • @media クエリ内のセレクタはスコープされない
  • 複雑なセレクタ(:has(), :where() など)は未対応の場合がある
  • ネストされたat-rule(@supports 内の @media など)は考慮していない

これらの制限は、AI生成CSSの傾向(シンプルなセレクタが多い)を踏まえ、実用上は問題ないと判断しました。より厳密なスコーピングが必要な場合は、PostCSSプラグインなどの利用を検討してください。


microCMSスキーマ設計: HTMLとCSSを別々のフィールドに格納

APIスキーマの構成

記事コンテンツのAPIスキーマを以下のように設計しました。

フィールドID 表示名 種類 用途
title 記事タイトル テキストフィールド SEO・OGP用
category カテゴリー コンテンツ参照 フィルタリング用
author 著者名 テキストフィールド メタ情報用
publishedAt 公開日 日時 メタ情報用
thumbnail サムネイル画像 画像 一覧表示・OGP用
aiGeneratedHtml AI生成HTML テキストエリア 記事本文HTML
aiGeneratedStyle AI生成スタイル テキストエリア 記事専用CSS
tableOfContents 目次 繰り返し SEO description用

ポイントは以下の2つです。

  1. aiGeneratedHtml: AI生成HTMLをそのまま格納
  2. aiGeneratedStyle: AI生成CSSをそのまま格納

なぜHTMLとCSSを分離したか

HTMLとCSSを別フィールドにした理由は、CSSのスコーピング(後述) を行うためです。

AI生成CSSには :rootbody などグローバルに影響するセレクタが含まれており、そのまま適用するとサイト全体のスタイルが崩れてしまいます。

CSSを別フィールドに分離することで、Next.js側でスコーピング処理を挟んでから適用できるようになります。


Next.js App Routerでの表示実装

CSSスコーピングの必要性

AI生成CSSをそのまま <style> タグで挿入すると、大きな問題が発生します。

/* AI生成CSSの例 */
:root { --primary-color: #2563eb; }
body { font-family: "Inter", sans-serif; }
* { margin: 0; padding: 0; }

これらのセレクタはサイト全体に影響してしまいます。ヘッダーやフッター、他のページのスタイルまで書き換わってしまうのです。

CSSスコーピング関数の実装

解決策として、CSSセレクタを特定のクラス配下にスコープする関数を実装しました。

/**
 * CSSをスコープ化する関数
 * セレクタを指定されたクラス配下に限定する
 */
function scopeCSS(css: string, scopeClass: string): string {
  return css
    .split('\n')
    .map((line) => {
      const trimmed = line.trim();

      // 空行・コメント行はそのまま
      if (!trimmed || trimmed.startsWith('/*') || trimmed.startsWith('*')) {
        return line;
      }

      // セレクタの行({ を含む)を処理
      if (trimmed.includes('{')) {
        let selector = trimmed.substring(0, trimmed.indexOf('{')).trim();

        // :root と body はスコープクラスに置換
        if (selector === ':root' || selector === 'body') {
          selector = `.${scopeClass}`;
        }
        // @media などのat-ruleはそのまま
        else if (selector.startsWith('@')) {
          return line;
        }
        // 通常のセレクタにはプレフィックスを追加
        else {
          selector = `.${scopeClass} ${selector}`;
        }

        return line.substring(0, line.indexOf(trimmed)) + selector + ' {';
      }

      return line;
    })
    .join('\n');
}

この関数により、以下のように変換されます。

/* 変換前 */
:root { --primary-color: #2563eb; }
body { font-family: "Inter", sans-serif; }
.article-container { max-width: 800px; }

/* 変換後 */
.ai-content-wrapper { --primary-color: #2563eb; }
.ai-content-wrapper { font-family: "Inter", sans-serif; }
.ai-content-wrapper .article-container { max-width: 800px; }

ページコンポーネントの実装

Next.js App Routerでの実装例です。

// app/articles/[id]/page.tsx

export default async function ArticlePage({
  params
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params;

  // microCMSから記事データを取得
  const article = await getArticle(id);

  // CSSをスコープ化
  const scopedStyles = scopeCSS(article.aiGeneratedStyle, 'ai-content-wrapper');

  return (
    <div className="min-h-screen bg-white">
      {/* スコープ化したCSSを動的に挿入 */}
      <style>
        {scopedStyles}
      </style>

      {/* AI生成HTMLをレンダリング */}
      <div
        className="ai-content-wrapper"
        dangerouslySetInnerHTML={{ __html: article.aiGeneratedHtml }}
      />
    </div>
  );
}

この実装により、記事ごとに完全に異なるデザインを持つことが可能になります。通常のCMSでは「サイト全体で統一されたデザイン」になりますが、このアプローチでは各記事が独自のデザインを持てるという特徴があります。


メリット・デメリット

メリット

  • 運用効率の向上: AI生成 → HTMLとCSSをコピペ → 完了。分解・再構築の手間がない
  • デザインの自由度: 記事ごとに異なるデザインを適用可能。特集ページやキャンペーンページに有効
  • AIの進化に追従しやすい: 「HTMLとCSSを格納する」構造は変わらないため、新しいAIツールへの移行が容易

デメリット

  • セキュリティへの配慮: dangerouslySetInnerHTML を使用するため、信頼できるソースからのみHTMLを受け入れる運用が必要
  • SEO対応の工夫: メタデータ用フィールド(タイトル、目次など)を別途用意し、generateMetadata で動的に設定する必要がある
  • 検索・フィルタリングの制限: 構造化された検索(「この見出しを含む記事」など)は難しくなる

まとめ

本記事では、microCMSを「HTML置き場」として使い、AI生成記事をNext.jsで表示する実装パターンを紹介しました。

ポイント:

  1. AI生成の完成形HTMLとCSSを、それぞれテキストエリアに格納
  2. CSSはスコーピング関数で処理してから適用
  3. 記事ごとに異なるデザインを実現可能

このアプローチが適しているケース:

  • AIでコンテンツを量産したい
  • 記事ごとに異なるデザインが必要
  • 特集ページ・キャンペーンページを効率的に作りたい

適していないケース:

  • コンテンツの構造化検索が必要
  • 統一されたデザインシステムを維持したい

ヘッドレスCMSの「構造化データを管理する」という一般的な使い方とは異なりますが、AI生成コンテンツを扱う場面では有効なアプローチです。

「microCMSは何でも格納できる」 という柔軟性を活かした、新しいCMS活用パターンとして参考になれば幸いです。


参考

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?