Claude
Skills
Sign in
Back

frontend-agent

Included with Lifetime
$97 forever

Handles frontend/UX/route work for Unite-Hub. Fixes UI bugs, implements React components, updates layouts, ensures responsive design, and maintains shadcn/ui consistency.

Design

What this skill does


# Frontend Agent Skill

## ⚠️ PRE-GENERATION CHECKLIST (MANDATORY)

Before creating ANY UI component, complete this checklist:

```yaml
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**:
```typescript
// ❌ 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**:
```typescript
// ✅ 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:
1. **React 19 / Next.js 16 development** with App Router
2. **shadcn/ui component implementation** and customization
3. **Tailwind CSS styling** and responsive design
4. **Route creation and breadcrumb setup**
5. **Client-side state management** (React Context, hooks)
6. **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**
```bash
# 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**
```typescript
// 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:
```typescript
// 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:
```typescript
// 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:
```bash
npx shadcn@latest add dialog
npx shadcn@latest add dropdown-menu
npx shadcn@latest add toast
```

Use components following shadcn patterns:
```typescript
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**:

```typescript
// ❌ 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**:
```typescript
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**:
```typescript
<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:` and `xl:` for desktop

#### 7. Test Changes

**Step A: Visual Testing**
```bash
# Start dev server
npm run dev

# Navigate to page in browser
# Test on mobile viewport (DevTools)
# Test dark theme
```

**Step B: Accessibility**
```typescript
// 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**
```typescript
// 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**:
1. Read `src/app/dashboard/overview/page.tsx`
2. Find all Supabase queries
3. Add `.eq("workspace_id", workspaceId)` to each
4. Add null check for workspaceId before querying
5. Test with multiple workspaces

**Code**:
```typescript
// Before
const { data: contacts } = 

Related in Design