Claudeのコードスキルを活用してUIを構築する方法

Ashley Goolam

Ashley Goolam

21 1月 2026

Claudeのコードスキルを活用してUIを構築する方法

新しい機能ごとにUIコンポーネントをClaude Codeに手動で記述することは、クラスなしでCSSを書くようなもので、繰り返しが多く、一貫性がなく、チーム全体でスケールすることは不可能です。UI構築のためのClaude Codeスキルは、デザインシステムを実行可能なツールに変え、予測可能なパラメーターとボイラープレートなしでコンポーネント、レイアウト、スタイルを生成します。

UI構築のためのClaude Codeスキルとは?

Claude Codeスキルは、UI生成ロジックを再利用可能でバージョン管理されたツールとしてパッケージ化し、Claude CodeがModel Context Protocol (MCP) を介して発見・呼び出しできるようにします。「Tailwindで、左寄せの画像、右寄せのテキスト、プライマリボタンを持つレスポンシブなカードコンポーネントを作成してください」のような冗長なプロンプトを作成する代わりに、building-uiスキルを一度定義し、component: "card", layout: "image-left"のような簡潔なパラメーターで呼び出します。

各スキルは、以下を定義するSKILL.mdファイルで構成されています。

公式リポジトリのbuilding-uiスキルは、コンポーネント、レイアウト、テーマ、フォームのパターンを提供します。これにより、アドホックなUI生成が体系的で再現可能なプロセスに変わります。

claude code skills

素のプロンプトに対する主な利点

💡
美しいAPIドキュメントを生成する優れたAPIテストツールが欲しいですか?

最高の生産性で開発チームが協力して作業できる統合されたオールインワンプラットフォームが欲しいですか?

Apidogはあなたの全ての要求に応え、Postmanをはるかに手頃な価格で置き換えます
ボタン

building-uiスキルのセットアップ

ステップ1: Claude Codeをインストールし、MCPを有効にする

Claude Code CLIをまだインストールしていない場合:

npm install -g @anthropic-ai/claude-code
claude --version  # 2.0.70以上である必要があります

MCP設定ディレクトリとファイルを作成します:

# macOS/Linux
mkdir -p ~/.config/claude-code
touch ~/.config/claude-code/config.json

# Windows
mkdir %APPDATA%\claude-code
echo {} > %APPDATA%\claude-code\config.json
claude code

ステップ2: building-uiスキルをクローンしてビルドする

git clone https://github.com/anthropics/skills.git
cd skills/skills/building-ui
npm install
npm run build

これにより、TypeScriptハンドラがdist/index.jsにコンパイルされます。

ステップ3: スキルをロードするようにMCPを設定する

~/.config/claude-code/config.jsonを編集します:

{
  "mcpServers": {
    "building-ui": {
      "command": "node",
      "args": ["/absolute/path/to/skills/building-ui/dist/index.js"],
      "env": {
        "UI_LIBRARY": "react",
        "STYLE_SYSTEM": "tailwind",
        "THEME_CONFIG": "~/project/design-tokens.json"
      }
    }
  }
}

重要:

ステップ4: インストールを確認する

claude

ロードされたら、実行します:

/list-tools

次のように表示されるはずです:

Available tools:
- building-ui:generate-component
- building-ui:create-layout
- building-ui:apply-theme
- building-ui:generate-form

ツールが表示されない場合は、ログを確認してください:

# macOS/Linux
tail -f ~/.cache/claude-code/logs/mcp.log

# Windows
type %APPDATA%\claude-code\logs\mcp.log

よくある問題:

スキルを用いた主要なUI構築パターン

building-ui スキルは、4つの主要なツールをエクスポートします。それぞれが構造化されたパラメータを受け入れ、生成されたコードを返します。

1. コンポーネント生成ツール

ツール名: building-ui:generate-component
ユースケース: 再利用可能なUIコンポーネントを作成

パラメータ:

: バリアントを持つボタンを作成

generate-componentツールを使用して、primary、secondary、outlineのバリアント、サイズmedium、および無効状態のサポートを持つボタンコンポーネントを作成します。

生成された出力 (React + Tailwind):

// Button.tsx
import React from 'react';
import clsx from 'clsx';

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: 'primary' | 'secondary' | 'outline';
  size?: 'small' | 'medium' | 'large';
}

export const Button: React.FC<ButtonProps> = ({
  variant = 'primary',
  size = 'medium',
  disabled,
  children,
  className,
  ...props
}) => {
  const baseClasses = 'font-semibold rounded-lg transition-colors';
  const variantClasses = {
    primary: 'bg-blue-600 text-white hover:bg-blue-700',
    secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300',
    outline: 'border-2 border-blue-600 text-blue-600 hover:bg-blue-50'
  };
  const sizeClasses = {
    small: 'px-3 py-1.5 text-sm',
    medium: 'px-4 py-2 text-base',
    large: 'px-6 py-3 text-lg'
  };

  return (
    <button
      disabled={disabled}
      className={clsx(
        baseClasses,
        variantClasses[variant],
        sizeClasses[size],
        disabled && 'opacity-50 cursor-not-allowed',
        className
      )}
      {...props}
    >
      {children}
    </button>
  );
};

スキルは、環境変数に基づいてTypeScriptの型、アクセシビリティ属性、およびスタイリングクラスを推論します。

2. レイアウト作成ツール

ツール名: building-ui:create-layout
ユースケース: レスポンシブなページレイアウトを生成

パラメータ:

: レスポンシブなサイドバーを持つダッシュボードレイアウト

create-layoutを使用して、折りたたみ可能なサイドバー、ヘッダー、メインコンテンツエリア、フッターを備えたレスポンシブなダッシュボードレイアウトを生成します。gap-4を使用し、サイドバーをデスクトップでは幅256px、モバイルでは全幅にします。

生成された出力:

// DashboardLayout.tsx
import React, { useState } from 'react';
import clsx from 'clsx';

interface DashboardLayoutProps {
  header?: React.ReactNode;
  sidebar?: React.ReactNode;
  main: React.ReactNode;
  footer?: React.ReactNode;
}

export const DashboardLayout: React.FC<DashboardLayoutProps> = ({
  header,
  sidebar,
  main,
  footer
}) => {
  const [sidebarOpen, setSidebarOpen] = useState(false);

  return (
    <div className="min-h-screen flex flex-col">
      {/* Header */}
      <header className="bg-white shadow-sm border-b border-gray-200 z-10">
        <div className="px-4 sm:px-6 lg:px-8 py-4">
          {header}
        </div>
      </header>

      <div className="flex flex-1">
        {/* Mobile menu button */}
        <button
          className="lg:hidden fixed bottom-4 right-4 bg-blue-600 text-white p-3 rounded-full shadow-lg z-20"
          onClick={() => setSidebarOpen(!sidebarOpen)}
        >
          ☰
        </button>

        {/* Sidebar */}
        <aside className={clsx(
          'bg-gray-50 border-r border-gray-200',
          'fixed lg:relative inset-y-0 left-0 z-30',
          'w-64 transform transition-transform lg:translate-x-0',
          sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'
        )}>
          <div className="p-4">
            {sidebar}
          </div>
        </aside>

        {/* Main content */}
        <main className="flex-1 p-4 sm:p-6 lg:p-8">
          {main}
        </main>
      </div>

      {/* Footer */}
      {footer && (
        <footer className="bg-gray-50 border-t border-gray-200 mt-auto">
          <div className="px-4 sm:px-6 lg:px-8 py-4">
            {footer}
          </div>
        </footer>
      )}
    </div>
  );
};

スキルは、モバイルメニューロジック、ブレークポイント対応クラス、およびアクセシビリティ属性を自動的に追加します。

3. テーマ適用ツール

ツール名: building-ui:apply-theme
ユースケース: コンポーネント全体にデザインルールを適用

パラメータ:

: カードコンポーネントにダークテーマを適用

apply-themeを使用して、スレートカラーパレット、スペーシングスケール4、Interフォントファミリーでダークモード用のCardコンポーネントを設定します。

生成された出力:

// card-theme.ts
export const cardTheme = {
  light: {
    background: 'bg-white',
    border: 'border-gray-200',
    text: 'text-gray-900',
    subText: 'text-gray-600'
  },
  dark: {
    background: 'bg-slate-800',
    border: 'border-slate-700',
    text: 'text-slate-100',
    subText: 'text-slate-400'
  }
};

// Usage in Card.tsx
import { cardTheme } from './card-theme';

interface CardProps {
  variant?: 'light' | 'dark';
  children: React.ReactNode;
}

export const Card: React.FC<CardProps> = ({ variant = 'light', children }) => {
  const theme = cardTheme[variant];

  return (
    <div className={clsx(
      'rounded-lg p-4 border',
      theme.background,
      theme.border
    )}>
      {children}
    </div>
  );
};

スキルはTHEME_CONFIGファイルを読み取り、テーマ固有のトークンマップを生成します。THEME_CONFIGがJSONファイルを指している場合:

{
  "colors": {
    "primary": "#3B82F6",
    "secondary": "#6B7280"
  },
  "fonts": {
    "sans": "Inter",
    "mono": "JetBrains Mono"
  }
}

生成されたコードは、Tailwindのデフォルト値の代わりにこれらの正確な値を使用します。

4. フォーム生成ツール

ツール名: building-ui:generate-form
ユースケース: スキーマから検証済みフォームを作成

パラメータ:

: 検証機能付きユーザー登録フォーム

generate-formを使用して、フィールド: name (テキスト、必須)、email (メール、必須)、password (パスワード、最小長8)、acceptTerms (チェックボックス) を持つユーザー登録フォームを作成します。/api/registerにonBlurバリデーションで送信します。

生成された出力:

// UserRegistrationForm.tsx
import React, { useState } from 'react';
import { z } from 'zod';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm, SubmitHandler } from 'react-hook-form';

const schema = z.object({
  name: z.string().min(1, '名前は必須です'),
  email: z.string().email('無効なメールアドレスです'),
  password: z.string().min(8, 'パスワードは8文字以上である必要があります'),
  acceptTerms: z.boolean().refine(val => val === true, {
    message: '利用規約に同意する必要があります'
  })
});

type FormData = z.infer<typeof schema>;

export const UserRegistrationForm: React.FC = () => {
  const [isSubmitting, setIsSubmitting] = useState(false);

  const {
    register,
    handleSubmit,
    formState: { errors },
    trigger
  } = useForm<FormData>({
    resolver: zodResolver(schema),
    mode: 'onBlur'
  });

  const onSubmit: SubmitHandler<FormData> = async (data) => {
    setIsSubmitting(true);
    try {
      const response = await fetch('/api/register', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      });

      if (!response.ok) throw new Error('登録に失敗しました');

      // Handle success
      console.log('ユーザー登録済み:', await response.json());
    } catch (error) {
      console.error('登録エラー:', error);
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4 max-w-md">
      <div>
        <label htmlFor="name" className="block text-sm font-medium text-gray-700">
          Name
        </label>
        <input
          id="name"
          {...register('name')}
          className={clsx(
            'mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500',
            errors.name && 'border-red-500'
          )}
        />
        {errors.name && (
          <p className="mt-1 text-sm text-red-600">{errors.name.message}</p>
        )}
      </div>

      <div>
        <label htmlFor="email" className="block text-sm font-medium text-gray-700">
          Email
        </label>
        <input
          id="email"
          type="email"
          {...register('email')}
          className={clsx(
            'mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500',
            errors.email && 'border-red-500'
          )}
        />
        {errors.email && (
          <p className="mt-1 text-sm text-red-600">{errors.email.message}</p>
        )}
      </div>

      <div>
        <label htmlFor="password" className="block text-sm font-medium text-gray-700">
          Password
        </label>
        <input
          id="password"
          type="password"
          {...register('password')}
          className={clsx(
            'mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500',
            errors.password && 'border-red-500'
          )}
        />
        {errors.password && (
          <p className="mt-1 text-sm text-red-600">{errors.password.message}</p>
        )}
      </div>

      <div className="flex items-center">
        <input
          id="acceptTerms"
          type="checkbox"
          {...register('acceptTerms')}
          className="h-4 w-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
        />
        <label htmlFor="acceptTerms" className="ml-2 block text-sm text-gray-900">
          利用規約に同意します
        </label>
      </div>
      {errors.acceptTerms && (
        <p className="text-sm text-red-600">{errors.acceptTerms.message}</p>
      )}

      <button
        type="submit"
        disabled={isSubmitting}
        className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
      >
        {isSubmitting ? '登録中...' : '登録'}
      </button>
    </form>
  );
};

スキルは、react-hook-formzodバリデーション、アクセシビリティ属性、およびローディング状態を自動的に接続します。

高度な技術を使用した動的なUI生成

条件付きレンダリングロジック

一部のUIでは、パラメータに基づいて条件付きセクションが必要です。スキルはフィールド定義でconditionsをサポートしています:

"accountType"が"business"の場合にのみ"company"フィールドが表示されるユーザープロフィールフォームを生成します。

これにより、条件付きレンダリングを備えたフォームが生成されます:

{accountType === 'business' && (
  <div>
    <label htmlFor="company">会社</label>
    <input id="company" {...register('company')} />
  </div>
)}

コンポーネント構成

スキル呼び出しを連結して、複雑なUIを構築します:

まず、サイドバーとヘッダーを持つDashboardLayoutコンポーネントを生成します。次に、メトリクス用のStatCardコンポーネントを生成します。最後に、両方にダークテーマを適用します。

Claude Codeはこれらを順次実行し、呼び出し間でコンテキストを渡します。レイアウトコンポーネントはカードの生成時に利用可能であり、適切な統合を保証します。

実行時のテーマ切り替え

テーマ対応コードを出力するようにスキルを設定します:

{
  "building-ui": {
    "command": "node",
    "args": ["dist/index.js"],
    "env": {
      "UI_LIBRARY": "react",
      "STYLE_SYSTEM": "tailwind",
      "THEME_CONFIG": "~/project/themes.json",
      "SUPPORT_THEME_TOGGLE": "true"
    }
  }
}

これで、生成されたコンポーネントにはThemeProviderラッパーが含まれます:

// App.tsx
import { ThemeProvider } from './ThemeProvider';
import { DashboardLayout } from './DashboardLayout';

function App() {
  return (
    <ThemeProvider defaultTheme="light" enableSystem>
      <DashboardLayout />
    </ThemeProvider>
  );
}

UI構築スキルのデバッグと反復

.claude-cacheで生成されたコードを表示

Claude Codeはスキルの出力をキャッシュします。それらを検査してください:

# macOS/Linux
cat ~/.cache/claude-code/last-skill-output.tsx

# Windows
type %APPDATA%\claude-code\last-skill-output.tsx

生成されたコードが期待と一致しない場合は、パラメータを調整してください。より具体的に指定します:

次のようにする代わりに: 「カードを生成してください」
次のようにします: 「16pxのパディング、8pxのボーダーラディウス、そしてさりげないボックスシャドウを持つカードを生成してください」

プロジェクトごとのスキルデフォルトを上書きする

プロジェクトのルートに.claude-ui-config.jsonを作成します:

{
  "uiLibrary": "vue",
  "styleSystem": "css-modules",
  "themeConfig": "./design-tokens.json"
}

これは、そのプロジェクトに対してのみグローバルなMCP設定を上書きします。

スキルのバージョン管理

building-uiスキルを更新する際は、バージョンをタグ付けします:

cd skills/building-ui
npm version patch  # またはminor/major
git tag -a v1.1.0 -m "Added support for Vue 3.5"

バージョンを固定するためにClaude Codeの設定を更新します:

{
  "mcpServers": {
    "building-ui": {
      "command": "node",
      "args": ["/path/to/skills/building-ui-v1.1.0/dist/index.js"]
    }
  }
}

これにより、互換性のない変更が本番ワークフローに影響を与えるのを防ぎます。

結論

UI構築のためのClaude Codeスキルは、自然言語を手術のような正確さで、本番環境対応のコンポーネント、レイアウト、テーマ、フォームに変換します。セットアップに15分投資するだけで、デザインの一貫性を強制し、ボイラープレートを排除し、機能開発を加速する再利用可能なツールキットを手に入れることができます。generate-component、create-layout、apply-theme、generate-formの4つのコアツールから始めて、特定のデザインシステムに合わせて拡張してください。

スキルがAPIを利用するUIを生成する際には、Apidogでそれらのエンドポイントを検証し、AIが構築したインターフェースが信頼できるバックエンドと通信することを保証してください。

ボタン

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる