Railsプロジェクトにshadcn/uiを導入する方法 + v0でUIを作る手順サンプル
「ActiveRecord だけは手放せない。でも、フロントは React + Tailwind で高速に組み、しかも生成 AI で UI を自動生成できたら最高じゃないか?」──そんな欲張りなフルスタック Rails エンジニアのために、本記事では shadcn/ui と v0 を “Rails × Vite” 環境へ滑らかにインストールし、AI に自然言語で画面を作らせるまでの最短ルートを解説します。
“Stimulus も好きだけど、複雑な UI はやっぱり React のほうがラク。
とはいえ、gem でごちゃごちゃするのは嫌だ…”
そのモヤモヤ、ここでスッキリさせましょう。
手順は「Rails に Vite を載せている」前提からスタート。Tailwind のセットアップでつまずかないコツから、npx shadcn@latest init 一発でボタンを出現させる快感、そして v0 に「簡単なログイン画面を作って」とつぶやくだけで完成する AI ドリブン UI まで、実践コードを交えつつ一気に駆け抜けます。
読み終える頃には “Vibe Coding!!” とつぶやきながら、新規プロジェクトを shadcn/ui で彩り、AI を組み込んだ UX を Rails 上に展開する方法が手に入るはずです。
Railsにshadcn/uiを導入するモチベーション
- v0と連携して自然言語でUIを作りたい
- ActiveRecordは素晴らしいのでRails使いたい
- Stimulusよりvite+Reactのほうが使いやすい
実際の手順
前回の記事で作成したRuby on Rails + Vite + React + TypeScript の開発環境から進めていくことにします。
manual installとかgemのshadcn-uiとか色々試していてハマったのですが、結論、vite のインストール手順をなぞるのが早いです。
vite_railsの敷いてくれたレールにうまく乗っけるようにいい感じに手順をカスタマイズする必要があります。
Railsプロジェクト自体は作成できているので、Step2の "Add Tailwind CSS"から実行する。
Tailwind CSSの追加
npm install tailwindcss @tailwindcss/vite
3.Edit tsconfig.json file、および4.Edit tsconfig.app.json fileは vite-railsがいい感じに設定してくれているので飛ばしてOK。
vite.config.tsでtailwindcssのpluginをロードするようにする
npm install -D @types/node
vite.config.ts
import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import path from "path";
import { defineConfig } from "vite";
import RubyPlugin from "vite-plugin-ruby";
export default defineConfig({
build: {
manifest: true,
rollupOptions: {
input: "./app/javascript/entrypoints/application.tsx",
},
},
plugins: [RubyPlugin(), react(), tailwindcss()],
server: {
hmr: true,
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./app/javascript"),
},
},
});
vite-railsが作成してくれたvite.config.tsのplugins に tailwindcss()だけ指定すればOK。
shadcn の初期設定コマンドを実行
ここまで来れば、shadcnの初期設定コマンドが実行できるようになるはずです。
npx shadcn@latest init
Buttonコンポーネントを追加してみる
npx shadcn@latest add button
HelloWorld.tsx
import { Button } from "./ui/button";
export default function HelloWorld() {
return <Button>Click me</Button>;
}
初期設定でNeutralを選択していた場合は、このようなボタンが表示されていればOK
v0で作成されたログインフォームを追加してみる
v0にある程度まとまったコンポーネントを作らせてみましょう。
途中プレビューが表示されなかったので再度指示を出していますが、指示は「簡単なログイン画面のモックを作成してください」のたったの一行です。
LoginForm.tsx
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Checkbox } from "@/components/ui/checkbox"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export default function LoginForm() {
return (
<div className="flex min-h-screen items-center justify-center p-4">
<Card className="w-full max-w-md">
<CardHeader>
<CardTitle className="text-2xl">ログイン</CardTitle>
<CardDescription>アカウントにログインしてください</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">メールアドレス</Label>
<Input id="email" type="email" placeholder="example@example.com" />
</div>
<div className="space-y-2">
<Label htmlFor="password">パスワード</Label>
<Input id="password" type="password" />
</div>
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<Checkbox id="remember" />
<Label htmlFor="remember" className="text-sm">
ログイン情報を記憶する
</Label>
</div>
<a href="#" className="text-sm text-primary hover:underline">
パスワードをお忘れですか?
</a>
</div>
</CardContent>
<CardFooter>
<Button className="w-full">ログイン</Button>
</CardFooter>
</Card>
</div>
)
}
shadcnでまだインストールされていないコンポーネントがあるので適宜追加しましょう。
npx shadcn@latest add checkbox
npx shadcn@latest add input
npx shadcn@latest add label
npx shadcn@latest add card
これでv0で自然言語で作成した画面をRailsに取り込むことができるようになりました。
Helloworld.tsx
import LoginForm from "./LoginForm";
export default function HelloWorld() {
return <LoginForm />;
}
で表示します。
変な位置に配置されたので修正しましょう。
application.html.erb
<body>
<main class="container mx-auto px-5 flex justify-center">
<%= yield %>
</main>
</body>
とりあえず中央には寄りましたが、application.html.erbで flex container を指定するより個々のReact Componentで制御するほうが柔軟で良いかもしれません。
あとはCardの幅とか「ログイン情報を記録する」と「パスワードをお忘れですか?」をちょちょっと手で修正するとこんな感じになります。
LoginForm.tsx
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
export default function LoginForm() {
return (
<div className="flex min-h-screen items-center justify-center p-4">
<Card className="w-[400px]">
<CardHeader>
<CardTitle className="text-2xl">ログイン</CardTitle>
<CardDescription>アカウントにログインしてください</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">メールアドレス</Label>
<Input id="email" type="email" placeholder="example@example.com" />
</div>
<div className="space-y-2">
<Label htmlFor="password">パスワード</Label>
<Input id="password" type="password" />
</div>
<div className="flex justify-between flex-col">
<div className="flex items-center space-x-2">
<Checkbox id="remember" />
<Label htmlFor="remember" className="text-sm">
ログイン情報を記憶する
</Label>
</div>
<a href="#" className="text-sm text-primary hover:underline mt-2">
パスワードをお忘れですか?
</a>
</div>
</CardContent>
<CardFooter>
<Button className="w-full">ログイン</Button>
</CardFooter>
</Card>
</div>
);
}
Enjoy Vibe Coding!!
メモ
- gemのshadcn-uiだと React Component ではなく erbが出力される
- erbを利用しない場合、gemの側の shadcn-uiは特に必要なかった
- 「tailwindの最新版がv4なのにドキュメントがv3にしか対応してない...」ということで色々ハマったが今見たら更新されていたのでクリアできた
株式会社CodeKnightsは
「生成AI時代の、変化の激しい環境を勝ち残るためのWebサービス開発」
を専門として活動しています。
お仕事のお問い合わせはこちらから↓
その他の人気記事
SNSアカウント
X(Twitter)
note
Discussion