すべての記事に戻る

Design-as-code:12日間でプラットフォーム全体を作り直した話

AI時代におけるプロダクト開発とエンジニアリングの新しい協業モデルについて、フロントエンドエンジニアの視点から


ありえない数字

12日間。プロダクトデザイナーとフロントエンドエンジニアの2人。プラットフォームの完全な作り直し。

プロトタイプではない。MVPでもない。本番アプリケーションの全面的な置き換えだ。最終的に1つのPRで26,000行のレガシーコードを削除した。すべてのページ、すべてのルート、すべてのインタラクションをゼロから再構築し、実際のユーザーに提供した。

従来のプロダクト開発ワークフローでは、このタイムラインはありえない。通常、この規模のプロジェクトには数ヶ月かかる。Figmaでのデザイン探索に数週間、ステークホルダーレビューのラウンド、ハンドオフのセレモニー、スプリント計画、そしてピクセルパーフェクトな実装という長い道のりが待っている。今回起きたことは根本的に違った。より頑張ったからではない。一緒に働く方法そのものが変わったのだ。

これは、VM0でZeroプラットフォームをリリースした経緯と、プロダクトとエンジニアリングの協業の未来について学んだことの記録だ。

従来のボトルネック

フロントエンドエンジニアなら誰もが知っている従来のパイプライン:

  1. デザイナーがFigmaでモックアップを作成
  2. デザインレビュー、イテレーション、承認
  3. スペーシング、カラー、ブレークポイントを注釈したスペック
  4. エンジニアがビジュアルスペックをコードに変換
  5. やり取りの繰り返し:「ここを4px左に動かして」
  6. ようやくAPIレイヤーの接続
  7. 結合テスト、さらなるやり取り

Before and After: The old handoff-heavy workflow vs. the new direct collaboration

ボトルネックは個々のステップにあったのではない。ステップとステップの間の隙間にあった。待ち時間、伝達ロス、コンテキストスイッチ。デザイナーがインタラクションに対して持つメンタルモデルは、静的なFigmaフレームにフラット化されてレッドラインで注釈された時点で、すでに劣化している。エンジニアはデザイナーが想像したものを再構築するが、それは不可避的に不完全なコピーになる。

この摩擦にあまりにも慣れてしまっていて、もはや見えなくなっていた。「そういうものだ」と思っていた。

実験:デザイナーがコードを書いたらどうなるか?

2026年3月5日、プロダクトデザイナーのMingがPR #3685を作成した:feat(platform): add zero app with shell, pages and polish。4,146行の動作するReactコードだ。

Figmaファイルではない。デザイントークンのエクスポートでもない。動くアプリケーションだ。

このPRには完全なアプリシェルが含まれていた。サイドバーナビゲーション、ルーティング構造、チャット・スケジュール・アクティビティ・チーム管理・設定のページスケルトン。すべてデザインシステムでスタイリングされ、ブラウザでレンダリングされていた。データはモックだったが、UIは本物だった。npm run devして、すべてのページをクリックして回ることができた。

Mingは従来の意味でこのコードをゼロから書いたわけではない。AIコーディングツール(最初はCursor、後にClaude Code)を使って、デザインビジョンを直接Reactコンポーネントに変換した。AIが機械的な変換(JSX構造、CSSプロパティ、コンポーネント合成)を担い、MingはAIには判断できないビジュアルとインタラクションの意思決定を行った。レイアウトのリズム、情報の階層構造、トランジションの感触。

続く4日間で、さらに3つのPRがマージされた:

日付PRMingが提供したもの
3月5日#3685アプリシェル、サイドバー、全ページスケルトン(+4,146行)
3月6日#3825スケジュールページ、UIの仕上げ(+2,650行)
3月9日#3993オンボーディングフロー、Slack設定ダイアログ(+1,146行)
3月9日#4050Aboutページ、フローティングナビカード

3月9日には、新プラットフォームのフロントエンド全体が動作するコードとして存在していた。本番で最終的に目にするすべてのページが、開発環境でクリック可能になっていた。ただし、まだ何も実際には動いていなかった。

ここで自分の出番だ。

新しい仕事:魂を吹き込む

The 12-day migration: UI blocks placed, logic wired in, the big switch flipped

3月9日にコードベースを開いたとき、フラットなデザインをコードに変換するという従来の課題はなかった。コードはすでにそこにあった。自分の仕事は、すべてのモックを本物に置き換えること。美しくデザインされた各画面を、その下にある生きたバックエンドに接続することだった。

これは根本的に仕事のあり方を変えた。ピクセルのことではなく、データフローのことを考えていた。「モックアップと合っているか?」ではなく「このページにはどのAPI呼び出しが必要で、失敗したらどうなるか?」を考えていた。

最初の1週間はこんな感じだった:

1日目(3月9日): 認証とOrg切り替え。MingのシェルにClerk認証を接続し、クロスドメインリダイレクトを追加し、Org切り替え機能を実装した。2つのPR、どちらも即日マージ。

2日目(3月10日): コネクターとスケジュール。モックのコネクターグリッドを実際のAPIデータに置き換え、スケジュールタブを実際のcronジョブに接続し、インストラクションエディタをバックエンドに接続した。4つのPR。

3日目(3月11日): 大規模な接続日。チームページに実際のサブエージェントデータを接続(+3,271行)。アクティビティページに実際のログを接続。そして目玉:チャットページを実際のエージェント実行パイプラインに接続し、約1,200行のデモコードを動作するAI会話インターフェースに置き換えた。同日、FeatureSwitchKey.Zeroというfeature flagを導入し、新旧のプラットフォームを並行稼働できるようにした。

4-5日目(3月12-13日): ファイル添付、セッション管理、マルチエージェントチャット、設定の永続化。Mingが構築したすべてのページが、実際に機能するようになった。

そのリズムはほとんど音楽的だった。毎朝、Mingのスキャフォールドからページを選び、コンポーネント構造を把握し、必要なデータを特定し、API連携を構築し、エラーステートを処理して、プッシュする。午後にはまた1つのページが生きたものになっていた。

Feature Switch:並行世界

FeatureSwitchKey.Zeroというfeature flagについて、独立して語る価値がある。これこそが、今回のマイグレーションを無謀ではなく安全にしたものだ。

3月11日以降、本番アプリケーションは2つの完全なUIを並行して動かしていた。旧システムのユーザーには旧ルートが表示され、新システムの内部テスターにはZeroが表示された。接続した各ページは、ユーザーのワークフローを一切リスクにさらすことなく、本番コンテキストでテストできた。

これ自体は革新的ではない。Feature flagは一般的なプラクティスだ。しかし、feature flagとdesign-as-codeワークフローの組み合わせが特別なものを生み出した。新プラットフォームのUX全体を検証できた(Mingが完全にブラウズ可能なUIを構築していたから)と同時に、各ページを段階的に機能させていった(自分が1つずつ接続していたから)。いつでも問題が起きれば、スイッチを戻すことができた。

何も問題は起きなかった。

12日目:ビッグスイッチ

3月17日、PR #5095を作成した:refactor: remove all non-zero platform pages and feature flag

diff:+456行、-26,041行。

Before:旧VM0 Platform。テーブル、Run ID、生のセッションデータ。

The old VM0 Platform

After:新しいZero。ピン留めされたエージェントとユースケースカードを備えた対話型AIワークスペース。

The new Zero platform

1回のマージで、すべてのレガシールートが削除された。Feature flagが除去された。Zeroはもはやオプションではなく、唯一のモードになった。続くPR(#5155)で/zeroのURLプレフィックスも完全に削除した。/zero/chatだったものが、単に/chatになった。

なぜこの削除に自信が持てたのか:

26,000行は不安とともに削除されたのではない。安堵とともに削除された。

パターンの再現

最も驚いたのは、マイグレーション自体ではなかった。発見したワークフローが、その後のすべての機能開発のデフォルトモードになったことだ。MingがAI支援でUIシェルを構築し、自分がロジックを接続してアーキテクチャを拡張する。同じdesign-as-codeパターンが、機能単位で繰り返される:

パーミッションシステム(3月19日→4月7日)

MingがPR #5467を作成した。SheetコンポーネントとトグルコントロールによるパーミッションドロワーUI。3コミットのクリーンなUI。

自分は同じPRに13コミットを追加した。firewall_access_requestsのデータベースマイグレーション、APIエンドポイント、結合テスト、lint修正。その後2週間で10以上のフォローアップPRにより、完全なパーミッションレイヤーを構築した。承認カードのリデザイン、アクセスリクエストのSlack通知、パーミッション問題診断用のCLI doctorコマンド、そして最終的にコードベース全体で「firewall」から「permission」へのリネーム。

Mingのドロワーが種だった。パーミッションシステムが木になった。

スケジュールシステム(3月23日→4月13日)

Mingがスケジュール詳細ルートとカレンダーUXをデザインした(#6155)。3コミットのクリーンなUI作業。

自分は14コミットを追加した。自動生成付きの説明編集、通知用Slackチャンネル選択、未保存変更の確認ダイアログ、カレンダー/リストビューの統合、包括的なテスト。その後15以上のフォローアップPRで、実行履歴、タイムゾーン処理、cron式サポートを備えた完全な定期タスクシステムに拡張した。

Telegram連携(4月27日→4月28日)

この時点ではパターンが十分に確立されており、プラットフォーム連携全体を48時間で出荷した。MingがSettings UI(#11196)とオンボーディングフロー(#11399)を構築。自分はマルチボットAPI、メッセージ送受信、ファイルアップロード/ダウンロード、リッチメッセージコンテキスト、Ablyリアルタイム更新、E2Eテストを構築した。翌日、全ユーザーに公開された。

AIの役割

AIの役割について正確に述べたい。過大評価も過小評価も容易だからだ。

AIがデザイナーのコーディングを可能にした。 Mingはプロダクトデザイナーであり、ソフトウェアエンジニアではない。レイアウト、階層構造、インタラクションで考える人であり、React hooksやTypeScript genericsで考える人ではない。AIツール(Cursor、その後Claude Code)が、デザイン意図から動作するコードへの機械的な変換を担うことで、そのギャップを埋めた。Mingが指示し、AIがタイピングした。結果として、デザイナーが著者でありながらエンジニアが拡張できるコードが生まれた。

AIがレビューループを加速した。 共同PRでは、自分のAIエージェントがMingのコードをレビューし、問題を優先度(P0/P1/P2)で分類し、修正コミットを直接プッシュした。PR #5060は38分で5回のレビューラウンドを通過した。PR #5467は20分で3回のラウンドを完了した。これは「AIがコードレビューを置き換える」ということではない。自分はすべての変更を読んでいる。しかし、lintの問題、型の不足、テストのギャップを特定する機械的な作業が自動化された。

AIはデザインの意思決定をしていない。 各ページの情報アーキテクチャ、インタラクションパターン、ビジュアルの階層構造。これらはMingのプロダクト感覚から生まれたもので、ユーザーリサーチとドメイン知識に基づいている。AIは設定ページを生成できるが、トグルにすべきかドロップダウンにすべきか、確認ダイアログが必要なのか摩擦になるのかは判断できない。

AIはアーキテクチャの意思決定をしていない。 並行デプロイにfeature flagを使う選択、APIレイヤーの分離戦略、ページを一括ではなく段階的に接続する判断。これらはエンジニアリングの判断だ。AIはコードを速く書く助けにはなったが、順序立てやリスク管理は人間が行った。

率直にまとめると:AIはデザインとエンジニアリングの間の翻訳レイヤーを取り除いた。どちらの専門性も置き換えたのではなく、両者の間の隙間を埋めたのだ。

自分の役割がどう変わったか

このワークフローで3ヶ月過ごした今、フロントエンドエンジニアとしての自分の役割を違う目で見ている。

ビジュアルの翻訳者ではなくなった。 Figmaファイルを受け取ってスペーシングの値を合わせるのに何時間も費やす日々は終わった。自分がそれを速くできるようになったからではなく、もはやそれが自分の仕事ではないからだ。デザイナーの意図は、コードの画像としてではなく、コードとして届く。

アーキテクチャの拡張者になった。 自分の主な価値は、動作するUI画面を受け取り、その下に見えないインフラを構築することだ。API連携、データバリデーション、エラーハンドリング、パーミッションチェック、リアルタイム更新、テスト。共同PRの大半でのコミット比率がそれを物語っている。MingがUIを3コミット、自分がそれ以外を13コミット。

品質のゲートキーパーになった。 AIアシストのレビューループにより、以前よりはるかに広い範囲のコード品質を維持できるようになった。機械的な問題は自動レビューが検出し、自分はアーキテクチャ上の懸念、エッジケース、機能がエンドツーエンドで実際に動作するかに集中する。

デリバリー戦略家になった。 Feature flag、段階的な接続、並行デプロイ。機能がコードから本番に至るまでの順序立ては、今や自分の仕事の中核であり、後付けではない。

数字で見る成果

3ヶ月間。2人。AIアシスト全般。

これはがむしゃらに働いた指標ではない。どちらも週末出勤や徹夜はしていない。速度の源泉は無駄時間の排除だ。ハンドオフミーティング、スペックの誤解、「ここを4px動かして」のやり取り。デザイン意図がコードに直接流れ込み、エンジニアリングがそのコードをその場で拡張するとき、単純に無駄が少なくなる。

チームにとっての意味

すべてのチームがこのように働くべきだとは言わない。このワークフローは特定の状況から生まれた。少人数のチーム、グリーンフィールドでの再構築の機会、そして高性能なAIコーディングツールへの早期アクセス。状況によって結果は異なるだろう。

しかし、根底にあるシフトは普遍的だと信じている。デザインとエンジニアリングの境界は溶解しつつあり、AIがその溶媒だ。 AIツールが意図からコードへの変換を上達させるにつれ、より多くのデザイナーが直接コードを出荷するようになる。そうなれば、エンジニアは翻訳に費やす時間が減り、アーキテクチャ、品質、デリバリーにより多くの時間を使うようになる。

フロントエンドエンジニアの仕事はなくならない。形が変わるのだ。そして正直に言えば、新しい形の方が面白い。


YumaはVM0のフロントエンドエンジニア。AIエージェントOSであるZeroを動かすプラットフォームを開発している。本人が認めたい以上の量のレガシーコードを一括削除してきた。

最新情報をキャッチ

// エージェントネイティブ開発の最新インサイトを入手。

購読するDiscordに参加