🎨

AIとの開発を快適に ― 個人開発で実践したUI設計Tips集

に公開

はじめに

AIツール(ChatGPT、GitHub Copilot、Cursor等)を活用した開発では、適切な指示を出すことで最初から実用的なコードを生成してもらうことができます。

この記事では、個人開発プロジェクト「TechSeek」での実践例を通じて、AIツール活用時の設計アプローチと具体的な指示方法を紹介します。

こんな方におすすめ

  • AIツールを活用した開発に取り組んでいる方
  • 個人開発でUI/UXの品質向上を図りたい方
  • 効率的なフロントエンド開発手法を学びたい方

TechSeekとは

TechSeekは、技術書の検索機能を提供するWebアプリケーションです。現在約100冊の技術書データを扱っており、今後さらにデータを増やしていく予定です。

TechSeekの検索画面

  • 技術スタック:
    • フロントエンド: Next.js 15(BFF・SSR), React 19, TypeScript, vanilla-extract, SWR, Zustand, aspida
    • バックエンド: Rails 8 API, SQLite, ActiveAdmin, Sidekiq, rswag
    • 外部API: OpenAI API, 楽天Books API
    • インフラ: ConoHa VPS, Kamal(Dockerデプロイ), Cloudflare CDN
    • テスト: RSpec, Vitest, React Testing Library, MSW
    • 開発環境: Storybook, ESLint, Prettier, RuboCop, Ruby LSP

こんな課題を解決したかった

例えば、こんな指示を出すと:

不適切な指示例:
"ボタンを作ってください"

↓ 生成されるコード

<button style={{ backgroundColor: 'blue', color: 'white' }}>
  ボタン
</button>

主な課題:

  • 一貫性のないコードが生成される
  • 再利用性が低い
  • プロジェクト全体の統一感が保てない

これらの課題へのアプローチとして、TechSeekプロジェクトで実践したUI設計Tipsを紹介します。

Tips 1: デザイントークンの定義

デザイントークンとは

デザイントークンは、色やサイズ、余白などのデザイン要素を体系的に管理するための仕組みです。AIツールとの協働では、定義されたトークンに基づいて一貫性のあるスタイリングを生成しやすくなります。

デザイントークンの詳細についてはデザイントークンとは - CodeGridを参考にしています。

定義したトークンカテゴリ

TechSeekプロジェクトでは、以下8つのカテゴリでデザイントークンを管理しています:

  • spacing: 余白・間隔
  • color: カラーパレット
  • fontSize: フォントサイズ
  • radius: 角丸
  • boxShadow: 影
  • fontFamily: フォントファミリー
  • breakpoint: レスポンシブブレークポイント
  • zIndex: 重ね順管理

spacing: 8pxベースシステム

値設定: xxs: 2px | xs: 4px | sm: 8px | md: 16px | lg: 24px | xl: 32px | xxl: 48px | xxxl: 64px

採用理由:

  • 8の倍数なので計算時に端数が出にくい(8×1.5=12pxなど)
  • 様々な画面サイズ(1920px、1280pxなど)に適応しやすい

4pxは8の倍数ではありませんが、タグやバッジ、アイコンとテキストの間で使用すると見た目のバランスが良くなるため、用意しています。

参考: なぜ8pxグリッドシステムがUIデザインの標準となっているのか

color: ブルー系メインカラー

値設定: blue: #4790bb | black: #333 | lightBlue: #7cb4c8 | gray: #666 | white: #fff

ブルーをメインカラーに採用した理由:

  • 信頼性・安定性を表現する色彩心理
  • IT・テック系での一般的な使用

黒を#333にしている理由:

  • 純粋な黒(#000)は画面で目に負担がかかる
  • より自然で読みやすいダークグレー

カラーパレット:

  • メインボタン: blue (#4790bb)
  • サブボタン: lightBlue (#7cb4c8)
  • 見出し: black (#333)
  • 補足説明: gray (#666)
  • 背景: white (#fff)

命名戦略: 理想的なprimary等の意味的命名も検討したが、デザインシステムの知識不足による破綻リスクを避けてblueblackgrayなどの色名を採用。

参考: より良いUXを提供しよう!:色彩心理学を活用したウェブデザイン

fontSize: 階層構造を意識した視認性と使いやすさの両立

値設定: xs: 12px | sm: 14px | md: 16px | lg: 24px | xl: 32px

基本方針:

役割 サイズ 主な用途
xl (32px) 32px メインタイトル(ページタイトルなど)
lg (24px) 24px セクション見出し
md (16px) 16px 本文(標準サイズ)
sm (14px) 14px 補助テキスト(キャプションなど)
xs (12px) 12px 注釈、補足情報

採用理由:

  • 16pxを標準サイズ:Googleが推奨、ユーザーが読み慣れている、PCとスマホで統一可能
  • 12pxを最小サイズ:視認性を保ちつつ補足情報を控えめに表示

参考:

デザイントークン実装例

デザイントークン定義

実際のTechSeekプロジェクトのデザイントークン定義
export const tokens = {
  boxShadow: {
    lg: '0 4px 8px rgba(0, 0, 0, 0.15)',
    md: '0 2px 4px rgba(0, 0, 0, 0.1)',
    sm: '0 1px 2px rgba(0, 0, 0, 0.05)',
    xl: '0 8px 16px rgba(0, 0, 0, 0.2)',
  },
  breakpoint: {
    pc: '1024px',
  },
  color: {
    black: '#333',
    blue: '#4790bb',
    darkBlue: '#2a5772',
    gray: '#666',
    lightBlue: '#7cb4c8',
    lightGray: '#e0e0e0',
    lightLightBlue: '#e6f0f4',
    lightLightGray: '#f5f5f5',
    navy: '#1e3a8a',
    orange: '#f97316',
    white: '#fff',
  },
  fontFamily: {
    ibmPlex: '"IBM Plex Sans JP", sans-serif',
    notoSans: '"Noto Sans JP", sans-serif',
  },
  fontSize: {
    lg: '24px',
    md: '16px',
    sm: '14px',
    xl: '32px',
    xs: '12px',
  },
  radius: {
    full: '9999px',
    lg: '12px',
    md: '8px',
    sm: '4px',
    xl: '16px',
  },
  spacing: {
    lg: '24px',
    md: '16px',
    sm: '8px',
    xl: '32px',
    xs: '4px',
    xxl: '48px',
    xxxl: '64px',
  },
  zIndex: {
    modal: '9999',
  },
} as const;

デザイントークン用 AIへの指示ルール設定例

実際のTechSeekプロジェクトのAIへの指示ルール設定例
# デザイントークン管理ルール

デザイントークンの定義と運用に関するルールです。  
実装時には必須ルールを参考にし、レビュー時にはチェックリストを活用して確認します。

## 必須ルール(実装時に参照)

- トークンは `src/styles/tokens.css.ts` で一元管理する
- 新しい色・サイズは必ずトークンに定義してから使用する
- コンポーネントでは定義済みトークンのみを参照する
- ハードコード値は禁止
- 命名は統一されたルールに基づくこと
- 色はアクセシビリティ基準(WCAG 2.1 AA)を満たすこと

## チェックリスト(レビュー時に参照)

- [ ] トークンが `src/styles/tokens.css.ts` で一元管理されている  
- [ ] 新しい色・サイズがトークンに追加されている  
- [ ] コンポーネントが定義済みトークンを使用している  
- [ ] ハードコード値が残っていない  
- [ ] 命名規則に一貫性がある  
- [ ] コントラスト比などアクセシビリティ基準を満たしている  

Tips 2: 5つの層で整理するコンポーネントディレクトリ構成

ディレクトリ設計の重要性

AIツールに「コンポーネントを作って」と指示すると、どこに配置すべきか迷ってしまい、適当な場所に作ってしまうことがある。5つの層という明確なルールを決めておけば、AIも迷わずに適切な場所にコンポーネントを配置できるようになる。

5つの層による構成

src/
├── components/
│   ├── base/         # 第1層:基本UI要素(最小単位・再利用最優先)
│   ├── patterns/     # 第2層:複合パターン(汎用的な組み合わせ)
│   ├── pages/        # 第3層:ページ固有UI(特定ページ専用)
│   └── layouts/      # 第4層:レイアウト(ページ全体構造)
└── features/         # 第5層:機能別コード集約
    └── [feature]/    # 例: book, search, user
        ├── components/
        ├── hooks/
        ├── types/
        └── api/

AI活用の基本方針

  • 基本コンポーネント(Base層)のみを事前に用意
  • Pages/Features層では新規コンポーネント生成を許可、Patterns層は既存Base層の組み合わせで構成
  • AIには既存コンポーネントを優先的に組み合わせるよう指示 → 余計なスタイル追加を防ぐ
  • 完成イメージを見せれば、既存サイトの雰囲気に合わせてUIを生成

5つの層の詳細

Base層(第1層)- 基本UI要素

  • 配置: components/base/
  • 内容: Box, Text, Button, Input, Image, Icon, Tag, Link
  • 役割: UIの基本要素
  • ライブラリ統合: 外部ライブラリ(アニメーション、アイコン等)はBase層でのみ導入(付け替えが容易で影響範囲が限定される)

Patterns層(第2層)- 汎用パターン

  • 配置: components/patterns/
  • 内容: Modal, Dropdown, Tabs, Accordion, Table, Toast
  • 役割: Baseを組み合わせた汎用的なUIパターン

Pages層(第3層)- ページ固有UI

  • 配置: components/pages/
  • 内容: HeroSection, PricingTable, ContactForm など
  • 役割: 特定ページ専用のUI、Base/Patternsを活用

Layouts層(第4層)- ページ構造

  • 配置: components/layouts/
  • 内容: Header, Footer, Sidebar, MainLayout
  • 役割: ページ全体の構造定義、グローバルナビゲーション

Features層(第5層)- 機能別集約

  • 配置: features/[feature]/
  • 内容: components/, hooks/, types/, api/ で機能を完結
  • 役割: 特定機能に関連する全てのコードを集約
  • 参考: bulletproof-reactの設計思想

実装時の設計原則

基本ルール

  1. インラインスタイル完全禁止 - style属性は使わない
  2. 既存コンポーネント優先活用 - 新規作成前に必ず既存確認
  3. 1ファイル1コンポーネント - 複数コンポーネントの混在禁止

配置判断フロー

新しいコンポーネントを作成する際の判断基準:

  1. これ以上分解できない基本要素?Base層
  2. 複数のBaseの組み合わせで汎用的?Patterns層
  3. ページ全体の構造・レイアウト?Layouts層
  4. 特定ページでのみ使用?Pages層
  5. 特定機能のドメインロジック含む?Features層

TechSeekプロジェクトでの5層設計実装例

ディレクトリ構造の設計

実際のTechSeekプロジェクトのディレクトリ構造
src/
├── components/
│   ├── base/                    # 第1層:基本UI要素
│   │   ├── Box.tsx
│   │   ├── Text.tsx
│   │   ├── Button.tsx
│   │   ├── Input.tsx
│   │   ├── Image.tsx
│   │   ├── Icon.tsx
│   │   └── Tag.tsx
│   ├── patterns/                # 第2層:汎用パターン
│   │   ├── Modal.tsx
│   │   ├── Tabs.tsx
│   │   ├── Accordion.tsx
│   │   ├── Table.tsx
│   │   └── Toast.tsx
│   ├── pages/                   # 第3層:ページ固有UI
│   │   ├── home/
│   │   │   └── HeroSection.tsx
│   │   ├── contact/
│   │   │   └── ContactForm.tsx
│   └── layouts/                 # 第4層:レイアウト
│       ├── Header.tsx
│       ├── Footer.tsx
│       ├── Sidebar.tsx
│       └── MainLayout.tsx
└── features/                    # 第5層:機能別集約
    ├── book/
    │   ├── components/
    │   │   ├── BookCard.tsx
    │   │   ├── BookList.tsx
    │   │   └── BookSearch.tsx
    │   ├── hooks/
    │   │   ├── useBook.ts
    │   │   └── useBookmark.ts
    │   ├── types/
    │   │   └── types.ts
    │   └── api/
    │       └── api.ts
    ├── search/
    │   ├── components/
    │   ├── hooks/
    │   ├── types/
    │   └── api/
    └── user/
        ├── components/
        ├── hooks/
        ├── types/
        └── api/

5層設計用 AIへの指示ルール設定例

実際のTechSeekプロジェクトのAIへの指示ルール設定例
# コンポーネント設計ルール

コンポーネント設計でスケーラブルなReactアプリケーションを構築する実践的なガイドラインです。

## AIへの指示原則

### 3つの鉄則

1. インラインスタイル完全禁止 - `style`属性は使わない
2. 既存コンポーネント優先活用 - 新規作成前に必ず既存確認
3. 1ファイル1コンポーネント - 複数コンポーネントの混在禁止

### アーキテクチャ

```text
src/components/
├── base/         # 基本UI(外部ライブラリ使用可)
├── patterns/     # 複合パターン
├── layouts/      # レイアウト構造
└── pages/        # ページ専用UI

src/features/{domain}/components/  # ドメイン固有(最小CSS)

実装優先順位

1. 既存コンポーネントチェック(最優先)

// ✅ 推奨: 既存活用
<Box direction="column" gap="lg">
  <Text as="h1" size="xl" text="タイトル" />
  <Button variant="primary" text="送信" />
</Box>

// ❌ 禁止: インラインスタイル
<div style={{ display: 'flex', flexDirection: 'column' }}>
  <h1 style={{ fontSize: '32px' }}>タイトル</h1>
</div>

3. 層別制限

外部ライブラリ 責務
Base ✅ 許可 基本UI要素
Patterns ❌ Base層のみ 複合パターン
Layouts ❌ Base層のみ レイアウト
Features ❌ 最小CSS ドメイン固有

主要コンポーネント

Base層

  • Box: レイアウト・コンテナ
  • Text: 全テキスト表示
  • Button: ボタン・アクション
  • Input: フォーム入力
  • Icon: アイコン表示

Patterns層

  • Modal: ダイアログ・ポップアップ
  • Pagination: ページネーション
  • Tooltip: 補足情報表示

よくある間違い

❌ カスタムCSSの過剰使用

// features/book/styles.css.ts
export const card = style({
  display: 'flex',        // Boxで対応可能
  flexDirection: 'column', // Boxで対応可能
  gap: '16px',           // Boxで対応可能
});

✅ 既存コンポーネント活用

<Box direction="column" gap="md" padding="lg">
  <Text as="h2" text={book.title} />
  <Text size="sm" text={book.author} />
</Box>

コンポーネント配置の判断基準

新しいコンポーネントを作成する際の判断基準:

  1. これ以上分解できない基本要素?Base層
  2. 複数のBaseの組み合わせで汎用的?Patterns層
  3. ページ全体の構造・レイアウト?Layouts層
  4. 特定ページでのみ使用?Pages層
  5. 特定機能のドメインロジック含む?Features層

実装チェックリスト

基本確認

  • 既存コンポーネントで要件満たせないか確認
  • インラインスタイル使用していない
  • 適切な層に配置されている
  • TypeScript型定義済み
  • 1ファイル1コンポーネント原則を守っている

依存関係確認

  • Base層が他の層を使用していない
  • Patterns層がBase層のみを使用している
  • Layouts層がBase、Patterns層のみを使用している
  • Pages層がBase、Patterns、Features層のみを使用している
  • Features層がBase、Patterns層のみを使用している

ファイル構造確認

  • ファイル名が index.tsx である
  • Features層で components/, hooks/, types/, api/ が分離されている
  • 外部ライブラリがBase層でのみ使用されている

この設計により、保守性・再利用性・一貫性を備えたコンポーネントシステムを構築できます。


まとめ

AIツールとの協働でUI開発を進める際に試してみた2つのTipsを紹介しました。

今回紹介したTips

Tips 1: デザイントークンの定義

色・サイズ・余白を体系的に管理することで、AIが生成するスタイリングに一貫性を持たせやすくしています:

  • 8pxベースシステム: 計算時に端数が出にくく、様々な画面サイズに適応しやすい
  • ブルー系カラーパレット: IT・テック系で使われることが多い配色
  • 16px基準フォントサイズ: 読みやすさを考慮した標準的なサイズ
  • cursorルール設定: デザイントークン管理のルールとチェックリストの例

Tips 2: 5層コンポーネント構成

コンポーネントの配置場所を明確にすることで、AIへの指示がしやすくなります:

  • Base層: 基本UI要素(Box, Text, Button等)、外部ライブラリはここのみ使用
  • Patterns層: 汎用的な複合パターン(Modal, Tabs等)
  • Pages層: ページ固有のUI(HeroSection, ContactForm等)
  • Layouts層: ページ全体の構造(Header, Footer, MainLayout等)
  • Features層: ドメイン固有のコード集約(components, hooks, types, api)

実践してみた結果

TechSeekプロジェクトでこれらを試したところ:

  • デザイントークンにより、ある程度統一感のあるUIになった
  • 明確なルールにより、AIへの指示が出しやすくなった
  • 既存コンポーネント優先で、冗長なコードが減った

最後に

個人開発でも、これらのTipsを試してみると、AIツールとの協働がスムーズになり、一貫性のあるUI開発ができるようになりました。

今後も実践を通じて新しいTipsを発見し、どんどん追加していきたいと思います。

Discussion