SWELL カスタマイズの WP-CLI + Python 自動化 — カラー10色 + グローバルナビを 30秒で揃える (2026年版)

SWELL のカスタマイザは UI が直感的で、初心者でも迷いません。ただ、AI × ソロ起業の前提だと 3〜4個の WP サイトを並行運用 することが確定しているので、毎回同じカラーパレットとナビを UI でクリックして設定するのは時間が惜しい。

ここでは SWELL のカラー10色とグローバルナビ (ホーム / プロフィール / お問い合わせ) を WP-CLI + Python で 30秒で揃える 実装ログを公開します。前回の Contact Form 7 自動化と同じ流儀の続編です。

目次

目次

  1. なぜ SWELL カスタマイザの自動化が効くのか
  2. theme_mod の正体 — どこに保存されているか
  3. setup_swell_basic.py — カラー10色を一括投入
  4. setup_swell_navigation.py — グローバルナビを idempotent に組み立てる
  5. 実行ログと所要時間
  6. 次のサイトに使い回すときのカスタマイズ

1. なぜ SWELL カスタマイザの自動化が効くのか

SWELL のカスタマイズで、サイトごとに必ず触る箇所はだいたい固定です:

  • カラーパレット (メイン / リンク / フッター背景 / ヘッダー背景 など 10色弱)
  • フッターコピーライト
  • グローバルナビゲーション (ホーム / プロフィール / お問い合わせ)
  • WordPress 標準のサンプルページ (slug=sample-page) の削除

UI で 1個ずつクリックすると 1サイトあたり 30〜45分。3サイト目に入る頃には飽きます。

Python + WP-CLI で書いてしまえば、1サイトあたり 30秒。差は60〜90倍。

2. theme_mod の正体 — どこに保存されているか

SWELL のカラー設定は WordPress の theme_mod という仕組みで保存されています。実体は wp_options テーブルの 1行:

option_name: theme_mods_swell_child
option_value: a:24:{...PHP serialized array of all customizer settings...}

すべてのカスタマイザー設定 (カラー・フォント・フッター文言など) がこの 1つの serialized array に詰め込まれている。これを直接 SQL で書き換えると serialize の整合性が壊れるので、WP-CLI の wp theme mod set で 1キーずつ書く のが安全です。

WP-CLI の theme mod set は、PHP の set_theme_mod() を経由します。これは serialize の整合性を保ちつつ、キャッシュ無効化や hooks の発火もすべて WP 流儀で行います。

3. setup_swell_basic.py — カラー10色を一括投入

ピクセルアートトーン (夕焼け + 東京タワー基準) のカラーセットを、テーマカスタマイザに 10キー投入します。

"""SWELL の基本カラー設定を一括投入する。"""
import json
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

from core.lib.automation.wp_cli import WPCLIClient


SWELL_BASIC_COLORS: dict[str, str] = {
    "color_main":         "#E76F51",  # メイン: 夕焼けオレンジ
    "color_text":         "#2B2B2B",  # 本文: 墨色
    "color_link":         "#2A9D8F",  # リンク: ティール
    "color_bg":           "#FFFFFF",  # ページ背景: 白
    "color_sub_bg":       "#FAF3E0",  # サブ背景: クリーム
    "color_sub_text":     "#2B2B2B",  # サブ文字
    "color_header_bg":    "#FFFFFF",  # ヘッダー背景
    "color_header_text":  "#2B2B2B",  # ヘッダー文字
    "color_footer_bg":    "#264653",  # フッター背景: ダークネイビー
    "color_footer_text":  "#FAF3E0",  # フッター文字: クリーム
}


def main() -> None:
    wp = WPCLIClient()

    print("=== Setting SWELL basic colors ===")
    for key, value in SWELL_BASIC_COLORS.items():
        wp.theme_mod_set(key, value)
        print(f"  {key:<22} = {value}")

    # 自己検証 (theme_mods_swell_child を取り戻して全キー一致確認)
    mods = json.loads(wp.run("option", "get", "theme_mods_swell_child", "--format=json"))
    all_ok = all(mods.get(k) == v for k, v in SWELL_BASIC_COLORS.items())
    print("Result:", "ALL OK" if all_ok else "SOME MISMATCH")


if __name__ == "__main__":
    main()

ポイント

  • WPCLIClient.theme_mod_set(key, value) が SSH + wp theme mod set <key> <value> をラップ。実装は core/lib/automation/wp_cli.py 参照
  • 末尾の自己検証: SWELL の theme_mod のキー名は時々変わる (バージョンアップで color_link_hover が追加された等) ため、設定後に theme_mods_swell_child を JSON で取り戻して全キー一致を確認。一致しないキーがあれば即気づける
  • idempotent: 何度実行しても結果が同じ。既存値を上書きするだけ

カラーチョイスの背景

「夕焼けオレンジ + ティール + ダークネイビー + クリーム」は ai-shacho.com の世界観基準画像 (ピクセルアート風の AI 社員ダッシュボード) のトーンに揃えています。サイトごとに別パレットにしたい場合は、SWELL_BASIC_COLORS 辞書の値を差し替えるだけです。

4. setup_swell_navigation.py — グローバルナビを idempotent に組み立てる

カラーが入ったら次はナビ。標準サンプルページの削除 → グローバルナビ作成 → ホーム/プロフィール/お問い合わせを追加 → ヘッダーロケーションに割り当て、まで一気に進めます。

スクリプトの主要ロジック

GLOBAL_NAV_NAME = "グローバルナビ"
HOME_URL = "https://ai-shacho.com/"
PAGE_SLUGS_TO_ADD = ["profile", "contact"]
HEADER_LOCATIONS = ("header_menu",)  # PC用のみ。SP表示時はSWELLのハンバーガーが自動で同メニュー流用


def main() -> None:
    wp = WPCLIClient()

    # 1. Delete sample-page (idempotent)
    sample = json.loads(
        wp.run("post", "list", "--post_type=page", "--name=sample-page",
               "--fields=ID,post_title", "--format=json")
    )
    for p in sample:
        wp.run("post", "delete", str(p["ID"]), "--force")

    # 2. Fetch target pages by slug
    page_ids = get_pages_by_slugs(wp, PAGE_SLUGS_TO_ADD)

    # 3. Ensure global nav menu exists (create if not)
    nav_id = find_menu_id_by_name(wp, GLOBAL_NAV_NAME)
    if not nav_id:
        nav_id = int(wp.run("menu", "create", GLOBAL_NAV_NAME, "--porcelain").strip())

    # 4. Add menu items (idempotent: skip if already in menu)
    existing_items = json.loads(
        wp.run("menu", "item", "list", str(nav_id),
               "--fields=db_id,title,url,object_id,type", "--format=json")
    )
    existing_object_ids = {str(it.get("object_id")) for it in existing_items
                          if it.get("type") == "post_type"}
    existing_urls = {it.get("url") for it in existing_items
                     if it.get("type") == "custom"}

    if HOME_URL not in existing_urls:
        wp.run("menu", "item", "add-custom", str(nav_id), "ホーム", HOME_URL)

    for slug, pid in page_ids.items():
        if str(pid) not in existing_object_ids:
            wp.run("menu", "item", "add-post", str(nav_id), str(pid))

    # 5. Assign to header locations
    for loc in HEADER_LOCATIONS:
        wp.run("menu", "location", "assign", str(nav_id), loc)

idempotent 設計の要点

このスクリプトは 何度実行しても同じ結果 になるように作っています。

  • 削除: sample-page が既に削除済みなら何もしない (post listで該当なし)
  • メニュー作成: 既存メニューがあれば term_id だけ拾う、なければ新規作成
  • メニュー項目追加: 既存の object_id (固定ページの ID) と url (カスタムリンクの URL) を取得しておき、追加対象がすでにあればスキップ
  • ロケーション割り当て: wp menu location assign は冪等 (再実行しても同じ場所に割り当てられる)

これで、cron で毎日走らせても破壊的な変更が起きません。新しい固定ページを PAGE_SLUGS_TO_ADD に追加するだけで、次回実行時に自動的にメニュー反映されます。

header_menu だけにアサインしている理由

SWELL のヘッダーロケーションは header_menu (PC) と sp_head_menu / nav_sp_menu (SP) の 3つがあります。実際にスマホ表示で SWELL のハンバーガーメニューを開くと、PC の header_menu と同じ内容が自動で展開されます (テンプレ実装でフォールバックあり)。

なので PC 用の header_menu だけ割り当てれば、SP も自動でカバー されます。3つすべて割り当てると逆に重複表示が起きるサイトもあるため、最小限が安全です。

5. 実行ログと所要時間

両スクリプトを順次実行したログ:

$ python scripts/setup_swell_basic.py
=== Setting SWELL basic colors ===
  color_main             = #E76F51
  color_text             = #2B2B2B
  color_link             = #2A9D8F
  color_bg               = #FFFFFF
  color_sub_bg           = #FAF3E0
  color_sub_text         = #2B2B2B
  color_header_bg        = #FFFFFF
  color_header_text      = #2B2B2B
  color_footer_bg        = #264653
  color_footer_text      = #FAF3E0
Result: ALL OK

$ python scripts/setup_swell_navigation.py
=== 1. Deleting sample-page ===
  Deleted: サンプルページ (ID=2)
=== 2. Fetching pages to add to menu ===
  profile: ID=10
  contact: ID=12
=== 3. Ensuring 'グローバルナビ' menu ===
  Created: term_id=15
=== 4. Adding menu items ===
  Added custom: ホーム → https://ai-shacho.com/
  Added page: profile (ID=10)
  Added page: contact (ID=12)
=== 5. Assigning to header locations ===
  Assigned: header_menu

各ステップの所要:

ステップ 所要
カラー10色一括投入 約 8秒 (10 × ssh round-trip)
サンプルページ削除 約 1秒
グローバルナビ作成 + 3項目追加 約 5秒
ロケーション割り当て + 検証 約 2秒

合計 約 16秒。UI で 30〜45分かかる作業がほぼゼロ秒の体感になります。

6. 次のサイトに使い回すときのカスタマイズ

新しいサイトでこのスクリプトを使うときは 3つのファイルを差し替えます:

  1. core/lib/automation/wp_cli.pyDEFAULT_SSH_HOSTDEFAULT_WP_PATH (新サイト用 ssh ホスト名・新サイトの public_html パス)
  2. scripts/setup_swell_basic.pySWELL_BASIC_COLORS 辞書 (サイトごとに色を変えたい場合)
  3. scripts/setup_swell_navigation.pyHOME_URL (新ドメイン), PAGE_SLUGS_TO_ADD (新サイトの固定ページ slug リスト)

固定ページ (profile / contact など) は事前に WP-CLI で作っておきます。前回の setup_contact_form_7.py のように、固定ページ作成も同じ流儀でスクリプト化できます。

将来的には全部 YAML 設定ファイルに切り出して、サイトごとに 1ファイル参照で済む形に拡張する予定です。

まとめ

SWELL は UI が良くできていますが、運用するサイトが 2個目以降 になると、毎回同じクリックを繰り返すコストが効いてきます。

  • カラー = theme_mod_set で1キー1コマンド
  • ナビ = wp menu ファミリーで idempotent に組み立て
  • 検証 = 設定後に option get theme_mods_swell_child で全キー突合

このパターンをテンプレ化しておけば、3サイト目・4サイト目の立ち上げが秒で終わります。


次に読むおすすめ

CTA

X 会社アカウントをフォロー: @ai_shacho_jp — 自動化スクリプト・実装ログを毎日投稿しています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次