前回の記事の続きです。
Vibe Coding に最適な Next.js と Claude Code に向けて、UX デザイン設計ガイドを整理します。
dApps 開発の実知見を基に、 「仮説検証期における MVP 開発」 を想定したデザインシステムです。
デザイナーのアサインを省略しながら、エンジニアと PdM だけで及第点の UX デザインを可能にする ことを企図しています。
対象読者
本記事は以下のような方にお勧めです。
- 効率的なAI開発フローを模索したいエンジニア
- 技術選定に悩んでいるPM
- 素早くMVPを開発したいハッカソン参加者
特に、最速で仮説検証用MVPを開発したい方に有用です。あるいはソロプレナーなど。
また、FBやTipsをシェアは大歓迎なので、ぜひお気軽にコメントしてください。「ここはバッドプラクティスでは?」などのツッコミもぜひ。
docs/ui-design-system.md
# Web3 dApps UI Design Guide
## Core Principles
- Minimal and meaningful color usage in UI
- NFTs and tokens are the main focus, UI is supporting
- Use only functional colors, not decorative ones
## Color System
### 1. Neutral Colors (95% of UI)
| Purpose | Tailwind |
| ---------------- | ---------------------- |
| Background | `white`, `gray-50` |
| Text (Primary) | `black`, `gray-900` |
| Text (Secondary) | `gray-500`, `gray-600` |
| Borders | `gray-200`, `gray-300` |
### 2. Semantic Colors
| Meaning | Purpose | Tailwind |
| ------- | ---------------------------- | ------------ |
| Success | Wallet connected, TX success | `green-600` |
| Warning | High gas, caution | `yellow-400` |
| Error | Failed, high risk | `red-500` |
| Info | Tips, supplementary | `blue-500` |
### 3. Interaction States
| State | Implementation |
| -------- | -------------------------------------- |
| Normal | `bg-black text-white` |
| Hover | `hover:bg-gray-900 hover:shadow-sm` |
| Disabled | `bg-gray-300 text-gray-500 opacity-50` |
| Loading | `opacity-50` + `animate-spin` |
## Implementation Patterns
### Header & Navigation
```tsx
<header className="sticky top-0 z-40 border-b border-gray-200 bg-white/95 backdrop-blur">
<div className="container mx-auto px-4">
<div className="flex h-16 items-center justify-between">
<Logo />
<Navigation />
<WalletButton />
</div>
</div>
</header>
```
Navigation states:
- Active: `bg-black text-white`
- Hover: `hover:bg-gray-100`
- Focus: `focus:ring-2 focus:ring-gray-400`
### Wallet Button
```tsx
<Button
className={`
${
isConnected
? "bg-green-600 hover:bg-green-700"
: "bg-black hover:bg-gray-800"
} text-white transition-all duration-200
`}
>
{isConnecting ? (
<>
<Zap className="mr-2 h-4 w-4 animate-spin" />
Connecting...
</>
) : isConnected ? (
<>
<CheckCircle className="mr-2 h-4 w-4" />
{formatAddress(address)}
</>
) : (
<>
<Wallet className="mr-2 h-4 w-4" />
Connect Wallet
</>
)}
</Button>
```
### Mint Button
```tsx
<Button
onClick={handleMint}
disabled={!isValid || isMinting}
className="w-full bg-black hover:bg-gray-800 text-white"
size="lg"
>
{isMinting ? (
<>
<Zap className="mr-2 h-5 w-5 animate-spin" />
Minting NFT...
</>
) : (
"Mint NFT"
)}
</Button>
```
### Loading States
```tsx
// Processing
<div className="text-center p-3 bg-gray-50 border border-gray-200 rounded-lg">
<div className="text-sm text-black">🔄 Processing transaction...</div>
<div className="text-xs text-gray-600 mt-1">Gas: {gasEstimate}</div>
</div>
// Error state
<div className="text-center p-4 bg-red-50 border border-red-200 rounded-lg">
<div className="text-sm text-red-600 font-medium mb-2">
Minting Failed (Attempt {retryCount}/{maxRetries})
</div>
<div className="text-sm text-red-500 mb-3">{errorMessage}</div>
<Button className="text-yellow-700 border-yellow-300 hover:bg-yellow-50">
<Zap className="mr-1 h-3 w-3" />
Retry
</Button>
</div>
// Success state
<div className="w-24 h-24 bg-gradient-to-br from-green-100 to-green-200 rounded-full flex items-center justify-center mx-auto mb-6 shadow-lg">
<CheckCircle className="h-14 w-14 text-green-600" />
</div>
<h1 className="text-3xl font-bold text-black mb-4">
🎉 Successfully Minted!
</h1>
```
### Risk Level Display
```tsx
const getRiskColor = (level: string) => {
const colors = {
High: "text-red-600 bg-red-100",
"Medium-High": "text-orange-600 bg-orange-100",
Medium: "text-yellow-600 bg-yellow-100",
Low: "text-green-600 bg-green-100",
};
return colors[level] || "text-gray-600 bg-gray-100";
};
```
## Tech Stack
- Next.js + Tailwind CSS + shadcn/ui
- Zustand for global state management
- react-hook-form for form validation
- TypeScript enforcement
## Design Rules
- Light Mode only (no Dark Mode)
- Images allowed only for NFTs, token icons, and logos
- Animations under 200ms
- Icons + text for accessibility
### Responsive Design
```tsx
// Mobile-first approach
<div className="hidden md:flex items-center space-x-6">
<Navigation />
</div>
<div className="md:hidden flex items-center space-x-2">
<MobileButton />
</div>
```
## Tailwind Theme Configuration
```ts
theme: {
colors: {
neutral: {
background: "#ffffff",
surface: "#f4f4f4",
border: "#e5e7eb",
text: "#000000",
subtext: "#6b7280"
},
semantic: {
success: "#16A34A",
warning: "#FACC15",
danger: "#EF4444",
info: "#3B82F6"
},
state: {
primary: "#000000",
onPrimary: "#ffffff",
disabled: "#d1d5db"
}
}
}
```
## Benefits
- High usability: Intuitive wallet connection flow
- Consistent UX: Unified experience across all screen sizes
- Maintainability: shadcn/ui + Tailwind combination
- Scalability: Component separation and Zustand utilization
docs/ja/ui-design-system.md
# Web3 dApps UI デザインガイド
## 基本原則
- UI の色は最小限かつ意味駆動
- NFT やトークンが主役、UI は脇役
- 装飾ではなく役割ある色のみ使用
## カラーシステム
### 1. ニュートラルカラー(95%を占める)
| 用途 | Tailwind |
| -------------- | ---------------------- |
| 背景 | `white`, `gray-50` |
| テキスト(主) | `black`, `gray-900` |
| テキスト(副) | `gray-500`, `gray-600` |
| ボーダー | `gray-200`, `gray-300` |
### 2. セマンティックカラー
| 意味 | 用途 | Tailwind |
| ------ | ---------------------- | ------------ |
| 成功 | Wallet 接続済、TX 成功 | `green-600` |
| 警告 | 高ガス、注意事項 | `yellow-400` |
| エラー | 失敗、高リスク | `red-500` |
| 情報 | Tips、補足 | `blue-500` |
### 3. インタラクションステート
| 状態 | 実装 |
| -------- | -------------------------------------- |
| 通常 | `bg-black text-white` |
| hover | `hover:bg-gray-900 hover:shadow-sm` |
| disabled | `bg-gray-300 text-gray-500 opacity-50` |
| loading | `opacity-50` + `animate-spin` |
## Web3 dApps における共通 UI パターンと色運用
## 実装パターン
### Header & Navigation
```tsx
<header className="sticky top-0 z-40 border-b border-gray-200 bg-white/95 backdrop-blur">
<div className="container mx-auto px-4">
<div className="flex h-16 items-center justify-between">
<Logo />
<Navigation />
<WalletButton />
</div>
</div>
</header>
```
ナビゲーション状態:
- アクティブ: `bg-black text-white`
- ホバー: `hover:bg-gray-100`
- フォーカス: `focus:ring-2 focus:ring-gray-400`
### Wallet Button
```tsx
<Button
className={`
${
isConnected
? "bg-green-600 hover:bg-green-700"
: "bg-black hover:bg-gray-800"
} text-white transition-all duration-200
`}
>
{isConnecting ? (
<>
<Zap className="mr-2 h-4 w-4 animate-spin" />
Connecting...
</>
) : isConnected ? (
<>
<CheckCircle className="mr-2 h-4 w-4" />
{formatAddress(address)}
</>
) : (
<>
<Wallet className="mr-2 h-4 w-4" />
Connect Wallet
</>
)}
</Button>
```
### Mint Button
```tsx
<Button
onClick={handleMint}
disabled={!isValid || isMinting}
className="w-full bg-black hover:bg-gray-800 text-white"
size="lg"
>
{isMinting ? (
<>
<Zap className="mr-2 h-5 w-5 animate-spin" />
Minting NFT...
</>
) : (
"Mint NFT"
)}
</Button>
```
### Loading States
```tsx
// プロセス中
<div className="text-center p-3 bg-gray-50 border border-gray-200 rounded-lg">
<div className="text-sm text-black">🔄 Processing transaction...</div>
<div className="text-xs text-gray-600 mt-1">Gas: {gasEstimate}</div>
</div>
// エラー状態
<div className="text-center p-4 bg-red-50 border border-red-200 rounded-lg">
<div className="text-sm text-red-600 font-medium mb-2">
Minting Failed (Attempt {retryCount}/{maxRetries})
</div>
<div className="text-sm text-red-500 mb-3">{errorMessage}</div>
<Button className="text-yellow-700 border-yellow-300 hover:bg-yellow-50">
<Zap className="mr-1 h-3 w-3" />
Retry
</Button>
</div>
// 成功状態
<div className="w-24 h-24 bg-gradient-to-br from-green-100 to-green-200 rounded-full flex items-center justify-center mx-auto mb-6 shadow-lg">
<CheckCircle className="h-14 w-14 text-green-600" />
</div>
<h1 className="text-3xl font-bold text-black mb-4">
🎉 Minted!
</h1>
```
### Risk Level Display
```tsx
const getRiskColor = (level: string) => {
const colors = {
High: "text-red-600 bg-red-100",
"Medium-High": "text-orange-600 bg-orange-100",
Medium: "text-yellow-600 bg-yellow-100",
Low: "text-green-600 bg-green-100",
};
return colors[level] || "text-gray-600 bg-gray-100";
};
```
## 技術スタック
- Next.js + Tailwind CSS + shadcn/ui
- zustand でグローバルステート管理
- react-hook-form でフォームバリデーション
- TypeScript 強制
## 設計ルール
- Light Mode 専用(Dark Mode なし)
- 画像は NFT・トークンアイコン・ロゴのみ許可
- アニメーションは 200ms 以下
- アイコン + テキストでアクセシビリティ確保
### レスポンシブ対応
```tsx
// モバイルファーストアプローチ
<div className="hidden md:flex items-center space-x-6">
<Navigation />
</div>
<div className="md:hidden flex items-center space-x-2">
<MobileButton />
</div>
```
## Tailwind Theme 設定
```ts
theme: {
colors: {
neutral: {
background: "#ffffff",
surface: "#f4f4f4",
border: "#e5e7eb",
text: "#000000",
subtext: "#6b7280"
},
semantic: {
success: "#16A34A",
warning: "#FACC15",
danger: "#EF4444",
info: "#3B82F6"
},
state: {
primary: "#000000",
onPrimary: "#ffffff",
disabled: "#d1d5db"
}
}
}
```
## 効果
- 高いユーザビリティ: 直感的な Wallet 接続フロー
- 一貫した UX: 全画面サイズでの統一感
- 保守性: shadcn/ui + Tailwind の組み合わせ
- 拡張性: コンポーネント分割と zustand 活用
参考
シリーズ記事
Claude Codeを使用した開発フロー(特にdApps)に最適なテンプレートを構築中で、各項目についてメモを残しています。
- Claude Code x MVP開発に最適なdApps要求定義
- Claude Code x MVP開発に最適なNext.jsディレクトリ構成
- Claude Code x MVP開発に最適なUXデザインガイド
- Claude Code x MVP開発に最適なNext.jsの状態管理パターン [Zustand, React Hook Form, TanStack Query]
- Claude Code x MVP開発の作業フロー(のメモ)
- AO dApps × Next.jsのnpmライブラリ選定 [2025年]
- EVM dApps x Next.jsのnpmライブラリ選定 [2025 年]
- Solana dApps × Next.jsのnpmライブラリ選定 [2025年]
参考文献
『LLMのプロンプトエンジニアリング ―GitHub Copilotを生んだ開発者が教える生成AIアプリケーション開発』
『生成AIのプロンプトエンジニアリング ―信頼できる生成AIの出力を得るための普遍的な入力の原則』
『開発者とアーキテクトのためのコミュニケーションガイド ―パターンで学ぶ情報伝達術』