🎨

【PoCで終わらない】運用フェーズまで見据えたAI駆動UIデザイン/フロントエンド開発実践

に公開

はじめに

こんにちは。AlmondoでSWEとして主にフロントエンド開発で携わっております、kita3222です。

昨今、生成AIの進化がめまぐるしい中で、フロントエンド開発においても様々なツールが登場してきました。

例えば、v0はAIとの対話を通してUIを構築するAI開発ツールです。Reactのコードを用いてUIを構築するため、UIデザイン生成だけでなく、同時に実装が行えるという点で非常に先進的なフロントエンド開発ツールと言えます。

https://v0.dev/

v0をはじめとするAIデザインツールはどれもPoCレベルのシステム開発であれば、スピード感のある開発が可能となり、とても重宝するのですが、何画面もあるようなシステムの開発においては正直なところ、力不足感が否めないです。

ただ、UIデザインの生成と同時にフロントエンド部分の実装が完了してしまえば、デザイン→実装へのコストがゼロになるという点で、ソフトウェア開発の生産性を大幅に向上できる可能性を秘めていると感じます。

そこで、「コードを用いてデザインする」というv0の思想を取り入れつつ、中規模以上のシステム開発においても一貫したデザイン管理が可能な形を追求しました。本記事ではその過程と実際にAlmondoでの運用事例をご紹介させていただきます。

現状のデザインにおけるAI活用

生成AIが登場する以前は、UIデザインの検討や作成を行う際に使用するツールはほとんどFigma一択でした。

その時代に、デザイン検討・作成の過程をいきなりHTML・CSSで行うのは現実的ではありませんでした。

デザインは検討過程でスクラップアンドビルドを繰り返すため、それに対して都度コードを書いているようでは非効率です。そのため、Figmaのような直感的にGUI操作でUIデザインが作れるツールが普及していたと考えられます。

しかし、生成AIの登場によって、v0やLovable、boltのような対話を通して、AIがコードを用いてデザインを作成してくれるようなツールが出てくるようになり、コーディングのコストが著しく下がりました。

これらのサービスは「自然言語による漠然とした指示によって、UIデザイン及び実装が簡単に作成可能であること」とそれによって「何度も高速でデザインの試行が可能であること」という点が特徴的です。

瞬時にユーザーの指示に従ってそれを満たすようなUIデザインがサービス画面上に表示されるので、何度も自分の満足のいく画面になるまでデザインの試行錯誤が気軽に行えます。

このようなコードを用いてデザイン検討・作成を行うような方法は、生成AIがコーディング作業を代替してくれるようになったおかげで、以前よりは現実的になってきました。

この辺りの話は以前「コードでデザインを作り、管理するという発想」と言う考察記事を書きました。

https://zenn.dev/kaiki_kk/articles/375385b17719fa

現状のAIデザインツールにおける課題

v0やLovableといったAIデザインツールでは、何画面もある中規模以上のシステムを一貫したデザインを管理し続けることが難しいです。具体的には以下のような理由が挙げられます。

  • セッションが独立しているため、同一チャット内でしか同じシステムに対する実装ができない。
  • (v0の場合)ツール上で生成したコードをエディターに取り込んで実装した後、その変更を再度ツール側に同期させる機能がない。

1画面の実装をするのであれば1セッションの中で作りきれるのですが、複数画面の実装を1つのセッションで行おうとすると、コンテキストの肥大化によってどんどん生成結果の精度が下がっていきます。

また、v0の場合はGithubとの連携機能が現状だと存在しないため、一度生成したUIをCursorなどのエディタに落として修正してから、再度v0でUIを作ろうと思ってもそれができません。

つまり、0→1のUI生成にユースケースが限られてくるため、中〜大規模システム開発で使用するのはなかなか難しいのです。

では、どのようなものが理想か

では、中規模以上のシステム開発を行う上ではどのようなものが理想でしょうか。以下の条件を満たすようなものだと私は考えました。

  • v0のようにAIとの対話を通してUIデザインの検討・実装が一気通貫でできるような体験であること
  • システム内で一貫したデザインルールに則ったUIが継続的に実装可能であること
  • (Figmaの代替手段として)継続的なデザインの運用管理が可能であること。

つまり、デザインシステムのような一定のルールに基づき、AIとの対話形式でデザインの自動生成が行え、そして生成したデザインを継続的にメンテナンスし続けられるような環境であることが理想です。

Almondo の方針

Almondoでは、主に以下の3つの開発ツール(ライブラリ)を駆使することで、この課題を解決しました。

  • Cursor(AIエディタ)
  • shadcn/ui(UIコンポーネントライブラリ)
  • Storybook(UIカタログ)

Cursorについて

Cursorは、AIによる様々な支援機能が搭載されたエディタです。

https://www.cursor.com/ja

CursorにはAgentモードが搭載されており、AI Agentとの対話を通してコードの生成が可能です。突き詰めると、v0でやっていることはほとんどCursorで代替可能です。

v0 との開発体験比較

観点 v0 Cursor
生成したUIのプレビュー ブラウザ上のサービス画面で即表示 localhost を起動して即確認
セッションをまたぐ開発 チャットごとに生成コードが独立し、画面数が増えると管理が煩雑 1つのリポジトリを共有し、セッションを切り替えても継続開発が可能。さらに、Project Rulesを活用することでセッションごとに生成されるUIの差分も最小限にすることが可能。

v0では、生成されたUIデザインをブラウザのサービス画面上に表示されるので、何度も自分の満足のいく画面になるまで気軽に再生成が可能ですが、「AIによって生成したコードがすぐブラウザ上で確認できる環境」があれば同じような体験は実現できると言えます。

Cursor Agentとの対話を通してUIを生成し、ローカルホストを起動してブラウザで確認すれば同じような開発体験は実現できます。

また、v0やLovableとの大きな違いで言うと、同一システムに対して複数のチャットのセッションを跨いで継続的に開発が可能であると言う点です。

v0ではプロジェクトという共通のプロンプトを設定し、複数のチャットの管理が可能ですが、結局のところ、チャットごとに生成されるコードは独立して管理されるので、複数画面の実装には不向きです。

一方、Cursorでは1つのリポジトリに対してAI Agentとの開発が可能なので、チャットのセッションを切り替えた場合でも、継続的に開発が可能です。

チャットのセッションを跨いで違う画面を実装する際も、Project Rulesにデザインシステムなどの共通ルールを定義しておけばセッションごとに生成されるUIの差分も最小限にすることが可能です。

shadcn/uiについて

shadcn/uiはカスタマイズ性に富んだUIコンポーネントライブラリです。

https://ui.shadcn.com/

shadcn/uiは、「システム内で一貫したデザインルールに則ったUIを継続的に実装する」上で重要な役割を担います。

実態としてはTailwind CSSとRadix UIで実装されたUIコンポーネント集です。以下のようにCLI経由で必要な時にTailwind CSSでスタイリングされたコンポーネントが作られるのです。

npx shadcn@latest add button
生成されたButtonコンポーネント
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const buttonVariants = cva(
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
  {
    variants: {
      variant: {
        default:
          "bg-primary text-primary-foreground shadow hover:bg-primary/90",
        destructive:
          "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
        outline:
          "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
        secondary:
          "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        default: "h-9 px-4 py-2",
        sm: "h-8 rounded-md px-3 text-xs",
        lg: "h-10 rounded-md px-8",
        icon: "h-9 w-9",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
)

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : "button"
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        {...props}
      />
    )
  }
)
Button.displayName = "Button"

export { Button, buttonVariants }

AI-ReadyなUIコンポーネントライブラリ

MaterialUIなどの従来のUIライブラリと異なり、スタイリングの実装が隠蔽されず、全てリポジトリの中で表現されます。そのため、AIがコンポーネントの構造やルールを理解しやすく、他のUIライブラリよりもAIによる実装が容易になります。

AI-Ready

The design of shadcn/ui makes it easy for AI tools to work with your code. Its open code and consistent API allow AI models to read, understand, and even generate new components.

An AI model can learn how your components work and suggest improvements or even create new components that integrate with your existing design.

(引用: shadcn/ui docs “Introduction” https://ui.shadcn.com/docs

デザインシステムを取り入れやすい内部構造

さらに、shadcn/uiはデザインシステムをコードとして表現するための仕組みであり、デザインシステムを取り入れやすい形に設計されたライブラリとも公式では言及されています。

Every component in shadcn/ui shares a common, composable interface. If a component does not exist, we bring it in, make it composable, and adjust its style to match and work with the rest of the design system.

(引用: 同上)

shadcn/ui はスタイルを定義するレイヤーと振る舞いを定義するレイヤーの2層に分かれて定義されています。

特にスタイルを定義するレイヤーにおいては、プロジェクト全体のトークンを定義するglobal.cssとtailwind.config.ts、各コンポーネントのバリアントを管理するCVAの3つの要素と、それらを元に各コンポーネントで定義されたユーティリティクラスによって見た目は決まります。

(引用: Manupa Kandasamy “The anatomy of shadcn/ui” https://manupa.dev/blog/anatomy-of-shadcn-ui

shadcn/uiによって生成されるコンポーネントはいずれもtailwind.config.tsで定義されたユーティリティクラスを使用するので、global.cssでデザインシステムのトークンを変更することで、全てのコンポーネントに対して一括反映が可能です。

これにより、案件ごとに顧客のブランドイメージに沿ったデザインシステムを定義し、システムを構築することも可能になります。

運用面でのメリット

生成AIによるチャット形式でのUIデザイン、コード生成だと、生成結果が自由すぎて制御が効かなくなる可能性があり、運用コストが上がる可能性があります。

その点、shadcn/uiという「制約」を設けることで、生成結果が一定のルールに基づくこととなり、運用面での懸念も解消できます。

Storybookについて

Storybookは、UIコンポーネントを管理・ドキュメント化するためのツールです。

https://storybook.js.org/

一般的には、Figmaで設計したコンポーネントと実装済みのコンポーネントとのズレを検知するための「ビジュアルリグレッションテスト」の目的で利用することが多いのではないでしょうか。

今回は、どちらかというと「AIによって生成されたUIデザインの品質管理」を行う用途で採用しました。

Figmaでは大きく分けて次の二つの視点を切り替えながらデザインを管理できます。

  • 俯瞰視点:各画面を一望してトンマナのブレや不整合をチェック
  • 詳細視点:コンポーネント単位で状態変化やバリエーションを確認

AIによって生成されたUIデザインはやはり不安定なことが多いです。
Storybook上でコンポーネントの状態を網羅的に整理し、さらに画面全体を俯瞰して確認できるようにすることで、AIによって生成されたデザインであっても、品質の担保が一定可能となります。

また、Figmaで事前にデザインを共有して認識をすり合わせるのと同様に、生成したUIモックをStorybookに反映してホスティングしておくことで、開発の早い段階から顧客とデザインの認識を合わせることも可能となります。

実際にやってみる

ここからは、実際に上記3つのツールを駆使して簡単な社内RAG ChatシステムのUIを構築していきます。

以下のような機能を持ちます。

機能概要

  • AI チャットページ
    • RAGチャット
    • チャット履歴表示 / 会話管理
  • ナレッジベース登録 / 管理ページ
    • RAGで参照するドキュメントやFAQなどをアップロード/管理
    • ステータスを表示
    • ドキュメント検索
  • ユーザー招待 / 管理ページ
    • 組織内ユーザーの招待 / 管理
    • ユーザー名検索
    • ステータスと権限(管理者/一般ユーザー/閲覧専用)を表示

1. Cursorでshadcn/uiをセットアップ

フロントエンドのプロジェクト配下で以下のコマンドを実行すると、shadcn/uiのセットアップが行われます。

npx shadcn@latest init

以降、CLIコマンド経由で欲しいコンポーネントの生成が可能になります。

2. shadcn/uiのデフォルトのスタイリングで画面実装

まずはレイアウトの実装を行なっていきます。

shadcn/uiにはコンポーネントを組み合わせて実装されたページやレイアウトのサンプルがあります。

こだわりがなければ、いくつかあるサイドバー・ヘッダーのサンプルから要件に合いそうなものを取得してくると良いでしょう。

今回はチャット画面において、ページ遷移の目的で使用するグローバルなサイドバーと、チャット画面で表示するチャット履歴のサイドバーの2つのサイドバーの開閉ができるようにしたかったため、以下のグローバルサイドバーの開閉ボタンがヘッダーにあるものを選択しました。

npx shadcn@latest add sidebar-16

次に、各ページの実装を進めていきます。

まず、ナレッジベース管理画面から実装していきます。

CursorのAgentチャットで以下のようなプロンプトで画面を実装していきます。shadcn/ui を使用することについてはProject Rulesに定義済みなので、プロンプトにはあえて記載はしません。

プロンプト
ナレッジベース画面を実装してください。

機能概要
- RAGで参照するドキュメントやFAQなどをアップロード/管理する画面。
- ステータスを表示
- ドキュメント検索

要件
- テーブル上に登録済みのナレッジベースの一覧が表示されること
- 画面右上に「新規登録」ボタンを設置すること。それを押下すると、ナレッジベース登録ダイアログが表示されて、ナレッジベース元のファイルをアップロードできること。

実装先
- app/(app)/knowledge-base ディレクトリ配下に実装すること

すると、以下のような画面が生成されました。
良い感じですね。特に手直しする必要もなさそうです。


ナレッジベース管理画面とほぼ同じ要領でユーザー管理画面も実装していきます。

プロンプト
ユーザー管理画面を実装してください。

機能概要
- 組織内ユーザーの招待 / 管理
- ユーザーの招待
- ステータスと権限(管理者/一般ユーザー/閲覧専用)を表示

要件
- テーブル上にユーザーの一覧が表示されること
- 画面右上に「ユーザー招待」ボタンを設置すること。それを押下すると、ユーザー招待ダイアログが表示されてユーザーの招待が可能であること

実装先
- app/(app)/user ディレクトリ配下に実装すること


最後に、チャット画面を実装してきます。

他の画面とは異なり、mainタグ領域内にチャット履歴を表示するためのサイドバーを実装する必要があります。こういう少々トリッキーなUIをAIで生成させようとすると、プロンプトでかなり丁寧に画面のイメージを伝えないとなかなか思うような生成結果にはなりません。

そこで、Figmaでサクッと簡易的なワイヤーフレームを作成しました。
やはりUIを自然言語だけで表現しようとすると限界があります。「どこに何の要素があるか」と言うのがざっくりわかるワイヤーフレームを作って渡すだけで生成結果で齟齬が生まれづらくなります。

プロンプト
RAGチャット画面を実装してください。

機能概要
- チャット機能(RAG部分)
    - メッセージ表示
    - メッセージ入力
- チャット履歴サイドバー
  - 新規追加ボタン(アイコンボタンのみ)
  - サイドバーの開閉ボタン
  - 検索フィールド
 

要件
- チャット履歴サイドバーは開閉可能。サイドバーを閉じた場合、チャット画面部分が広がるように
- チャット履歴は日時降順で表示

実装先
- app/(app)/chat ディレクトリ配下に実装すること

添付したワイヤーフレームを参考に実装してください
ワイヤーフレーム

すると、何度かやり取りを経て以下のようなUIが生成されました。イメージ通りのものが作れました。

ここまでで、shadcn/uiのデフォルトのスタイリングを適用したコンポーネントを使用して、主要3画面のUIデザイン/実装を行いました。

shadcn/uiのデフォルトのデザインが洗練されたものなので、このままでも良さそうですが、色合いが地味すぎるのと、デザインが「いかにもshadcn/ui使って作りました」感が出過ぎている点も微妙です。

そこで次に、顧客のブランドイメージに沿ったデザインシステムをCursor Agentを使って構築し、適用していきます。

3. ブランドイメージに沿ったデザインシステムを構築し、システムに対して適用

まず、Cursor Agentを使ってブランドイメージに沿ったデザインシステムを構築していきます。

以下のように、Cursor Agentがデザインシステムを作成する上で必要な検討事項について、開発者にヒアリングするような形でデザインシステムを検討し、その結果を global.cssに反映させるようなフローで進めていきます。

まず、以下のようなProject Rulesを定義します。

Project Rules
---
description: shadcn/ui + Radix UI + Tailwind CSS v4環境でのデザインシステム構築ルール
globs: 
alwaysApply: false
---
# デザインシステム構築ルール

## 0. 前提
- shadcn/ui+Radix UI+Tailwind を使う  
- トークンは `global.css` の `:root` と `[data-mode="dark"]` に書く  
- Tailwind の `theme.extend` に `hsl(var(--token))` でマッピング  
- 既存設定は壊さずマージすること  

---

## 1. ユーザーに聞くこと
まだ情報が無ければ、下から順に一つずつ質問して答えを待つ。  
### ブランド基礎
1. ブランド / プロダクト名は?  
2. 主なユーザー層(年齢・業界)は?  
3. キーカラー(プライマリ/セカンダリ/アクセント)を教えて  
4. ダークモードいる? 基調色どうする?  
5. 使いたいフォント(和文/欧文)ある?  
6. 角丸の雰囲気:シャープ/ミディアム/大きめ?  
7. 影の強さ:なし/控えめ/がっつり?  

### レイアウト & 余白
8. 最大コンテンツ幅(px)は?(例: 1280)  
9. ブレークポイント変えたい?(sm〜2xl)  
10. スペーシングは 4px ステップ? 8px? カスタム?  

### コンポーネント仕様
11. フォーカスリングの色と太さは?  
12. デフォルトのトランジション時間(ms)は?  
13. ボタンの高さ: sm / md / lg で何pxずつ?  

### アクセシビリティ
14. 高齢者向け可読性や WCAG レベルで気にしてることある?  
15. 今後追加したいトークン範囲(例: グラフ色、通知色)は?  

---

## 2. トークン生成
- 回答をもとに CSS カスタムプロパティを `:root` に作成  
- カラーは HSL: `--primary`, `--primary-foreground`, `--border`, `--background`, `--foreground`, `--ring`, ほか必要分  
- ダークモードが要る場合は `[data-mode="dark"]` に反転 or 微調整版をコピー  

### 例
```css
:root {
  --primary: 166 72% 40%;
  --primary-foreground: 0 0% 100%;
  --border: 210 15% 90%;
}
```

---

## 3. 最終確認
- トークン重複がないか  
- コントラスト比が WCAG 目標を満たすか  
- Tailwind ビルドが成功するか  
- ハードコードされた色が残っていないか  

このルールを選択した状態で、Cursor Agentとのチャットを開始します。

すると、以下のようにデザインシステムを構築する上で必要な質問をされるのでそれに答えていきます。

今回はAlmondo社を顧客と想定して、デザインシステムを構築していきます。

最終的に生成されたデザイントークンがglobal.cssに反映されます。すると、shadcn/uiを使用しているため、一括で全てのページに反映されます。

改善後のUIは以下です。最初に生成したものよりも、明るい印象で「いかにもshadcn/ui使って作りました」感もなくだいぶ垢抜けた印象になりました。

また、一度デザインシステムが固まれば、今後追加されるコンポーネントは自動的にこのデザインを踏襲するようになるので特別な対応は不要で、shadcn/uiのCLIを実行するだけです。

4. Storybook上で確認

Storybookを使って、最終的な成果物をコンポーネントごとに状態別で確認できるようにします。コンポーネントを確認する中で、改善したいポイントが見つかった場合、StoryBookを確認しながらglobal.cssやユーティリティクラスの修正を行うことで、デザインシステムの細かい試行錯誤も可能です。

以下のコマンドでStorybookのセットアップを行います。

npm create storybook@latest

次に、今回作成された各コンポーネントに対応するstoriesファイルをCursorで生成していきます。

プロンプト

@components 配下のコンポーネントに対してStoryBookを適用してください。

コンポーネントごとに必ずDocsを生成すること。

こうして、各コンポーネントに対してStorybookの適用が完了すると、ブラウザ上でコンポーネント単位で確認できるようになります。


画面に依存しないatomsレベルのコンポーネント。上はテーブルコンポーネントの例

また、アトミックデザインで言うところのatoms単位のコンポーネントだけでなく、molecules以上のページに依存したコンポーネントについてもAPI連携部分などをモック化するなどでStoryBook上で確認できるような工夫は可能です。ページのデザインまで見たいと言う場合にはそのような対応がおすすめです。


画面に依存したコンポーネント。上はチャット画面の例

今後コンポーネントを追加するたびに、storiesファイルも同時に生成するようにすることで、継続的なデザイン運用が可能となります。

今回作成したRAG ChatシステムのStoryBookはこちらになります。

https://feature-frontend-rag-chat-app-using-shadcnui.df6ejaeqh6cwy.amplifyapp.com/

まとめ

本記事では、UI デザイン/フロントエンド開発において「コードでデザインをする」というv0やLovable などAIデザインツールによる開発体験に着目し、それを中〜大規模開発へ応用する手法として、Cursor・shadcn/ui・Storybook を組み合わせた事例をご紹介しました。

生成AIをシステム開発で活用する上では、AIのアウトプットをコントロールできるように「制約」を設けることが重要だと私は考えております。

今回は、shadcn/uiという「制約」(Tailwind CSSのユーティリティクラスを使用するという制約と、shadcnが用意しているコンポーネントを用いてデザインするという制約)を設けた上で、生成結果をStorybook上で容易に確認できる仕組みを取り入れることで、運用まで見据えた形を意識しました。

これにより、0→1のスピード感を保ちつつ、拡張性の高いデザインと継続的な運用体制が両立できるようになりました。特に、高度なデザイン性が求められない社内ツールなどのシステム開発においては有用だと思います。

最後に

Almondoでは現在、第二創業期を共に歩んでいただける仲間を募集しています。
おかげさまで、スタートアップから大企業まで、さまざまなバックグラウンドを持つエンジニアの方々にご興味を持っていただけるようになってきました!
上場企業のバックアップを受けつつも、スタートアップならではの柔軟さとスピード感を活かして、ユニークな立ち位置から新しい挑戦ができる環境です。

少しでも「面白そう」と感じたら、お気軽にご応募ください!

https://almondotech.notion.site/almondo-recruitment

2025年 5月31日 追記

v0でも、Githubとの同期ができるようになりました。

ただし、v0では単一のコードベースに対して、複数のチャットセッションをまたいだ開発は難しいという課題は残っているため、中規模以上のシステム開発においては引き続き課題が残ります。

https://x.com/v0/status/1927883135146152237

Almondo Tech Blog

Discussion