SWELL のカスタマイザは UI が直感的で、初心者でも迷いません。ただ、AI × ソロ起業の前提だと 3〜4個の WP サイトを並行運用 することが確定しているので、毎回同じカラーパレットとナビを UI でクリックして設定するのは時間が惜しい。
ここでは SWELL のカラー10色とグローバルナビ (ホーム / プロフィール / お問い合わせ) を WP-CLI + Python で 30秒で揃える 実装ログを公開します。前回の Contact Form 7 自動化と同じ流儀の続編です。
目次
- なぜ SWELL カスタマイザの自動化が効くのか
- theme_mod の正体 — どこに保存されているか
- setup_swell_basic.py — カラー10色を一括投入
- setup_swell_navigation.py — グローバルナビを idempotent に組み立てる
- 実行ログと所要時間
- 次のサイトに使い回すときのカスタマイズ
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つのファイルを差し替えます:
core/lib/automation/wp_cli.pyのDEFAULT_SSH_HOSTとDEFAULT_WP_PATH(新サイト用 ssh ホスト名・新サイトの public_html パス)scripts/setup_swell_basic.pyのSWELL_BASIC_COLORS辞書 (サイトごとに色を変えたい場合)scripts/setup_swell_navigation.pyのHOME_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サイト目の立ち上げが秒で終わります。
次に読むおすすめ
- Claude Code を YouTube・X で2ヶ月独学した僕が、AI×ソロ起業ブログを立ち上げた初日ログ (2026年版)
- Contact Form 7 を Python + WP-CLI で 5分で自動設置する手順 (2026年版)
CTA
X 会社アカウントをフォロー: @ai_shacho_jp — 自動化スクリプト・実装ログを毎日投稿しています。
