skills/dojocodinglabs/frontend-dev-guidelines/SKILL.md
Frontend development guidelines for Next.js + React 19 + shadcn/ui applications. Modern patterns including App Router, Server Components, Client Components, Server Actions, shadcn/ui with Tailwind CSS, React Hook Form, lazy loading, Suspense boundaries, Supabase client integration, performance optimization, and TypeScript best practices. Use when creating pages, components, forms, styling, data fetching, or working with Next.js/React code.
npx skillsauth add aiskillstore/marketplace frontend-dev-guidelinesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
📋 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 frontendor use the scaffold-customizer agent to adapt for Vue, Angular, Svelte, vanilla React, or other frameworks/UI libraries.
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.
app/[route]/page.tsxloading.tsx for loading stateerror.tsx for error handling'use client' ONLY if using hooks/eventscn() for conditional classes// ✅ 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!
// ✅ 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>
}
// 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>
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>
)
}
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>
)
}
'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>
)
}
// 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...
}
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
📝 Note: This is a scaffold skill with instructional examples. Generate additional resources as needed for your specific project following these patterns.
When you need guidance on a specific topic, ask Claude to generate examples:
How to request: "Show me examples of [topic] with Next.js + shadcn/ui"
// 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'
export const metadata: Metadata = {
title: 'Page Title',
description: 'Page description',
}
// Dynamic metadata
export async function generateMetadata({ params }): Promise<Metadata> {
return {
title: `Post ${params.id}`,
}
}
// app/dashboard/loading.tsx
export default function Loading() {
return <div>Loading...</div>
}
// 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>
)
}
// 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 })
}
❌ 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
Not using Next.js? Adapt the patterns:
Not using shadcn/ui? Replace with:
Keep the principles:
Skill Status: SCAFFOLD ✅ Line Count: < 500 ✅ Progressive Disclosure: Instructional patterns + generate on-demand ✅
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.