WordPressのカスタムブロックをAgentic Codingしてみる

個人的にやってるアプリとかはよくAIにやらせてるけど、WordPress関連では調べごとをAIに頼むくらいだったので、そもそもWordPressのカスタムブロック作れるのか?を検証してみる。
(言うてちょっとWPのお作法があるだけのReactだからできるだろうとは思ってる)

IDEは最近お気に入りのKiroをつかいます。
事前にChatGPT o3(Claudeはレートリミットでお休み中)と一緒に壁打ちした内容をPre-PRD
としてREADME.mdに書いて、Kiroに仕様書を作ってもらう
Cover-Responsive-Focal
Kiro に渡す初回ブリーフィング(日本語)。WordPress のコア Cover ブロックを拡張し、1 枚の背景画像に対してブレークポイント別のフォーカルポイント(object-position)を設定できるプラグインを実装する。
⸻
1. プロジェクト概要
• 目的 : Gutenberg Cover ブロックを拡張し、デスクトップ/タブレット/モバイルで被写体が切れないようフォーカスポイントを可変にする。
• 成果物 : GPL-2.0 or later で公開する軽量プラグイン。スラッグは cover-responsive-focal。
2. 主な機能
# 機能 詳細
1 responsiveFocal 属性 media(文字列)+ x/y(0–1)のオブジェクト配列。
2 インスペクター UI サイドバーにリピーターを実装。ブレークポイント選択+FocalPointPicker。PC/SP プリセットをデフォルト生成。
3 動的 <style> 生成 render_block フィルターで CSS 変数 --fp-x / --fp-y をメディアクエリ内に出力。
4 画像は 1 枚のみ使用 既存 <img> を再利用。追加マークアップなし、CLS 0。
5 後方互換 responsiveFocal が空ならコアの focalPoint 挙動にフォールバック。
3. 技術スタック & ツール
• WordPress 6.5 以上
• @wordpress/scripts(Babel + Webpack)
• React 18 / Gutenberg Packages
• PHP 7.4+
• SCSS(任意)
4. ディレクトリ構成(案)
cover-responsive-focal/
├─ build/ # ビルド成果物
├─ src/
│ ├─ index.js # registerBlockType フィルター
│ ├─ inspector.js # UI
│ ├─ save.js # save 要素オーバーライド
│ └─ style.scss # 共通 CSS
├─ plugin.php # プラグインエントリ
├─ package.json
├─ composer.json # (必要なら)
└─ readme.txt # wp.org 用
5. 属性スキーマ
responsiveFocal: {
type: 'array',
default: [], // [{ media:'(max-width:767px)', x:0.60, y:0.40 }, …]
},
※ 既存属性(url, id, focalPoint 等)はそのまま。
6. JavaScript 概要
// index.js(一部)
import { addFilter } from '@wordpress/hooks';
addFilter(
'blocks.registerBlockType',
'crf/extend-cover',
( settings, name ) => {
if ( name !== 'core/cover' ) return settings;
settings.attributes.responsiveFocal = { type: 'array', default: [] };
return settings;
}
);
• InspectorControls でのリピーター UI と save.js の実装は Kiro タスク。
7. PHP 概要
/* plugin.php */
add_filter( 'render_block', 'crf_render_block', 10, 2 );
function crf_render_block( $content, $block ) {
if ( 'core/cover' !== $block['blockName'] ) return $content;
$attrs = $block['attrs'];
if ( empty( $attrs['responsiveFocal'] ) ) return $content;
$id = esc_attr( $attrs['dataFpId'] ?? wp_unique_id( 'crf-' ) );
$rules = '';
foreach ( $attrs['responsiveFocal'] as $row ) {
$rules .= sprintf( '@media %s{[data-fp-id="%s"]{--fp-x:%s%%;--fp-y:%s%%;}}',
$row['media'], $id, $row['x']*100, $row['y']*100 );
}
return $content . "<style id=\"$id\">$rules</style>";
}
8. CSS スニペット
.wp-block-cover__image-background {
width: 100%;
height: 100%;
object-fit: cover;
object-position: var(--fp-x, 50%) var(--fp-y, 50%);
}
9. Kiro へのタスク一覧
1. ディレクトリスキャフォールド & package.json 生成
2. responsiveFocal 属性追加(JS)
3. InspectorControls リピーター UI 実装
4. save.js で data-fp-id + インライン変数出力
5. PHP render_block フィルター完成
6. SCSS コンパイル設定
7. wp-env で動作確認 & ESLint/PHPCS 通過
8. README(日本語)作成
10. 受け入れ基準
• responsiveFocal 未設定時はコア動作と同一。
• モバイル LCP < 2.5s、CLS ≤ 0.1。
• @wordpress/eslint-plugin/recommended & WordPress-Core コーディング規約準拠。
11. 今後のロードマップ
• v0.2 : デスクトップ/タブレット/モバイルの自動プリセット追加
• v0.3 : フォーカル未指定時のサーバーサイドスマートクロップ(Imagick/OpenCV)
• v1.0 : WP.org 登録、国際化、GitHub Actions CI
⸻
以上で Kiro への初回ブリーフ完了

インスパイアされたのは t-hamano さんのEnable Responsive Imageなので、要件定義とか挙動の参考にしてねって送っておく

作った仕様書はこんな感じ

さすがに @wordpress/create-block
で開発環境つくってーは無理そうかなぁ

@types/wordpress__block-editor
とかの型情報もちゃんと取ってきてくれてるから、ベースは作ってもらう->確認して人間が手直しするで十分作れそう

テストとかもちゃんと書いてくれて感動・・・。正直カスタムブロックのテストの書き方どう書いたらいいんだろう?って状態なので、サンプルになりうるもの書いてくれるだけでありがて〜

「ここはなんでこうしてるの?」を深掘りしながら、納得できなかったら直していくスタイルですすめる

同じようななぜなぜ攻撃がだるくなってきたらCLAUDE.mdに方針として残す

「なんで?」ってシンプルに聞くと教えつつコード直すから、壁打ち気味にやりたいときは「直して欲しいって意図じゃなくて先にどうしてこうなってるのか解説してほしい」的に書くと、(セッションが違うからだと思うけど)推察して教えてくれて、現在の推奨がどうなっているか、どうするのがよさそうか(もしくはこのままでいいか)までいってくれる

たとえばテストのfireEvent
とuserEvent
の使い分け。
大体fireEvent
使われがちだな〜っていう体感があるけど、WP的にfireEvent
の方がまだメジャーなのかもしれないということで調べてもらった。
結果、fireEvent
とuserEvent
両方使われてるけど、Testing Libraryが推奨してるuserEvent
で統一しましょうとなってコード変更。でも、Range InputはuserEvent
が使えなかったからfireEvent
を使用した。まあハイブリッドアプローチ。
userEventの制限事項
- Range Input: user.clear()やuser.type()が使用できない
- 解決策: 実際のユーザー体験に近いテストが困難な要素では、fireEventを部分的に併用

「サブタスクごとにブランチ切ってプルリクエストして」は失敗しがち

調べてないしやってないけど、tasks.md
のタスクの最後に「新しいブランチを作成してプルリクエストを行う」とか書いてたらもしかしてうまくいくのだろうか………

プロトタイプをつくる->見てもらって方向性のすり合わせするっていうフローが個人的にすごくやりやすいかも。

凝らなくていいのに「このケースだとバグる?」「min-width とmax-width混在したときのテストってどうしようかな」とか考え始めて一生終わらない様相を見せ始めたけど、すり合わせ通話で モバイルとデスクトップ固定にする という方針を決められた