frontend-agent
Handles frontend/UX/route work for Unite-Hub. Fixes UI bugs, implements React components, updates layouts, ensures responsive design, and maintains shadcn/ui consistency.
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o frontend-agent.zip https://jpskill.com/download/17907.zip && unzip -o frontend-agent.zip && rm frontend-agent.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/17907.zip -OutFile "$d\frontend-agent.zip"; Expand-Archive "$d\frontend-agent.zip" -DestinationPath $d -Force; ri "$d\frontend-agent.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
frontend-agent.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
frontend-agentフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Frontend Agent Skill
⚠️ 事前生成チェックリスト (必須)
UIコンポーネントを作成する前に、必ずこのチェックリストを完了してください。
PRE_GENERATION_CHECKLIST:
1. READ_DESIGN_SYSTEM:
- [ ] 禁止されているパターンについて、/DESIGN-SYSTEM.md を読む
- [ ] トークンについて、/src/app/globals.css の @theme ブロックを確認する
- [ ] 注: accent-500 = #ff6b35 (オレンジ)
2. CHECK_EXISTING_COMPONENTS:
- [ ] まず /src/components/ui/ を確認する (48コンポーネント)
- [ ] shadcn の設定について、components.json を確認する
- [ ] ランディングページの既存のパターンを確認する
3. REFERENCE_UI_LIBRARIES:
- [ ] プレミアムコンポーネントについて、/docs/UI-LIBRARY-INDEX.md を参照する
- [ ] 優先順位: プロジェクト → StyleUI/KokonutUI/Cult UI → shadcn base
- [ ] カスタマイズせずに shadcn のデフォルトを使用しない
4. VERIFY_NO_FORBIDDEN_PATTERNS:
- [ ] bg-white、text-gray-600、または汎用的な hover ステートを使用しない
- [ ] 均一な grid-cols-3 gap-4 レイアウトを使用しない
- [ ] スタイルなしの <Card className="p-6"> を使用しない
- [ ] ブランドカラーのないアイコンを使用しない
禁止されているコードパターン:
// ❌ 絶対に生成しないでください
className="bg-white rounded-lg shadow p-4" // 汎用的なカード
className="grid grid-cols-3 gap-4" // 均一なグリッド
className="text-gray-600" // デフォルトのミュート
className="hover:bg-gray-100" // 汎用的な hover
<Card className="p-6"> // スタイルなしの shadcn
必須パターン:
// ✅ 常にデザイントークンを使用してください
className="bg-bg-card border border-border-base hover:border-accent-500"
className="text-text-primary"
className="text-text-secondary"
className="bg-accent-500 hover:bg-accent-400"
概要
Frontend Agent は、Unite-Hub Next.js アプリケーションにおけるすべての UI/UX 作業を担当します。
- App Router を使用した React 19 / Next.js 16 開発
- shadcn/ui コンポーネントの実装とカスタマイズ
- Tailwind CSS スタイリングとレスポンシブデザイン
- ルートの作成とパンくずリストの設定
- クライアントサイドの状態管理 (React Context, hooks)
- アクセシビリティとパフォーマンスの最適化
この Agent の使用方法
トリガー
ユーザーの発言例: "ダッシュボードのレイアウトを修正して"、"新しい連絡先ページを追加して"、"ナビゲーションを更新して"、"モーダルコンポーネントを作成して"
Agent の動作
1. リクエストの理解
質問例:
- どのページ/コンポーネントの作業が必要ですか?
- どのような動作が望ましいですか?
- デザインの参照 (スクリーンショット、ワイヤーフレーム) はありますか?
- 優先度 (P0/P1/P2) は何ですか?
2. 現在の実装の分析
ステップ A: ファイルの特定
# コンポーネントまたはページを検索
find src/app -name "*.tsx" | grep -i "contacts"
find src/components -name "*.tsx" | grep -i "hotleads"
ステップ B: 現在のコードの読み取り
// text_editor ツールを使用
text_editor.view("src/app/dashboard/contacts/page.tsx")
ステップ C: 依存関係の特定
- どの shadcn/ui コンポーネントが使用されていますか?
- どのコンテキストが消費されていますか (AuthContext など)?
- どの API ルートが呼び出されていますか?
- どのデータベースクエリが実行されていますか?
3. 変更の実装
ステップ A: コンポーネントの更新
既存のコンポーネントの場合:
// src/components/HotLeadsPanel.tsx
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { useAuth } from "@/contexts/AuthContext";
export function HotLeadsPanel({ workspaceId }: { workspaceId: string }) {
const { currentOrganization } = useAuth();
// ホットリードを取得
const [leads, setLeads] = useState([]);
useEffect(() => {
async function fetchLeads() {
const res = await fetch("/api/agents/contact-intelligence", {
method: "POST",
body: JSON.stringify({ action: "get_hot_leads", workspaceId }),
});
const data = await res.json();
setLeads(data.leads || []);
}
if (workspaceId) fetchLeads();
}, [workspaceId]);
return (
<Card>
{/* UI の実装 */}
</Card>
);
}
ステップ B: ルートの作成
新しいページの場合:
// src/app/dashboard/new-page/page.tsx
import { Metadata } from "next";
export const metadata: Metadata = {
title: "New Page | Unite Hub",
description: "Description of new page"
};
export default async function NewPage() {
return (
<div className="container mx-auto py-8">
<h1 className="text-3xl font-bold">New Page</h1>
{/* コンテンツ */}
</div>
);
}
ステップ C: shadcn/ui コンポーネント
必要に応じて新しいコンポーネントをインストールします。
npx shadcn@latest add dialog
npx shadcn@latest add dropdown-menu
npx shadcn@latest add toast
shadcn のパターンに従ってコンポーネントを使用します。
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Title</DialogTitle>
<DialogDescription>Description</DialogDescription>
</DialogHeader>
{/* コンテンツ */}
</DialogContent>
</Dialog>
4. ワークスペースフィルタリングの追加 (V1 では非常に重要)
すべてのデータベースクエリは、ワークスペースでフィルタリングする必要があります:
// ❌ 悪い例 - すべてのワークスペースのデータを表示
const { data: contacts } = await supabase
.from("contacts")
.select("*");
// ✅ 良い例 - ユーザーのワークスペースのデータのみを表示
const { data: contacts } = await supabase
.from("contacts")
.select("*")
.eq("workspace_id", workspaceId);
以下のテーブルで必須:
contacts-.eq("workspace_id", workspaceId)campaigns-.eq("workspace_id", workspaceId)drip_campaigns-.eq("workspace_id", workspaceId)emails-.eq("workspace_id", workspaceId)generatedContent-.eq("workspace_id", workspaceId)
5. ローディングとエラー状態の処理
ローディング状態:
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
async function fetchData() {
try {
setIsLoading(true);
const data =
(原文がここで切り詰められています) 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Frontend Agent Skill
⚠️ PRE-GENERATION CHECKLIST (MANDATORY)
Before creating ANY UI component, complete this checklist:
PRE_GENERATION_CHECKLIST:
1. READ_DESIGN_SYSTEM:
- [ ] Read /DESIGN-SYSTEM.md for forbidden patterns
- [ ] Check /src/app/globals.css @theme block for tokens
- [ ] Note: accent-500 = #ff6b35 (orange)
2. CHECK_EXISTING_COMPONENTS:
- [ ] Look in /src/components/ui/ first (48 components)
- [ ] Check components.json for shadcn configuration
- [ ] Review existing patterns in landing page
3. REFERENCE_UI_LIBRARIES:
- [ ] See /docs/UI-LIBRARY-INDEX.md for premium components
- [ ] Priority: Project → StyleUI/KokonutUI/Cult UI → shadcn base
- [ ] NEVER use shadcn defaults without customization
4. VERIFY_NO_FORBIDDEN_PATTERNS:
- [ ] No bg-white, text-gray-600, or generic hover states
- [ ] No uniform grid-cols-3 gap-4 layouts
- [ ] No unstyled <Card className="p-6">
- [ ] No icons without brand colors
FORBIDDEN CODE PATTERNS:
// ❌ NEVER GENERATE THESE
className="bg-white rounded-lg shadow p-4" // Generic card
className="grid grid-cols-3 gap-4" // Uniform grid
className="text-gray-600" // Default muted
className="hover:bg-gray-100" // Generic hover
<Card className="p-6"> // Unstyled shadcn
REQUIRED PATTERNS:
// ✅ ALWAYS USE DESIGN TOKENS
className="bg-bg-card border border-border-base hover:border-accent-500"
className="text-text-primary"
className="text-text-secondary"
className="bg-accent-500 hover:bg-accent-400"
Overview
The Frontend Agent is responsible for all UI/UX work in the Unite-Hub Next.js application:
- React 19 / Next.js 16 development with App Router
- shadcn/ui component implementation and customization
- Tailwind CSS styling and responsive design
- Route creation and breadcrumb setup
- Client-side state management (React Context, hooks)
- Accessibility and performance optimization
How to Use This Agent
Trigger
User says: "Fix dashboard layout", "Add new contact page", "Update navigation", "Create modal component"
What the Agent Does
1. Understand the Request
Questions to Ask:
- Which page/component needs work?
- What's the desired behavior?
- Are there design references (screenshots, wireframes)?
- What's the priority (P0/P1/P2)?
2. Analyze Current Implementation
Step A: Locate Files
# Find the component or page
find src/app -name "*.tsx" | grep -i "contacts"
find src/components -name "*.tsx" | grep -i "hotleads"
Step B: Read Current Code
// Use text_editor tool
text_editor.view("src/app/dashboard/contacts/page.tsx")
Step C: Identify Dependencies
- What shadcn/ui components are used?
- What contexts are consumed (AuthContext, etc.)?
- What API routes are called?
- What database queries are made?
3. Implement Changes
Step A: Component Updates
For existing components:
// src/components/HotLeadsPanel.tsx
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { useAuth } from "@/contexts/AuthContext";
export function HotLeadsPanel({ workspaceId }: { workspaceId: string }) {
const { currentOrganization } = useAuth();
// Fetch hot leads
const [leads, setLeads] = useState([]);
useEffect(() => {
async function fetchLeads() {
const res = await fetch("/api/agents/contact-intelligence", {
method: "POST",
body: JSON.stringify({ action: "get_hot_leads", workspaceId }),
});
const data = await res.json();
setLeads(data.leads || []);
}
if (workspaceId) fetchLeads();
}, [workspaceId]);
return (
<Card>
{/* UI implementation */}
</Card>
);
}
Step B: Route Creation
For new pages:
// src/app/dashboard/new-page/page.tsx
import { Metadata } from "next";
export const metadata: Metadata = {
title: "New Page | Unite Hub",
description: "Description of new page"
};
export default async function NewPage() {
return (
<div className="container mx-auto py-8">
<h1 className="text-3xl font-bold">New Page</h1>
{/* Content */}
</div>
);
}
Step C: shadcn/ui Components
Install new components if needed:
npx shadcn@latest add dialog
npx shadcn@latest add dropdown-menu
npx shadcn@latest add toast
Use components following shadcn patterns:
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Title</DialogTitle>
<DialogDescription>Description</DialogDescription>
</DialogHeader>
{/* Content */}
</DialogContent>
</Dialog>
4. Add Workspace Filtering (CRITICAL for V1)
All database queries MUST filter by workspace:
// ❌ BAD - Shows data from all workspaces
const { data: contacts } = await supabase
.from("contacts")
.select("*");
// ✅ GOOD - Only shows data from user's workspace
const { data: contacts } = await supabase
.from("contacts")
.select("*")
.eq("workspace_id", workspaceId);
Required for these tables:
contacts-.eq("workspace_id", workspaceId)campaigns-.eq("workspace_id", workspaceId)drip_campaigns-.eq("workspace_id", workspaceId)emails-.eq("workspace_id", workspaceId)generatedContent-.eq("workspace_id", workspaceId)
5. Handle Loading and Error States
Loading State:
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
async function fetchData() {
try {
setIsLoading(true);
const data = await fetch("...");
setData(data);
} catch (err) {
setError(err.message);
} finally {
setIsLoading(false);
}
}
fetchData();
}, []);
if (isLoading) return <Spinner />;
if (error) return <ErrorBanner message={error} />;
return <DataDisplay data={data} />;
6. Responsive Design
Tailwind Breakpoints:
<div className="
grid grid-cols-1 // Mobile: 1 column
md:grid-cols-2 // Tablet: 2 columns
lg:grid-cols-3 // Desktop: 3 columns
gap-4
">
{/* Cards */}
</div>
Mobile-First Approach:
- Start with mobile layout (default classes)
- Add
md:classes for tablet - Add
lg:andxl:for desktop
7. Test Changes
Step A: Visual Testing
# Start dev server
npm run dev
# Navigate to page in browser
# Test on mobile viewport (DevTools)
# Test dark theme
Step B: Accessibility
// Check for:
// - Proper ARIA labels
// - Keyboard navigation
// - Focus states
// - Screen reader support
<button aria-label="Close dialog">×</button>
<input aria-describedby="email-help" />
<div role="alert" aria-live="polite">{error}</div>
Step C: Performance
// Use React.memo for expensive components
import { memo } from "react";
export const ExpensiveComponent = memo(function ExpensiveComponent({ data }) {
return <div>{/* Render */}</div>;
});
// Use dynamic imports for heavy components
import dynamic from "next/dynamic";
const HeavyChart = dynamic(() => import("@/components/HeavyChart"), {
loading: () => <Spinner />,
ssr: false
});
Common Tasks
Task 1: Fix Missing Workspace Filter
Example: Dashboard Overview page showing all contacts
Steps:
- Read
src/app/dashboard/overview/page.tsx - Find all Supabase queries
- Add
.eq("workspace_id", workspaceId)to each - Add null check for workspaceId before querying
- Test with multiple workspaces
Code:
// Before
const { data: contacts } = await supabase.from("contacts").select("*");
// After
if (!workspaceId) {
return <div>No workspace selected</div>;
}
const { data: contacts, error } = await supabase
.from("contacts")
.select("*")
.eq("workspace_id", workspaceId);
if (error) {
console.error("Error fetching contacts:", error);
return <ErrorBanner />;
}
Task 2: Create New Dashboard Page
Example: Add "Analytics" page to dashboard
Steps:
- Create
src/app/dashboard/analytics/page.tsx - Add to navigation in
src/app/dashboard/layout.tsx - Implement page content with shadcn/ui components
- Add breadcrumbs
- Test navigation
Code:
// src/app/dashboard/analytics/page.tsx
import { Metadata } from "next";
import { Card } from "@/components/ui/card";
export const metadata: Metadata = {
title: "Analytics | Unite Hub",
};
export default async function AnalyticsPage() {
return (
<div className="container mx-auto py-8 space-y-6">
<div>
<h1 className="text-3xl font-bold">Analytics</h1>
<p className="text-muted-foreground">Track your campaign performance</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Card>
{/* Stat card 1 */}
</Card>
<Card>
{/* Stat card 2 */}
</Card>
<Card>
{/* Stat card 3 */}
</Card>
</div>
</div>
);
}
// src/app/dashboard/layout.tsx - Add to navigation
const navigation = [
{ name: "Dashboard", href: "/dashboard/overview", icon: HomeIcon },
{ name: "Contacts", href: "/dashboard/contacts", icon: UsersIcon },
{ name: "Campaigns", href: "/dashboard/campaigns", icon: MailIcon },
{ name: "Analytics", href: "/dashboard/analytics", icon: ChartIcon }, // NEW
];
Task 3: Implement Button Functionality
Example: Hot Leads panel "Send Email" button
Steps:
- Read
src/components/HotLeadsPanel.tsx - Find button location
- Implement onClick handler
- Call appropriate API endpoint
- Show success/error toast
Code:
import { useToast } from "@/components/ui/use-toast";
function HotLeadsPanel() {
const { toast } = useToast();
async function handleSendEmail(contactId: string) {
try {
const res = await fetch("/api/emails/send", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ contactId, templateType: "followup" }),
});
if (!res.ok) throw new Error("Failed to send email");
toast({
title: "Email sent",
description: "Your email has been queued for sending.",
});
} catch (error) {
toast({
variant: "destructive",
title: "Error",
description: error.message,
});
}
}
return (
<Button onClick={() => handleSendEmail(contact.id)}>
Send Email
</Button>
);
}
Styling Guidelines
Tailwind CSS Best Practices
Use Utility Classes:
// ✅ Good
<div className="flex items-center justify-between p-4 bg-background border rounded-lg">
// ❌ Bad (custom CSS)
<div style={{ display: "flex", padding: "16px" }}>
Use CSS Variables from Theme:
// Defined in globals.css
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--primary: 222.2 47.4% 11.2%;
}
}
// Use in components
<div className="bg-background text-foreground">
<div className="bg-card text-card-foreground">
<div className="bg-primary text-primary-foreground">
Responsive Design:
<div className="
text-sm md:text-base lg:text-lg
p-2 md:p-4 lg:p-6
grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3
">
Component Library Reference
shadcn/ui Components Available
accordion- Collapsible content panelsalert-dialog- Modal confirmation dialogsavatar- User profile imagesbadge- Status badgesbutton- Interactive buttonscard- Content containerscheckbox- Form checkboxesdialog- Modal dialogsdropdown-menu- Dropdown menusinput- Text inputslabel- Form labelspopover- Floating contentprogress- Progress indicatorsradio-group- Radio buttonsselect- Select dropdownsswitch- Toggle switchestabs- Tabbed interfacestoast- Notification toaststooltip- Hover tooltips
Install new components:
npx shadcn@latest add [component-name]
Error Handling Patterns
API Errors
try {
const res = await fetch("/api/...");
const data = await res.json();
if (!res.ok) {
throw new Error(data.error || "Something went wrong");
}
return data;
} catch (error) {
console.error("API Error:", error);
toast({
variant: "destructive",
title: "Error",
description: error.message,
});
return null;
}
Supabase Errors
const { data, error } = await supabase.from("contacts").select("*");
if (error) {
console.error("Supabase error:", error);
return <ErrorBanner message="Failed to load contacts" />;
}
if (!data || data.length === 0) {
return <EmptyState message="No contacts found" />;
}
return <ContactsList contacts={data} />;
Version 1 Constraints
What We Fix for V1:
- ✅ Workspace filtering on ALL pages
- ✅ Hot Leads button functionality
- ✅ Contact detail page navigation
- ✅ Dashboard stat cards
- ✅ Loading and error states
- ✅ Responsive design fixes
What We Do NOT Build for V1:
- ❌ Advanced animations
- ❌ Custom theme builder
- ❌ Drag-and-drop interfaces
- ❌ Real-time collaboration UI
- ❌ Mobile app
Key Points
- Always filter by workspace - Data isolation is critical
- Use shadcn/ui components - Don't reinvent the wheel
- Follow Tailwind conventions - Utility-first approach
- Handle loading/error states - Never show blank screens
- Test responsive design - Mobile, tablet, desktop
- Maintain accessibility - ARIA labels, keyboard navigation
Integration with Other Agents
The Frontend Agent works with:
- Backend Agent - Consumes API endpoints
- Docs Agent - Updates component documentation
- Orchestrator - Receives UI fix requests