AI に駅ナカ・おでかけ提案を作らせてみた — 3画面さまよった「券面」が、ついにコンポーネント化(やってみた #128)
/station-outing375px のビューポートで撮影。縦長のページはフレーム内をスクロールします。
解説記事
AI に駅ナカ・おでかけ提案を作らせてみた — 3画面さまよった「券面」が、ついにコンポーネント化(やってみた #128)
やってみたシリーズ: 自作のデザインシステム
@gunjo/ui(群青)を、群青のことを一度も見たことのない AI に、実際の画面で組ませていく連載。鉄道の利用者向け 深掘り(利用者向けバックログ)——駅ナカ・おでかけ提案(おすすめスポット・店舗・使えるクーポン・デジタル会員証)。
結果 — 3.5/5、そして「券面」がついに固まる
tsc 緑・375px mobile-first。予備知識ゼロの AI(群青を一度も触っていない設定):
4つの主役級が「これのために作られた」ようにぴったり:
PageHeader(アプリバー)・LoyaltySummaryCard(JRE POINT 残高/ランクの大きな見出し)・FilterChips(グルメ/おみやげ/カフェ)・ListCard(店舗もクーポンも・カード全体が ≥44px ボタン)。枠組みはほぼゼロ工数。 だがコイン裏の主役=レジで掲げる券面が無い。
4つの利用者向けの土台が #128 で一斉に自力発見された(別業界での自力発見がまた)。だが本丸は別にあった。
観測の核 — 3画面さまよった末の TicketStub のコンポーネント化
デジタル会員証 / クーポン提示の券面=完全手組み。これが筆頭の欠落。
TicketStub/PassCard/BarcodeCard/CouponStub/QrCodeどれも無い。唯一バーコードに近いScanInput/ScanGateは事業者/レジ側——コードを読み取る側で、旅行者が要る表示の真逆。「BarcodeCard/PassStubが要る——value・format(code128/qr)・読めるラベル・ミシン目・role=img。これが追加すべき唯一のもの。今は誰もが自前でバーコードを再発明し、多くは<img>をサーバに投げる。」
連載で券面は3画面さまよった:搭乗券 #114・国際線 eチケット #123・駅ナカ クーポン/会員証 #128=3回独立に手組み。3回ルール発火、その場で作る。
作る — TicketStub(チケット券面)
// クーポン(code128 バーコード):
<TicketStub value="CPN-NEWDAYS-3X-887412" codeLabel="887412">
<div className="flex items-center justify-between">
<span className="font-semibold">NewDays ポイント3倍</span>
<Badge variant="warning">期間限定</Badge>
</div>
<p className="mt-1 text-xs text-muted-foreground">対象:駅ナカ NewDays 全店・〜2026/06/30</p>
</TicketStub>
// 搭乗券(QR + OD/座席/搭乗口):
<TicketStub value="NH106-X7K2QM-18K" format="qr" codeLabel="X7K2QM">{/* … */}</TicketStub>
value+format(code128/qr)+読めるラベル+ミシン目のノッチ+上の内容の差込口(便の発着/座席・クーポン割引・会員ランク)。- 組み込みのコードは決まった値(FNV シードの疑似乱数)の見た目のプレースホルダ=サーバー描画で安全・サーバー/ブラウザずれ無し・実際の値は role=img の aria-label に。実スキャンは
codeで差替。サーバーコンポーネントでも安全。 -
ScanInput/ScanGateの消費者側の対(読み取る vs 提示する)。索引も「コードを出す→TicketStub・読み取る→ScanInput」に割った。 - PR#377・実機375pxで QR 327セル+code128 69バー・role=img が実際の値を保持・ミシン目・format トグル・溢れ0。
今回 src で作ったもの = TicketStub(3回目・11個目のコンポーネント化)。
学び — 「コインの裏側」は別のコンポーネント
群青には ScanInput/ScanGate(コードを読み取る事業者側)が最初からあった。だが消費者が要るのは提示する側=コインの裏。1つの概念(バーコード)に対し、事業者向け(読取)と利用者向け(提示)は別々のコンポーネントになる。 これは「守備範囲が割れる」(#126 RouteStops/Itinerary) の双子——同じ領域の語彙でも、向き(事業者向け/利用者向け)が違えば別のコンポーネント。利用者向けの深掘りが、最初からあった事業者向けのコンポーネントの「裏面」を炙り出した。連載の最初から「全モード 事業者向け+利用者向け 両面」と決めていたのは、まさにこの非対称を掘るためだった。
📊 コンポーネント化スコアボード(作成済 11個)
AmountBreakdown / ActionQueue / ListCard / Gantt-segments / SeatMap / LoyaltySummaryCard / RadioCard / FilterChips / PageHeader / Itinerary / TicketStub 進行中:StatusLevel・SegmentedControl・StatusScreen success・Gantt 時刻軸・AmenityRow
📋 利用者向けバックログ
- ✈️ 航空:全6枚 完了 ✅
- 🚆 鉄道:定期券✅駅ナビ✅きっぷ✅駅ナカ提案✅ / 残り:払戻し・遅延証明書
次回予告(やってみた #129)
- 鉄道 払戻し・遅延証明書(AmountBreakdown 手数料・申請フロー)で鉄道の利用者向けを締め、その後 次のモード(バス/タクシー/トラックの事業者向け+利用者向け)へ。
試す
- gunjo.jp / チケット券面 TicketStub / ロイヤリティ LoyaltySummaryCard / npm
@gunjo/ui/ GitHub / 前回まで #1〜#127 - GunjoUI by UIXHERO
3画面さまよった券面が、最初からあった事業者向けのコンポーネントの「裏面」として固まった——同じバーコードでも、読み取ると提示するは別のコンポーネント。
この連載は、作者が AI(Claude と Codex)と協働で制作しています。実験・検証の設計、判断、公開前の事実確認は人間が行い、実作業と下書き執筆は AI が担っています。
使用した @gunjo/ui コンポーネント
この画面のソースが直接 import しているコンポーネントです。
cold AI が組み上げた実コード
ファイル名をクリックでソースを展開できます。