Claude Code Plugins

Community-maintained marketplace

Feedback

frontend-master

@petbrains/mvp-builder
4
0

Master skill for frontend development with Next.js + React + Tailwind stack. Decision framework for choosing components, animations, assets, and tools. Routes to specialized skills for implementation details. Use as entry point for any frontend task.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name frontend-master
description Master skill for frontend development with Next.js + React + Tailwind stack. Decision framework for choosing components, animations, assets, and tools. Routes to specialized skills for implementation details. Use as entry point for any frontend task.
allowed-tools Read, Edit, Write, Bash (*), Playwright MCP tools

Frontend Master Skill

Unified decision framework for modern frontend development.

Stack: Next.js 14+ (App Router) · React 18+ · Tailwind CSS · TypeScript · Framer Motion

Quick Decision Matrix

WHAT DO YOU NEED?
│
├─► UI Components
│   ├─ Basic (buttons, forms, dialogs) → shadcn/ui
│   ├─ SaaS polish (tickers, marquees) → Magic UI [skill: frontend-magic-ui]
│   └─ Dramatic effects (spotlight, 3D) → Aceternity [skill: frontend-aceternity]
│
├─► Animations
│   ├─ Just plays/loops (loaders, feedback) → Lottie [skill: frontend-lottie]
│   └─ Reacts to input (hover, data) → Rive [skill: frontend-rive]
│
├─► Assets
│   ├─ Icons → Iconify/Lucide [skill: frontend-iconify]
│   ├─ Avatars → DiceBear (FREE) [skill: frontend-image-generation]
│   ├─ Photos → Unsplash (FREE) [skill: frontend-image-generation]
│   └─ Illustrations → unDraw (FREE) [skill: frontend-image-generation]
│
├─► Theming
│   ├─ Colors/palette → Color System [skill: frontend-color-system]
│   └─ Typography → Google Fonts [skill: frontend-google-fonts]
│
└─► Quality
    ├─ Code checks → Debug & Linting [skill: frontend-debug-linting]
    └─ Visual QA → Playwright [skill: frontend-playwright]

1. Project Setup Checklist

# New Next.js project
npx create-next-app@latest my-app --typescript --tailwind --eslint --app

# Essential dependencies
npm install clsx tailwind-merge framer-motion
npm install -D prettier eslint-config-prettier

# UI foundation
npx shadcn@latest init
npx shadcn@latest add button card input dialog

Recommended Structure

src/
├── app/                    # Next.js App Router
│   ├── layout.tsx          # Root layout + fonts
│   ├── page.tsx            # Home page
│   └── (routes)/           # Route groups
├── components/
│   ├── ui/                 # shadcn components
│   ├── magicui/            # Magic UI components
│   └── [feature]/          # Feature components
├── lib/
│   ├── fonts.ts            # Font configuration
│   ├── utils.ts            # cn() helper
│   └── constants.ts        # App constants
├── styles/
│   └── globals.css         # Tailwind + CSS vars
└── public/
    ├── animations/         # .lottie, .riv files
    ├── icons/              # Downloaded SVGs
    └── images/             # Static images

2. Component Selection Guide

UI Components Decision Tree

Need a component?
│
├─► Form element (input, select, checkbox)
│   └─► shadcn/ui — accessible, unstyled base
│
├─► Data display (table, card, list)
│   └─► shadcn/ui — consistent patterns
│
├─► Marketing/Landing page
│   ├─► Stats/numbers → Magic UI: NumberTicker
│   ├─► Logo carousel → Magic UI: Marquee
│   ├─► Feature grid → Magic UI: BentoGrid
│   ├─► Hero spotlight → Aceternity: Spotlight, Aurora
│   ├─► 3D hover cards → Aceternity: 3DCard
│   ├─► Text reveal → Aceternity: TextGenerateEffect
│   └─► Device mockup → Magic UI: Safari, iPhone
│
└─► Interactive element
    ├─► Simple hover/focus → Tailwind transitions
    ├─► Complex entrance → Framer Motion
    └─► State machine → Rive

Animation Decision Tree

Animation needed?
│
├─► Does it react to user input?
│   ├─ NO → Lottie (just plays)
│   └─ YES → Does it have multiple states?
│       ├─ Simple hover → CSS/Framer Motion
│       └─ Complex states → Rive
│
├─► What type?
│   ├─ Loading spinner → Lottie
│   ├─ Success/error → Lottie
│   ├─ Empty state illustration → Lottie
│   ├─ Animated toggle/checkbox → Rive
│   ├─ Progress driven by data → Rive
│   └─ Hero background effect → Aceternity

Quick Reference:

Need Solution
Loader spinner Lottie
Success checkmark Lottie
Animated button Rive
Data-driven progress Rive
Hero spotlight Aceternity
Number ticker Magic UI

3. Styling Best Practices

Tailwind Patterns

// ✅ Use cn() for conditional classes
import { cn } from "@/lib/utils"

<button className={cn(
  "px-4 py-2 rounded-md font-medium",
  "bg-primary text-primary-foreground",
  "hover:bg-primary/90 transition-colors",
  disabled && "opacity-50 cursor-not-allowed"
)}>

// ✅ Responsive: mobile-first
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">

// ✅ Dark mode with CSS variables
<div className="bg-background text-foreground">

// ❌ Avoid arbitrary values when Tailwind has it
<div className="mt-[16px]">  // Bad
<div className="mt-4">       // Good

Color System Setup

→ See [frontend-color-system] for full guide

/* globals.css - shadcn theme structure */
:root {
  --background: 0 0% 100%;
  --foreground: 240 10% 3.9%;
  --primary: 239 84% 67%;
  --primary-foreground: 0 0% 98%;
  /* ... */
}

.dark {
  --background: 240 10% 3.9%;
  --foreground: 0 0% 98%;
  /* ... */
}

Typography Setup

→ See [frontend-google-fonts] for font pairings

// lib/fonts.ts
import { Inter, Plus_Jakarta_Sans } from 'next/font/google'

export const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-inter',
})

export const jakarta = Plus_Jakarta_Sans({
  subsets: ['latin'],
  display: 'swap',
  variable: '--font-jakarta',
})

// app/layout.tsx
<html className={`${inter.variable} ${jakarta.variable}`}>

// tailwind.config.ts
fontFamily: {
  sans: ['var(--font-inter)'],
  display: ['var(--font-jakarta)'],
}

Font Pairing Presets:

Project Type Heading Body
Modern SaaS Plus Jakarta Sans Inter
Corporate Source Sans 3 Source Serif 4
Editorial Playfair Display Lora
Dev Tools Geist Inter

4. Assets Strategy

Icons

→ See [frontend-iconify] for full API

// Recommended: @iconify/react with Lucide set
import { Icon } from '@iconify/react'

<Icon icon="lucide:home" className="w-5 h-5" />

// Or download SVGs for performance
curl -o ./public/icons/home.svg "https://api.iconify.design/lucide/home.svg"

Images — FREE FIRST

→ See [frontend-image-generation] for all options

ALWAYS FREE FIRST:
  Avatars:      DiceBear, Boring Avatars, UI Avatars
  Photos:       Unsplash, Picsum
  Illustrations: unDraw, Storyset
  Backgrounds:  Haikei, Hero Patterns

AI GENERATION ONLY WHEN:
  - Custom branded asset needed
  - No suitable free alternative
  - User explicitly requests
// Avatar with fallback
const fallback = `https://api.dicebear.com/7.x/lorelei/svg?seed=${name}`
<img src={src || fallback} onError={e => e.target.src = fallback} />

// Placeholder photo
<img src="https://source.unsplash.com/800x600/?technology" />

5. SSR & Hydration Rules

Critical for Next.js App Router:

// 1. Client components need directive
'use client'

// 2. Browser-only code → useEffect
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
if (!mounted) return <Skeleton />

// 3. Heavy animations → dynamic import
import dynamic from 'next/dynamic'
const Globe = dynamic(() => import('@/components/globe'), { ssr: false })

// 4. Window/document access → check first
if (typeof window !== 'undefined') {
  // browser code
}

Components requiring 'use client':

  • All Aceternity components
  • All Magic UI animated components
  • Lottie/Rive players
  • Anything using useState, useEffect, event handlers

6. Performance Checklist

Images:
  ✓ Use next/image with proper sizing
  ✓ Add priority to LCP images
  ✓ Lazy load below-fold images

Fonts:
  ✓ Use next/font (auto self-hosted)
  ✓ Only 'latin' subset unless needed
  ✓ display: 'swap' always

Animations:
  ✓ Reduce particles on mobile
  ✓ Respect prefers-reduced-motion
  ✓ Pause when not in viewport

Components:
  ✓ Dynamic import heavy components
  ✓ Lazy load below-fold sections
  ✓ Memoize expensive renders
// Reduced motion check
const prefersReducedMotion = window.matchMedia(
  '(prefers-reduced-motion: reduce)'
).matches

// Viewport visibility
import { useInView } from 'react-intersection-observer'
const { ref, inView } = useInView({ threshold: 0.1 })
useEffect(() => {
  inView ? animation.play() : animation.pause()
}, [inView])

7. Quality Gates

Before Every Delivery

→ See [frontend-debug-linting] and [frontend-playwright]

CODE CHECKS (required):
  npm run lint        → 0 errors
  npm run typecheck   → 0 errors
  npm run format      → clean

VISUAL QA (required):
  1. npm run dev
  2. browser_navigate → page
  3. browser_take_screenshot → looks correct
  4. browser_console_messages { onlyErrors: true } → EMPTY
  5. browser_resize { width: 375 } → mobile works

Common Issues Quick Fix

TypeScript:
  "Type 'X' not assignable to 'Y'" → Fix type or add assertion
  "Object possibly undefined" → Add ?. or ?? fallback

React:
  "Missing useEffect dependencies" → Add deps or useCallback
  "Each child needs unique key" → Add key={item.id}

Hydration:
  "Text content mismatch" → 'use client' + mounted check
  "Hydration failed" → dynamic import with ssr: false

Console:
  "Failed to fetch" → Check API/network
  "Cannot read property of undefined" → Add loading state

8. Common Patterns

Responsive Container

<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
  {children}
</div>

Section Spacing

<section className="py-16 md:py-24 lg:py-32">
  <div className="container">
    <h2 className="text-3xl md:text-4xl lg:text-5xl font-bold mb-8">
      Title
    </h2>
  </div>
</section>

Card Grid

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  {items.map(item => (
    <Card key={item.id}>
      <CardHeader>
        <CardTitle>{item.title}</CardTitle>
      </CardHeader>
      <CardContent>{item.content}</CardContent>
    </Card>
  ))}
</div>

Loading State

function Component() {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)

  if (loading) return <Skeleton className="h-32 w-full" />
  if (!data) return <EmptyState />
  return <Content data={data} />
}

9. Skill Reference Map

Task Primary Skill When to Use
Dramatic hero effects frontend-aceternity Spotlight, aurora, 3D cards
Color palette/theme frontend-color-system Brand colors, dark mode
Linting & debugging frontend-debug-linting Before every delivery
Typography frontend-google-fonts Font setup, pairings
Icons frontend-iconify Search & integrate icons
Images & avatars frontend-image-generation FREE assets first
Simple animations frontend-lottie Loaders, feedback
SaaS components frontend-magic-ui Tickers, marquees, mockups
Visual testing frontend-playwright Screenshot verification
Interactive animations frontend-rive State-driven animations

10. Quick Start Templates

Landing Page Hero

'use client'
import { Spotlight } from '@/components/ui/spotlight'
import { FlipWords } from '@/components/ui/flip-words'

export function Hero() {
  return (
    <section className="relative h-screen bg-black overflow-hidden">
      <Spotlight className="absolute -top-40 left-0" fill="white" />
      <div className="relative z-10 container flex flex-col items-center justify-center h-full text-center">
        <h1 className="text-4xl md:text-6xl font-bold text-white mb-6">
          Build <FlipWords words={["faster", "better", "smarter"]} /> apps
        </h1>
        <p className="text-xl text-gray-400 max-w-2xl mb-8">
          Description text here
        </p>
        <Button size="lg">Get Started</Button>
      </div>
    </section>
  )
}

Stats Section

'use client'
import { NumberTicker } from '@/components/magicui/number-ticker'

const stats = [
  { value: 10000, label: 'Users', suffix: '+' },
  { value: 99.9, label: 'Uptime', suffix: '%' },
  { value: 50, label: 'Countries', suffix: '+' },
]

export function Stats() {
  return (
    <section className="py-16 bg-muted">
      <div className="container grid grid-cols-1 md:grid-cols-3 gap-8 text-center">
        {stats.map(stat => (
          <div key={stat.label}>
            <div className="text-4xl font-bold">
              <NumberTicker value={stat.value} />
              {stat.suffix}
            </div>
            <div className="text-muted-foreground">{stat.label}</div>
          </div>
        ))}
      </div>
    </section>
  )
}

External Resources

For latest API of any library → use context7 skill