Read OSS

プロジェクト初期化:空のディレクトリから設定済みコンポーネントシステムへ

中級

前提知識

  • 第1回:architecture-overview
  • Reactプロジェクトのセットアップに関する基本的な知識
  • pnpm workspacesの理解(モノレポセクション向け)

プロジェクト初期化:空のディレクトリから設定済みコンポーネントシステムへ

第2〜4回の内容は、components.json が存在するプロジェクトを前提としています。このファイルがどのように作成されるのかを説明するのが、今回の記事です。init コマンドは shadcn/ui の中でも最もインタラクティブな部分です。フレームワークを自動検出し、プリセットの選択を促し、テンプレートから新しいプロジェクトをスキャフォールドし、コンポーネントシステムを設定します。さらに、もう1つの役割もあります。設定ファイルが存在しない状態で add コマンドを実行すると、自動的に init が起動する仕組みになっています。

initコマンド:処理の流れ

init コマンドは create というエイリアスも持ち、設定フラグとともにコンポーネントを可変長引数として受け取ります。処理フローは複数の分岐を持ちます:

flowchart TD
    A["shadcn init"] --> B{Has components.json?}
    B -->|Yes| C{--force flag?}
    C -->|No| D["Prompt: overwrite?"]
    C -->|Yes| E["Continue with force"]
    B -->|No| F{Has package.json?}
    F -->|No| G["Scaffold new project"]
    F -->|Yes| H["Configure existing project"]
    G --> I["Select template"]
    I --> J["Select base: Radix or Base UI"]
    J --> K["Select preset"]
    K --> L["runInit()"]
    H --> M["Detect framework"]
    M --> J
    D -->|Yes| N["Backup existing config"]
    N --> L

components.json のバックアップ機能(131〜141行目)は、初期化の失敗からプロジェクトを守ります。処理がクラッシュしたりユーザーが中断した場合、process.on("exit") ハンドラーがバックアップを復元します。init プロセスはプリフライトチェックの前に components.json を一時的に削除するため、このバックアップ機能は欠かせません。

また、コマンドはモノレポのルートも検出します。components.json のないワークスペースルートにいる場合、特定のワークスペースパッケージで init を実行するよう案内し、利用可能なターゲットの一覧を表示します。

フレームワーク検出

FRAMEWORKS オブジェクトには、認識される11のフレームワークが定義されています。検出は getProjectInfo 内で行われ、複数のチェックが並列で実行されます:

flowchart TD
    A["getProjectInfo(cwd)"] --> B["glob for config files"]
    A --> C["Check src/ directory"]
    A --> D["Check TypeScript"]
    A --> E["Find tailwind config"]
    A --> F["Detect Tailwind version"]
    A --> G["Read tsconfig alias prefix"]
    A --> H["Read package.json"]
    B --> I{next.config.*?}
    I -->|Yes + app dir| J["next-app"]
    I -->|Yes + pages dir| K["next-pages"]
    B --> L{vite.config.*?}
    L -->|Yes| M["vite"]
    B --> N{astro.config.*?}
    N -->|Yes| O["astro"]
    B --> P{react-router.config.*?}
    P -->|Yes| Q["react-router"]
    B --> R{composer.json?}
    R -->|Yes| S["laravel"]

検出に使用する glob(**/{next,vite,astro,app}.config.*|gatsby-config.*|composer.json|react-router.config.*)は node_modules を除外しながら最大3階層まで検索します。結果は ProjectInfo 構造体として返され、フレームワーク・TypeScript の有無・Tailwind のバージョン・エイリアスのプレフィックス・src/ ディレクトリの有無が含まれます。

ヒント: フレームワークの検出に失敗した場合、shadcn はデフォルトで manual モードになります。CLI は引き続き使えますが、RSC サポートやディレクトリ構造といったデフォルト値を推論できないため、より多くのプロンプトが表示されます。

テンプレートシステム

テンプレートは createTemplate ファクトリーで定義され、templates/index.ts に登録されています:

テンプレートキー フレームワーク モノレポ対応
next next-app, next-pages あり
vite vite あり
start tanstack-start あり
react-router react-router あり
astro astro あり
laravel laravel なし(laravel new が必要)

各テンプレートは TemplateConfig を持ちます:

  • scaffold:Git のスパースチェックアウトを使って GitHub からテンプレートをダウンロードします
  • create:フレームワーク固有のプロジェクト作成処理(例:create-next-app
  • initcomponents.json の書き込みと初期コンポーネントのインストール
  • postInitgit init の実行と初期コミットの作成
  • monorepo--monorepo モード向けの設定オーバーライド

218〜299行目 のデフォルトスキャフォールドは、リポジトリ全体をクローンするのではなく、Git のスパースチェックアウトを使ってテンプレートディレクトリだけをダウンロードします:

git clone --depth 1 --filter=blob:none --sparse https://github.com/shadcn-ui/ui.git
git sparse-checkout set templates/next-app

クローン後、スキャフォールドはユーザーのパッケージマネージャーに合わせてワークスペースの設定を調整します。pnpm ベースのテンプレートのロックファイルは他のパッケージマネージャー向けに削除され、pnpm-workspace.yamlpackage.json の workspaces 設定に変換され、workspace: プロトコルの参照は npm 向けに書き換えられます。

プリセットとテーマ設定

DEFAULT_PRESETS オブジェクトには、6つのビルトインプリセットが定義されています:

classDiagram
    class PresetNova {
        style: "nova"
        iconLibrary: "lucide"
        font: "geist"
        menuAccent: "subtle"
    }
    class PresetVega {
        style: "vega"
        iconLibrary: "lucide"
        font: "inter"
    }
    class PresetMaia {
        style: "maia"
        iconLibrary: "hugeicons"
        font: "figtree"
    }
    class PresetLyra {
        style: "lyra"
        iconLibrary: "phosphor"
        font: "jetbrains-mono"
    }
    class PresetMira {
        style: "mira"
        iconLibrary: "hugeicons"
        font: "inter"
    }
    class PresetLuma {
        style: "luma"
        iconLibrary: "lucide"
        font: "inter"
    }

各プリセットには、スタイル・ベースカラー・テーマ・アイコンライブラリ・フォント・メニューアクセント・メニューカラーが設定されています。選択されたプリセットは URL にエンコードされます:https://ui.shadcn.com/init?base=radix&style=nova&baseColor=neutral&...。この URL は registry:base アイテムを指しており、その config フィールドに完全な設定が格納されています。

--defaults フラグは手軽なショートカットです。インタラクティブなプロンプトをすべてスキップし、next テンプレートと nova プリセットを自動的に選択します。CI 環境やすばやいプロジェクトセットアップに重宝します。

addコマンドと自動init

add コマンドは既存のプロジェクトへのコンポーネント追加が主な用途ですが、重要なフォールバック動作があります。components.json が存在しない場合、完全な init フローを自動的に実行します。

flowchart TD
    A["shadcn add button"] --> B["preflight check"]
    B --> C{components.json exists?}
    C -->|Yes| D["Resolve registry items"]
    C -->|No| E["Prompt: create config?"]
    E -->|Yes| F["Detect framework"]
    F --> G["Prompt for base + preset"]
    G --> H["runInit() with components"]
    H --> I["Config created + components installed"]
    D --> J["Transform source"]
    J --> K["Write files"]
    K --> L["Install npm dependencies"]

161行目MISSING_CONFIG が検出されると、add コマンドはユーザーに確認を求め、検出されたフレームワークからテンプレートを推定し、ベースとプリセットの選択を経て、最初にリクエストされたコンポーネントを含めた状態で runInit を呼び出します。init が完了した時点でコンポーネントはすでにインストールされているため、add を再度実行する必要はありません。

add コマンドはその他にも以下の処理に対応しています:

  • --all フラグ:レジストリインデックスのすべてのコンポーネントをインストールします(toast など非推奨のものを除く)
  • --dry-run:ファイルを書き込まずに変更内容をプレビューします
  • --diff:既存ファイルへの変更差分を表示します
  • ユニバーサルアイテムregistry:fileregistry:item タイプは、完全なプリフライトフローを経ずに即座にインストールされます
  • スタイル/テーマの確認registry:style または registry:theme のインストール時は、CSS 変数が上書きされることについて警告が表示されます

ヒント: 新規プロジェクトで shadcn add button を実行するだけで、shadcn/ui のセットアップを始めることができます。自動的に init の手順が案内され、同じフローの中で button コンポーネントもインストールされます。

モノレポのワークスペースルーティング

モノレポを使うプロジェクトでは、packages/shadcn/src/utils/add-components.tsaddComponents が、ui エイリアスの解決先が現在の作業ディレクトリと異なるかどうかを検出します。異なる場合は addWorkspaceComponents に処理を委譲し、ファイルを適切なパッケージにルーティングします:

  • registry:ui ファイル → ui パッケージ(エイリアスが指す先)
  • registry:hookregistry:pageregistry:block ファイル → アプリパッケージ
  • CSS の更新 → アプリのスタイルシート
  • npm の依存関係 → ui パッケージとアプリパッケージに分割

このルーティングは getWorkspaceConfig に依存しており、各エイリアスのパスをその package.json のルートに解決します。components エイリアスが ../../packages/ui/src/components を指している場合、packages/ui パッケージのルートを特定し、そこにある components.json を読み込みます。

デザイン設定(メニューカラー・メニューアクセント・RTL・アイコンライブラリ)は init 時にワークスペースの components.json ファイルに反映され、モノレポ全体での一貫性が保たれます。

次のステップ

ここまでで、プロジェクトの設定方法とコンポーネントのインストール方法を解説しました。アーキテクチャの最後のピースは AI 統合レイヤーです。第6回では、レジストリを AI コーディングアシスタントに公開する MCP サーバー、ライブラリ利用者向けのプログラマティック API、そして shadcn/ui のトリプルサーフェス設計が単一のコードベースから3つの利用パターンを実現する仕組みについて解説します。