SuperAPI AI Directory

frontend-dev-guidelines

Frontend & websites

View repository

Updated 10-15 21:11

About this skill

📋 OPINIONATED SCAFFOLD: Modern Next.js + React 19 + shadcn/ui stack

Default Stack:

  • Framework: Next.js 14+ (App Router)
  • UI Library: React 19
  • Components: shadcn/ui (Radix primitives)
  • Styling: Tailwind CSS
  • Forms: React Hook Form + Zod validation
  • State: React Context + TanStack Query for server state
  • Data Fetching: Server Components, Server Actions, TanStack Query
  • Language: TypeScript
  • Deployment: Vercel

To customize: Run /customize-scaffold frontend or use the scaffold-customizer agent to adapt for Vue, Angular, Svelte, vanilla React, or other frameworks/UI libraries.

Frontend Development Guidelines

Purpose

Modern frontend development with Next.js 14+ App Router, React 19, Server Components, and shadcn/ui. Focus on performance, type safety, and excellent UX with Supabase integration.

When to Use This Skill

  • Creating pages with App Router
  • Building Server/Client Components
  • Implementing Server Actions
  • Adding shadcn/ui components
  • Styling with Tailwind CSS
  • Data fetching with Supabase
  • Forms with React Hook Form + Zod
  • Performance optimization
  • TypeScript patterns

Quick Start

New Page Checklist

  • Create app/[route]/page.tsx
  • Use Server Component by default (no 'use client')
  • Fetch data directly in component
  • Add loading.tsx for loading state
  • Add error.tsx for error handling
  • Export metadata for SEO
  • Use Tailwind for styling

New Component Checklist

  • Server Component or Client Component?
  • Add 'use client' ONLY if using hooks/events
  • Use shadcn/ui components
  • Style with Tailwind classes
  • TypeScript types for props
  • Use cn() for conditional classes

Core Principles

1. Server Components by Default

// ✅ Server Component (default)
export default async function Page() {
  const data = await getData()  // Direct fetch, no hooks
  return <div>{data.title}</div>
}

// ❌ Don't add 'use client' unless needed
'use client'  // Only add if using hooks/events!

2. Client Components When Needed

// ✅ Client Component (interactivity)
'use client'

import { useState } from 'react'
import { Button } from '@/components/ui/button'

export function Counter() {
  const [count, setCount] = useState(0)
  return <Button onClick={() => setCount(count + 1)}>{count}</Button>
}

3. Server Actions for Mutations

// app/actions.ts
'use server'

import { revalidatePath } from 'next/cache'
import { createServerClient } from '@/lib/supabase/server'

export async function createPost(formData: FormData) {
  const supabase = createServerClient()

  const { data, error } = await supabase
    .from('posts')
    .insert({ title: formData.get('title') })

  if (error) throw error

  revalidatePath('/posts')
  return { success: true, data }
}

// In component:
<form action={createPost}>
  <input name="title" />
  <button type="submit">Create</button>
</form>

4. Use shadcn/ui Components

import { Button } from '@/components/ui/button'
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
import { Input } from '@/components/ui/input'

export function Example() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Title</CardTitle>
      </CardHeader>
      <CardContent>
        <Input placeholder="Type..." />
        <Button>Submit</Button>
      </CardContent>
    </Card>
  )
}

5. Tailwind CSS for Styling

import { cn } from '@/lib/utils'

export function Component({ className, variant }: Props) {
  return (
    <div className={cn(
      'rounded-lg bg-white p-4 shadow',
      variant === 'primary' && 'border-2 border-blue-500',
      className
    )}>
      Content
    </div>
  )
}

6. Forms with React Hook Form

'use client'

import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8)
})

export function LoginForm() {
  const form = useForm({
    resolver: zodResolver(schema)
  })

  async function onSubmit(values: z.infer<typeof schema>) {
    // Handle submission
  }

  return (
    <form onSubmit={form.handleSubmit(onSubmit)}>
      <input {...form.register('email')} />
      <input {...form.register('password')} type="password" />
      <button type="submit">Login</button>
    </form>
  )
}

7. Supabase Integration

// Server Component
import { createServerClient } from '@/lib/supabase/server'

export default async function Page() {
  const supabase = createServerClient()
  const { data } = await supabase.from('posts').select('*')

  return <div>{/* Render data */}</div>
}

// Client Component
'use client'

import { createClient } from '@/lib/supabase/client'

export function ClientComponent() {
  const supabase = createClient()
  // Use with hooks...
}

Directory Structure

app/
├── (auth)/              # Route group (auth pages)
│   ├── login/
│   │   └── page.tsx
│   └── register/
│       └── page.tsx
├── dashboard/
│   ├── page.tsx         # /dashboard
│   ├── loading.tsx      # Loading UI
│   ├── error.tsx        # Error UI
│   └── posts/
│       ├── page.tsx     # /dashboard/posts
│       └── [id]/
│           └── page.tsx # /dashboard/posts/[id]
├── api/
│   └── webhook/
│       └── route.ts     # API route
├── layout.tsx           # Root layout
└── page.tsx             # Home page

components/
├── ui/                  # shadcn/ui components
│   ├── button.tsx
│   ├── card.tsx
│   └── input.tsx
└── dashboard/           # Feature components
    ├── post-list.tsx
    └── post-card.tsx

lib/
├── supabase/
│   ├── client.ts        # Client-side
│   └── server.ts        # Server-side
└── utils.ts             # cn() utility

Example Resource Files

📝 Note: This is a scaffold skill with instructional examples. Generate additional resources as needed for your specific project following these patterns.

Patterns Covered

When you need guidance on a specific topic, ask Claude to generate examples:

  • Server vs Client Components - When to use each, migration patterns
  • Data fetching - Server Components, Server Actions, TanStack Query
  • Forms - React Hook Form + Zod, Server Actions
  • shadcn/ui usage - Component patterns, customization
  • Tailwind patterns - Responsive design, dark mode, animations
  • Performance - Code splitting, lazy loading, images
  • TypeScript - Component props, generics, utility types
  • Testing - Unit tests, integration tests, E2E

How to request: "Show me examples of [topic] with Next.js + shadcn/ui"


Common Imports

// Next.js
import { Metadata } from 'next'
import Link from 'next/link'
import Image from 'next/image'
import { redirect, notFound } from 'next/navigation'
import { revalidatePath, revalidateTag } from 'next/cache'

// React (Client Components)
'use client'
import { useState, useEffect, useCallback, useMemo, useTransition } from 'react'

// shadcn/ui
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Card, CardHeader, CardTitle, CardContent, CardFooter } from '@/components/ui/card'
import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@/components/ui/form'

// Tailwind
import { cn } from '@/lib/utils'

// Supabase
import { createClient } from '@/lib/supabase/client'
import { createServerClient } from '@/lib/supabase/server'

// Forms
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'

Quick Reference

Metadata (SEO)

export const metadata: Metadata = {
  title: 'Page Title',
  description: 'Page description',
}

// Dynamic metadata
export async function generateMetadata({ params }): Promise<Metadata> {
  return {
    title: `Post ${params.id}`,
  }
}

Loading States

// app/dashboard/loading.tsx
export default function Loading() {
  return <div>Loading...</div>
}

Error Handling

// app/dashboard/error.tsx
'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={reset}>Try again</button>
    </div>
  )
}

API Routes

// app/api/posts/route.ts
import { NextResponse } from 'next/server'

export async function GET(request: Request) {
  const posts = await getPosts()
  return NextResponse.json(posts)
}

export async function POST(request: Request) {
  const body = await request.json()
  const post = await createPost(body)
  return NextResponse.json(post, { status: 201 })
}

Anti-Patterns

❌ Using 'use client' on every component ❌ Not using Server Components for data fetching ❌ Inline styles instead of Tailwind ❌ Not using shadcn/ui components ❌ useState for server data (use Server Components) ❌ Direct database queries in Client Components ❌ Missing loading/error states ❌ Not using TypeScript properly


Customization Instructions

For Your Tech Stack

Not using Next.js? Adapt the patterns:

  • Vue/Nuxt → Similar SSR patterns
  • Vite + React → Remove Server Components, use TanStack Query
  • Angular → Similar concepts, different syntax
  • Svelte/SvelteKit → SvelteKit has similar features

For Your UI Library

Not using shadcn/ui? Replace with:

  • Material-UI → Import from @mui/material
  • Chakra UI → Import from @chakra-ui/react
  • Ant Design → Import from antd
  • Custom components → Build your own

For Your Patterns

Keep the principles:

  • Component composition
  • Type safety
  • Performance optimization
  • Accessibility
  • SEO considerations

Related Skills

  • backend-dev-guidelines - Supabase Edge Functions patterns
  • memory-management - Track UI/UX decisions
  • skill-developer - Meta-skill for creating skills

Skill Status: SCAFFOLD ✅ Line Count: < 500 ✅ Progressive Disclosure: Instructional patterns + generate on-demand ✅