nextjs-frontend-dev-guidelines
This repository contains a complete **Cursor (Claude AI)** infrastructure that provides **auto-activating skills**, **specialized agents**, and **powerful commands** to help you build better applications faster.
- Category: discovered
- Tags: github, community
- Version: 1.0.0
- Author: walid
- Downloads: 0
- Updated: 2025-11-22
Download the latest version (v1.0.0) from this page.
SKILL.md
# Next.js Frontend Development Guidelines
**Skill Version:** 1.0.0
**Stack:** Next.js 14+, React 18+, TypeScript, App Router
**Purpose:** Guidelines for building Next.js frontend applications
## Overview
This skill provides comprehensive guidelines for Next.js frontend development using the App Router, React Server Components, and modern best practices.
## When to Use This Skill
Load this skill when working on:
- Next.js pages and layouts
- React components (client & server)
- Routing and navigation
- Data fetching patterns
- UI components and styling
- Performance optimization
## Quick Reference
### Project Structure
```
app/
├── (routes)/ # Route groups
├── api/ # API routes
├── components/ # Shared components
├── lib/ # Utilities
└── styles/ # Global styles
components/
├── ui/ # Reusable UI components
├── forms/ # Form components
└── layout/ # Layout components
```
### Key Principles
1. **Server Components First** - Default to Server Components, use Client Components only when needed
2. **Type Safety** - Full TypeScript coverage with proper interfaces
3. **Performance** - Code splitting, lazy loading, image optimization
4. **Accessibility** - ARIA labels, semantic HTML, keyboard navigation
5. **Error Handling** - Error boundaries and proper error states
## Core Guidelines
### 1. Component Architecture
#### Server Components (Default)
```typescript
// app/posts/page.tsx
import { Post } from '@/types';
async function getPosts(): Promise<Post[]> {
const res = await fetch('https://api.example.com/posts', {
cache: 'no-store', // or 'force-cache' for static
});
return res.json();
}
export default async function PostsPage() {
const posts = await getPosts();
return (
<div>
<h1>Posts</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
))}
</div>
);
}
```
#### Client Components (When Needed)
```typescript
'use client';
import { useState } from 'react';
interface ButtonProps {
onClick?: () => void;
children: React.ReactNode;
}
export function InteractiveButton({ onClick, children }: ButtonProps) {
const [count, setCount] = useState(0);
return (
<button
onClick={() => {
setCount(c => c + 1);
onClick?.();
}}
>
{children} (clicked {count} times)
</button>
);
}
```
**Use Client Components for:**
- Event handlers (onClick, onChange, etc.)
- State management (useState, useReducer)
- Effects (useEffect)
- Browser APIs (localStorage, geolocation)
- React hooks
### 2. File and Folder Conventions
#### Special Files
- `page.tsx` - Page component (creates route)
- `layout.tsx` - Shared layout
- `loading.tsx` - Loading UI
- `error.tsx` - Error handling
- `not-found.tsx` - 404 page
- `route.ts` - API route handler
#### Naming Conventions
- **Components:** PascalCase - `UserProfile.tsx`
- **Utilities:** camelCase - `formatDate.ts`
- **Types:** PascalCase - `UserTypes.ts`
- **Constants:** UPPER_SNAKE_CASE - `API_ENDPOINTS.ts`
### 3. Data Fetching
#### Server-Side Fetching
```typescript
// app/users/[id]/page.tsx
interface PageProps {
params: { id: string };
}
async function getUser(id: string) {
const res = await fetch(`https://api.example.com/users/${id}`, {
next: { revalidate: 3600 } // ISR: revalidate every hour
});
if (!res.ok) throw new Error('Failed to fetch user');
return res.json();
}
export default async function UserPage({ params }: PageProps) {
const user = await getUser(params.id);
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
```
#### Client-Side Fetching
```typescript
'use client';
import { useEffect, useState } from 'react';
import { User } from '@/types';
export function UserList() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch('/api/users')
.then(res => res.json())
.then(setUsers)
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
```
### 4. Forms and User Input
```typescript
'use client';
import { useState, FormEvent } from 'react';
interface FormData {
name: string;
email: string;
}
export function ContactForm() {
const [formData, setFormData] = useState<FormData>({
name: '',
email: '',
});
const [submitting, setSubmitting] = useState(false);
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
setSubmitting(true);
try {
const res = await fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData),
});
if (!res.ok) throw new Error('Submission failed');
// Handle success
alert('Form submitted!');
setFormData({ name: '', email: '' });
} catch (error) {
console.error('Error:', error);
alert('Failed to submit form');
} finally {
setSubmitting(false);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={formData.name}
onChange={e => setFormData(prev => ({ ...prev, name: e.target.value }))}
placeholder="Name"
required
/>
<input
type="email"
value={formData.email}
onChange={e => setFormData(prev => ({ ...prev, email: e.target.value }))}
placeholder="Email"
required
/>
<button type="submit" disabled={submitting}>
{submitting ? 'Submitting...' : 'Submit'}
</button>
</form>
);
}
```
### 5. Error Handling
```typescript
// app/posts/error.tsx
'use client';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div>
<h2>Something went wrong!</h2>
<p>{error.message}</p>
<button onClick={reset}>Try again</button>
</div>
);
}
```
### 6. Loading States
```typescript
// app/posts/loading.tsx
export default function Loading() {
return (
<div>
<div className="skeleton" />
<div className="skeleton" />
<div className="skeleton" />
</div>
);
}
```
## TypeScript Best Practices
### Component Props
```typescript
// Always define prop interfaces
interface ButtonProps {
variant?: 'primary' | 'secondary';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
onClick?: () => void;
children: React.ReactNode;
}
export function Button({
variant = 'primary',
size = 'md',
disabled = false,
onClick,
children
}: ButtonProps) {
return (
<button
className={`btn btn-${variant} btn-${size}`}
disabled={disabled}
onClick={onClick}
>
{children}
</button>
);
}
```
### Generic Components
```typescript
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
keyExtractor: (item: T) => string;
}
export function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
return (
<ul>
{items.map(item => (
<li key={keyExtractor(item)}>
{renderItem(item)}
</li>
))}
</ul>
);
}
```
## Performance Optimization
### 1. Image Optimization
```typescript
import Image from 'next/image';
<Image
src="/hero.jpg"
alt="Hero image"
width={1200}
height={600}
priority // for above-the-fold images
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>
```
### 2. Dynamic Imports
```typescript
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('@/components/HeavyComponent'), {
loading: () => <p>Loading...</p>,
ssr: false, // disable SSR if not needed
});
```
### 3. Memoization
```typescript
'use client';
import { memo, useMemo, useCallback } from 'react';
const ExpensiveComponent = memo(function ExpensiveComponent({ data }) {
const processedData = useMemo(() => {
return data.map(item => /* expensive operation */);
}, [data]);
const handleClick = useCallback(() => {
console.log('clicked');
}, []);
return <div onClick={handleClick}>{/* render */}</div>;
});
```
## Additional Resources
For more specific topics, refer to these resource files:
- `routing.md` - Advanced routing patterns
- `styling.md` - CSS and styling approaches
- `state-management.md` - Client state patterns
- `authentication.md` - Auth integration patterns
## Common Patterns
### Conditional Rendering
```typescript
{isLoading ? (
<Spinner />
) : error ? (
<ErrorMessage error={error} />
) : (
<Content data={data} />
)}
```
### List Rendering
```typescript
{items.map(item => (
<ListItem
key={item.id}
item={item}
onEdit={handleEdit}
onDelete={handleDelete}
/>
))}
```
## Checklist for New Components
- [ ] TypeScript interfaces defined
- [ ] Proper naming (PascalCase for components)
- [ ] Client/Server component decision made
- [ ] Props validated and typed
- [ ] Error boundaries considered
- [ ] Loading states implemented
- [ ] Accessibility attributes added
- [ ] Performance optimized (memo, useMemo if needed)
---
**Last Updated:** 2025-01-10
**Maintained By:** Development Team