静的HTMLサイトのトップページを CMS 化する

「お知らせ」が CMS で管理できるようになったことで、サイト担当者が自分で更新できる基本的な仕組みが整いました。さらに、静的 HTML サイトにあったフォームについても CMS 側に実装し、一旦はここで納品を済ませたことにします。

その後、サイトのオーナーは日々のお知らせの更新が自分でできるようになると、「トップページの他の部分も自分で編集できるようにしたい」と要望するようになりました。

そこで次のステップとして、トップページの「お知らせ」以外の要素も CMS 化していく ことになります。

10. ヘッダー & フッターの情報を CMS 化する

トップページには「お知らせ」以外にも、サイト全体で共通して表示されるヘッダー部分(サイト名・キャッチコピー)とフッター部分(SNS アイコン・コピーライト) があります。これらを CMS 化することで、管理画面から一元的に更新できるようになります。

SCR-20250919-scmy

10-1. サイトタイトルの CMS 化(グローバル変数)

サイトタイトルについては、CMS 側で設定している ブログ名 をそのまま利用できるようにします。

a-blog cms には「グローバル変数」と呼ばれる仕組みがあり、サイト全体で共通して利用できる値を %{...} の形で呼び出すことができます。ブログ名は %{BLOG_NAME} で出力可能です。

これにより、管理画面からブログ名を変更すれば、ヘッダー部分にも自動的に反映されるようになります。

スマホの時のヘッダー部分(修正前 → 修正後)

<!-- 修正前 -->
<h1 class="text-lg font-bold text-gray-800 tracking-wider">
    <a href="#home">SAMPLEPLE</a>
</h1>

<!-- 修正後 -->
<h1 class="text-lg font-bold text-gray-800 tracking-wider">
    <a href="#home">%{BLOG_NAME}</a>
</h1>

PC の時のサブカラム ヘッダー部分(修正前 → 修正後)

<!-- 修正前 -->
<div class="mb-16">
    <div class="text-2xl font-bold text-white tracking-wider">
        <a href="#home">SAMPLEPLE</a>
    </div>
    <p class="text-sm text-gray-400 mt-2">
        静的HTMLからCMS化するための<br>サンプルHTML
    </p>
</div>

<!-- 修正後 -->
<div class="mb-16">
    <div class="text-2xl font-bold text-white tracking-wider">
        <a href="#home">%{BLOG_NAME}</a>
    </div>
    <p class="text-sm text-gray-400 mt-2">
        静的HTMLからCMS化するための<br>サンプルHTML
    </p>
</div>

ブログ名は管理画面の ブログ管理 で変更できます。

SCR-20250919-sjxe

↑ 「名前」の入力欄に設定されている内容が %{BLOG_NAME} として反映されます。

これにより、クライアントが管理画面でブログ名を変更するだけで、ヘッダー部分のサイトタイトルにも自動的に反映 されるようになります。

10-2. キャッチコピーの CMS 化(ブログフィールド)

サイトタイトルに続いて、キャッチコピーも管理画面から更新できるようにします。

ブログフィールドとは?

a-blog cms では、ブログ(サイト全体の単位)に紐づいたカスタムフィールドを「ブログフィールド」と呼びます。

記事やカテゴリにカスタムフィールドを持たせられるのと同じように、ブログ自体にも任意のフィールドを追加できる仕組み です。これにより、キャッチコピーのように サイト全体で共通する情報 を柔軟に管理することができます。

カスタムフィールド用ファイル field.html の作成

ブログのカスタムフィールドの作成するには、themes/sample/admin/blog というディレクトリ(フォルダ?)を作ります。そして、themes/sample/admin/blog/field.html というファイルを作りましょう。

カスタムフィールドメーカー

次に field.html の中に記述するフォームの HTML を作っていきます。この時に利用するのが「カスタムフィールドメーカー」というカスタムフィールド作成のための補助ツールになります。

  • http://localhost/bid/1/admin/customfield_maker/

SCR-20250919-solq

管理画面 の 一番左の黒いアイコンが並ぶメニューの一番下にあるスパナのアイコンをクリックすると管理者用の情報リンクが用意されています。

その一番上にある カスタムフィールドメーカー を選択してください。

SCR-20250919-spce

フィールドの設定

次のように入力します。

タイプタイトルフィールド
テキストエリアサイト説明文site_description

入力後、(生成)ボタンをクリックすると、下部に コードプレビューエリア が表示されます。 自動生成された HTML が表示されるので、(生成コードをコピー)ボタンをクリックし、その内容を /themes/sample/admin/blog/field.html に貼り付けます。

管理画面での確認

では、管理画面に項目が追加されたかを確認してみましょう。

管理画面 > ブログ管理 > カスタム設定 タブ にアクセスすると、新しく「サイト説明文」という入力欄が追加されています。

ここで入力した内容は、テンプレート内で {site_description} と書くことで呼び出せます。

テンプレートの修正例

<!-- 修正前 -->
<div class="mb-16">
    <div class="text-2xl font-bold text-white tracking-wider">
        <a href="#home">SAMPLEPLE</a>
    </div>
    <p class="text-sm text-gray-400 mt-2">
        静的HTMLからCMS化するための<br>サンプルHTML
    </p>
</div>

<!-- 修正後 -->
<div class="mb-16">
    <div class="text-2xl font-bold text-white tracking-wider">
        <a href="#home">%{BLOG_NAME}</a>
    </div>
    <!-- BEGIN_MODULE Blog_Field -->
    <p class="text-sm text-gray-400 mt-2">
        {site_description}[nl2br]
    </p>
    <!-- END_MODULE Blog_Field -->
</div>
ポイント
  • ブログフィールドで管理されているキャッチコピーは {site_description} 変数で表示
  • 変数はモジュールで囲まないと動作せず、今回は Blog_Field モジュールを利用
  • テキストエリアのデータには改行コードが含まれる可能性があり、改行コードは、校正オプションの [nl2br] を利用する

これで、ヘッダー部分の「サイト名」と「キャッチコピー」がブラウザの管理画面から更新可能になりました。

10-3. フッター部分の CMS 化(ブログフィールド)

ヘッダーと同様に、カスタムフィールドを追加します。

フィールドの設定

次のように入力します。

タイプタイトルフィールド
テキストXsns_x
テキストFacebooksns_facebook
テキストInstagramsns_instagram
テキストエリアフッターテキストsite_footer
<!-- BEGIN_MODULE Blog_Field -->
<ul class="flex space-x-4 mb-4">
    <!-- BEGIN x:veil -->
    <li>
        <a href="https://x.com/{sns_x}" class="text-gray-400 hover:text-white transition-colors">
            <span class="sr-only">X</span>
            <svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
        </a>
    </li><!-- END x:veil -->
    <!-- BEGIN facebook:veil -->
    <li>
        <a href="https://www.facebook.com/{sns_facebook}" class="text-gray-400 hover:text-white transition-colors">
            <span class="sr-only">Facebook</span>
            <svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path fill-rule="evenodd" d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z" clip-rule="evenodd"/></svg>
        </a>
    </li><!-- END facebook:veil -->
    <!-- BEGIN instagram:veil -->
    <li>
        <a href="https://www.instagram.com/{sns_instagram}" class="text-gray-400 hover:text-white transition-colors">
            <span class="sr-only">Instagram</span>
            <svg class="h-6 w-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path fill-rule="evenodd" d="M12 2c2.717 0 3.056.01 4.122.06 1.065.05 1.79.217 2.428.465.66.254 1.216.598 1.772 1.153a4.902 4.902 0 0 1 1.153 1.772c.247.637.415 1.363.465 2.428.047 1.066.06 1.405.06 4.122s-.013 3.056-.06 4.122c-.05 1.065-.218 1.79-.465 2.428a4.902 4.902 0 0 1-1.153 1.772 4.902 4.902 0 0 1-1.772 1.153c-.637.247-1.363.415-2.428.465-1.066.047-1.405.06-4.122.06s-3.056-.013-4.122-.06c-1.065-.05-1.79-.218-2.428-.465a4.902 4.902 0 0 1-1.772-1.153 4.902 4.902 0 0 1-1.153-1.772c-.247-.637-.415-1.363-.465-2.428C2.013 15.056 2 14.717 2 12s.013-3.056.06-4.122c.05-1.065.218-1.79.465-2.428a4.902 4.902 0 0 1 1.153-1.772A4.902 4.902 0 0 1 5.45 2.525c.637-.247 1.363-.415 2.428-.465C8.944 2.013 9.283 2 12 2Zm0 5a5 5 0 1 0 0 10 5 5 0 0 0 0-10Zm-7 5a7 7 0 1 1 14 0 7 7 0 0 1-14 0Z" clip-rule="evenodd"/></svg>
        </a>
    </li><!-- END instagram:veil -->
</ul>
<p class="text-xs text-gray-500">{site_footer}[nl2br]</p>
<!-- END_MODULE Blog_Field -->
</div>

ポイント

  • 今回も Blog_Field を利用
  • SNS の <li>..</li> は、<!-- BEGIN sns:veil --><!-- END sns:veil --> で囲む事で入力が無い時に <li>..</li> を削除することが可能
  • フッターテキストは、キャッチコピーと同様

コレで、ブログ管理 > カスタム設定 を確認すると、サイト全体の共通要素を一元管理できるようになりました。

SCR-20251012-pqhh

11. メインビジュアルを CMS 化する

トップページのメインビジュアル部分も CMS 化して、管理画面から画像とテキストを更新できるようにします。

前章 10. では ブログフィールド を使ってヘッダー情報を CMS 化しましたが、ここでは別のカスタムフィールドの仕組みである モジュールフィールド を使ってみます。

a-blog cms には、以下のように複数のカスタムフィールドが用意されています。それぞれ保存される場所が異なり、用途に応じて使い分けが可能です。

種類保存対象管理画面パス
ブログフィールドサイト全体admin/blog/field.html
カテゴリーフィールド各カテゴリーadmin/category/field.html
エントリーフィールド各記事admin/entry/field.html
ユーザーフィールド各ユーザーadmin/user/field.html
モジュールフィールド各モジュールIDadmin/module/field.html

この中の モジュールフィールド は、モジュール(例:Entry_Body や Entry_Summary など)ごとに独自のカスタムフィールドを設定できる仕組みです。今回はこの機能を使って、トップページのメインビジュアルを管理画面から更新できるようにします。

11-1. モジュールID を作成

まずはモジュールフィールドの設定単位となる モジュールID を作成します。

  1. 管理画面 > モジュールID にアクセスします。
  2. (モジュール作成)をクリックし、以下の内容を入力します。
項目設定内容
モジュールモジュールフィールド (Module_Field)
モジュールIDmain_visual
名前メインビジュアル

設定後、(作成)ボタンをクリックしてください。

11-2. ファイル を作成

ブログやエントリーのカスタムフィールドと同様に、モジュールフィールドもテンプレートファイルとして admin/module/ ディレクトリを配置します。

/themes/sample/
  └── admin/
      ├── blog/
      ├── entry/
      └── module/
         └── field.html (作成)

field.html に以下のように記述します。

@include("/admin/module/%{MODULE_ID}.html")

これにより、モジュールIDごとに異なるファイルを読み込むことができるようになります。 たとえば今回の main_visual モジュールIDの場合、次のような構成になります。

/themes/sample/
  └── admin/
      ├── blog/
      ├── entry/
      └── module/
         ├── field.html
         └── main_visual.html (作成)

こう設定することで、今回用意した「メインビジュアル」のモジュールIDの管理画面では、グローバル変数 %{MODULE_ID}main_visual に変換され最終的には main_visual.html が読み込まれることになります。

11-3. カスタムフィールドメーカー で項目を定義

次に、main_visual.html の中身を作ります。その際に便利なのが カスタムフィールドメーカー です。

タイプタイトルフィールド
テキストメインコピーmain_copy
テキストサブコピーsub_copy
メディア背景画像main_image

生成ボタンをクリックするとコードプレビューが表示されるので、 出力されたフォームHTMLをコピーし、main_visual.html に貼り付けてください。

SCR-20251011-keui

モジュールフィールドは、モジュールIDの管理画面の「条件設定タブ」の隣にある「カスタム設定タブ」に表示されます。

11-4. 表示用テンプレートの修正

モジュールID と管理画面の設定が完了したら、最後に表示用テンプレート _top.html のメインビジュアル部分を修正します。

修正前のコード

<section id="home" class="relative h-[46rem]">
    <img src="/images/main_visual.jpg" alt="美味しそうな料理のメインビジュアル" class="w-full h-full object-cover">

    <div class="absolute inset-0 bg-black/50"></div>

    <div class="absolute inset-0 flex flex-col px-4">
        <div class="flex-grow-[2]"></div>

        <div class="flex-shrink-0 text-center">
            <p class="text-4xl sm:text-5xl lg:text-6xl font-extrabold tracking-tight text-white" style="text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.6);">
                感動を、一皿に込めて。
            </p>
            <p class="mt-6 max-w-2xl mx-auto text-lg sm:text-xl text-white/90" style="text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);">
                あなたの特別な瞬間を、最高の食体験で彩ります。
            </p>
        </div>

        <div class="flex-grow"></div>
    </div>
</section>

テキストのカスタムフィールドの場合には {main_copy}{sub_copy} 定義したフィールド名を { } で囲むだけでしたが、メディアのカスタムフィールドは main_image というフィールド名でカスタムフィールドメーカーで設定しますが、表示の際には {main_image@path}{main_image@alt} のように @ で追加属性がありますので注意ください。

こちらも カスタムフィールドメーカーの出力用コード を参考にしてください。

修正後のコード

<!-- 修正後 -->
<!-- BEGIN_MODULE Module_Field id="main_visual" -->
<section id="home" class="relative h-[46rem]">
    <img src="%{MEDIA_ARCHIVES_DIR}{main_image@path}" alt="{main_image@alt}" class="w-full h-full object-cover">

    <div class="absolute inset-0 bg-black/50"></div>

    <div class="absolute inset-0 flex flex-col px-4">
        <div class="flex-grow-[2]"></div>

        <div class="flex-shrink-0 text-center">
            <p class="text-4xl sm:text-5xl lg:text-6xl font-extrabold tracking-tight text-white" style="text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.6);">
                {main_copy}
            </p>
            <p class="mt-6 max-w-2xl mx-auto text-lg sm:text-xl text-white/90" style="text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.6);">
                {sub_copy}
            </p>
        </div>

        <div class="flex-grow"></div>
    </div>
</section>
<!-- END_MODULE Module_Field -->

11-5. モジュールフィールドの入力画面をモーダル表示

モジュールID のカスタムフィールドは、 管理画面 > モジュールID 一覧ページ > 該当モジュールID 詳細ページ > カスタム設定 タブ と、通常は 4 回クリックして開く必要があります。

毎回この手順を踏むのは少し手間がかかるため、トップページの該当エリアから直接モーダルで編集画面を開けるように してみましょう。

編集リンクを追加する

先ほど作成した Module_Field の <section id="home" ... の直下に、以下のインクルード文を追加してください。

@include("/include/edit/module-custom.html",{"hash":"#acms_box3"})

SCR-20251011-kjmw

このコードを追加すると、メインビジュアルコンテンツの右上に「編集する」というリンクが表示されます。

SCR-20251011-kkwg

ポイント

@include("/include/edit/module-custom.html") は、a-blog cms に標準で用意されている管理画面ショートカット機能 を呼び出す仕組みです。

a-blog cms は、カスタムフィールドをはじめ、管理画面の UI についてもカスタマイズでき、運用者のことを考えた UI を追加実装できる点も特徴にあげられます。

12. About コンテンツを CMS 化する

前章の 11. メインビジュアルを CMS 化する と同様の手順で、About セクションも モジュールフィールド を利用して CMS 化していきます。

これにより、運用者が管理画面から自由にテキストや画像を変更できるようになります。

変更前

<section id="about" class="py-14 sm:py-20 bg-white">
    <div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
        <h2 class="text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl mt-2">About</h2>
        <p class="mt-4 text-2xl font-semibold text-sky-600">最高の食体験を、すべての人へ。</p>
        <p class="mt-6 text-lg leading-8 text-gray-600">
            私たちは、厳選された食材と革新的なアイデアを融合させ、心に残るダイニング体験を創造します。お客様一人ひとりの特別な日を、最高の料理とサービスで彩ることが私たちの使命です。
        </p>
    </div>
</section>

前章の手順を応用して、以下の項目をモジュールフィールドとして管理できるようにしてください。

タイプタイトルフィールド
テキストセクションタイトルabout_title
テキストサブタイトルabout_subtitle
テキストエリア説明文about_text

作業内容は 第11章と同じ手順 になりますので、ここではあえて詳細な説明は省略します。

ぜひ自分の手で設定を進めてみて、モジュールフィールドの仕組みをもう一度確認してみましょう。

13. ヘッダー・フッターを共通化してテンプレートを整理する

これまで、トップページのヘッダーやフッターを CMS 化してきました。 しかし、News や Contact ページでは、まだ静的 HTML のまま同じ構造が残っています。

このままでは、デザイン変更や CMS 情報の修正を行うたびに複数ページを更新する必要があり、保守性が低下します。

ここでは、ヘッダーとフッターをインクルードファイルとして共通化 し、全ページから同じテンプレートを読み込むようにします。

13-1. include ディレクトリの作成

テーマディレクトリ内に共通パーツをまとめるための include ディレクトリを作成します。

/themes/sample/
  ├── _top.html 
  ├── admin/
  ├── contact/
  ├── css/
  ├── images/
  ├── include (追加)
  ├── news/
  └── service/

include ディレクトリには、ヘッダーやサイドカラムなどの共通パーツを配置します。

今回のサイト構成では、一般的な「フッター」よりも 右カラム(aside) がグローバルな情報をまとめる役割を果たしているため、footer.html の代わりに aside.html を用意することにします。

13-2. 共通パーツのファイルを作成

include ディレクトリに以下のファイルを作成します。

/themes/sample/include/
  ├── header.html
  └── aside.html

まずは、_top.html の <header> 部分を include/header.html に、<aside> 部分を include/aside.html にコピーします。

header.html

<header class="fixed top-0 left-0 right-0 z-30 flex items-center justify-between h-16 px-4 bg-white shadow-md lg:hidden">
    <button
        @click="sidebarOpen = !sidebarOpen"
        class="p-2 -ml-2"
        aria-controls="sidebar"
        :aria-expanded="sidebarOpen">
        <span class="sr-only">サイトバーを開く</span>
        <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
        </svg>
    </button>

    <h1 class="text-lg font-bold text-gray-800 tracking-wider">
        <a href="#home">%{BLOG_NAME}</a>
    </h1>

    <a href="#contact" class="px-3 py-1.5 text-sm font-semibold text-white bg-sky-500 rounded-md hover:bg-sky-600 transition-colors">
        Contact
    </a>
</header>

aside.html(抜粋)

<aside
    id="sidebar"
    class="fixed top-0 left-0 h-screen w-72 bg-gray-900 flex flex-col justify-between p-8 transform -translate-x-full transition-transform duration-300 ease-in-out z-50 lg:translate-x-0 lg:shadow-none"
    :class="{ 'translate-x-0 shadow-2xl': sidebarOpen }">

    <div>
        <div class="mb-16">
            <div class="text-2xl font-bold text-white tracking-wider">
                <a href="#home">%{BLOG_NAME}</a>

... (略) ...

    <p class="text-xs text-gray-500">{site_footer}[nl2br]</p>
    <!-- END_MODULE Blog_Field -->
    </div>
</aside>

また、<header> 部分は、インクルード文に置き換え、<aside> も同様に書き換えてください。

@include("/include/header.html")

13-3. 各テンプレートでインクルード

_top.html 以外に、これまでテンプレート化したファイルは、以下の3つになります。

  • news/index.html
  • news/_entry.html
  • contact/index.html

これらも修正していく必要があります。news/index.html<header> が同じであれば、@include("/include/header.html") に置き換えてください。

今回のサイトは、しっかり SEO対策を考え見出し構成を考えているサイト作りを考えて実装されており、トップページと中ページで見出しが変わっていることが比較してみると分かります。

_top.html

<h1 class="text-lg font-bold text-gray-800 tracking-wider">
    <a href="#home">%{BLOG_NAME}</a>
</h1>

news/index.html

<p class="text-lg font-bold text-gray-800 tracking-wider">
    <a href="/#home">SAMPLEPLE</a>
</p>

修正前 include/header.html

<h1 class="text-lg font-bold text-gray-800 tracking-wider">
    <a href="#home">%{BLOG_NAME}</a>
</h1>

修正後 include/header.html

この場合の時に表示する、それ以外の時には BEGIN 〜 END の部分を消すことができる タッチモジュール というモジュールが色々用意されています。

今回は、トップページの時 Touch_Top と、それ以外の時の Touch_NotTop で分岐する設定を

<!-- BEGIN_MODULE Touch_Top -->
<h1 class="text-lg font-bold text-gray-800 tracking-wider">
    <a href="#home">%{BLOG_NAME}</a>
</h1>
<!-- END_MODULE Touch_Top -->
<!-- BEGIN_MODULE Touch_NotTop -->
<p class="text-lg font-bold text-gray-800 tracking-wider">
    <a href="/#home">%{BLOG_NAME}</a>
</p>
<!-- END_MODULE Touch_NotTop -->

aside.html のナビゲーションを調整

include/aside.html に記述されている <nav role="navigation"> の設定は、トップページではページ遷移を行わずにスムーズスクロールで移動し、その他のページではトップページへ遷移して対象セクションにスクロールする という動作になっています。

また、現在表示中のページを示すための アクティブクラス の指定もトップページとそれ以外で異なるため、分岐処理を追加して調整します。

<!-- BEGIN_MODULE Touch_Top -->
<nav role="navigation">
    <ul class="space-y-5 text-lg">
        <li><a href="/#home" @click="sidebarOpen = false"
                :class="activeLink === '#home' ? 'text-white font-semibold border-l-2 border-sky-400 pl-4' : 'text-gray-400 hover:text-white transition-colors'"
                :aria-current="activeLink === '#home' ? 'page' : false">Home</a></li>
        <li><a href="/#about" @click="sidebarOpen = false"
                :class="activeLink === '#about' ? 'text-white font-semibold border-l-2 border-sky-400 pl-4' : 'text-gray-400 hover:text-white transition-colors'"
                :aria-current="activeLink === '#about' ? 'page' : false">About</a></li>
        <li><a href="/#service" @click="sidebarOpen = false"
                :class="activeLink === '#service' ? 'text-white font-semibold border-l-2 border-sky-400 pl-4' : 'text-gray-400 hover:text-white transition-colors'"
                :aria-current="activeLink === '#service' ? 'page' : false">Service</a></li>
        <li><a href="/#news" @click="sidebarOpen = false"
                :class="activeLink === '#news' ? 'text-white font-semibold border-l-2 border-sky-400 pl-4' : 'text-gray-400 hover:text-white transition-colors'"
                :aria-current="activeLink === '#news' ? 'page' : false">News</a></li>
        <li><a href="/#contact" @click="sidebarOpen = false"
                :class="activeLink === '#contact' ? 'text-white font-semibold border-l-2 border-sky-400 pl-4' : 'text-gray-400 hover:text-white transition-colors'"
                :aria-current="activeLink === '#contact' ? 'page' : false">Contact</a></li>
    </ul>
</nav>
<!-- END_MODULE Touch_Top -->
<!-- BEGIN_MODULE Touch_NotTop -->
<nav role="navigation">
    <ul class="space-y-5 text-lg">
        <li><a href="/#home" @click="sidebarOpen = false" class="text-gray-400 hover:text-white transition-colors">Home</a></li>
        <li><a href="/#about" @click="sidebarOpen = false" <!-- BEGIN_IF [%{CCD}/eq/about] -->class="text-white font-semibold border-l-2 border-sky-400 pl-4" aria-current="page"<!-- ELSE -->class="text-gray-400 hover:text-white transition-colors"<!-- END_IF-->>About</a></li>
        <li><a href="/#service" @click="sidebarOpen = false" <!-- BEGIN_IF [%{CCD}/eq/service] -->class="text-white font-semibold border-l-2 border-sky-400 pl-4" aria-current="page"<!-- ELSE -->class="text-gray-400 hover:text-white transition-colors"<!-- END_IF-->>Service</a></li>
        <li><a href="/#news" @click="sidebarOpen = false" <!-- BEGIN_IF [%{CCD}/eq/news] -->class="text-white font-semibold border-l-2 border-sky-400 pl-4" aria-current="page"<!-- ELSE -->class="text-gray-400 hover:text-white transition-colors"<!-- END_IF-->>News</a></li>
        <li><a href="/#contact" @click="sidebarOpen = false" <!-- BEGIN_IF [%{CCD}/eq/contact] -->class="text-white font-semibold border-l-2 border-sky-400 pl-4" aria-current="page"<!-- ELSE -->class="text-gray-400 hover:text-white transition-colors"<!-- END_IF-->>Contact</a></li>
    </ul>
</nav>
<!-- END_MODULE Touch_NotTop -->

Touch_Top / Touch_NotTop は、トップページとそれ以外のページで出力内容を切り替えるための a-blog cms の条件分岐をするためのタッチモジュールです。トップページでは Alpine.js の activeLink を利用して現在位置に応じて動的にクラスを切り替えます。中ページでは CMS 側の変数 %{CCD}(現在のカテゴリーコード)を利用し、表示中のカテゴリに応じて aria-current="page" とスタイルを付与します。これにより、トップページではスムーズスクロール、それ以外のページでは通常遷移+アクティブ強調を実現します。