Next.js Component Rules
NextJSComponentsState ManagementError HandlingUI Design
Description
Guidelines for next-components
Globs
**/*
---
description: Guidelines for next-components
globs: **/*
---
# Next.js Component Rules
Rules for Next.js components and pages.
<rule>
name: next_component_standards
description: Standards for Next.js components and pages
filters:
- type: file_path
pattern: "app/.*?/page\\.tsx$|app/.*?/layout\\.tsx$|components/.*?\\.tsx$"
actions:
- type: suggest
message: |
Follow these Next.js component standards:
1. Component Structure:
- Use proper prop interfaces
- Implement proper state management:
* useState for local state
* useCallback for handlers
* useRef for DOM refs
- Use proper hooks:
* useEffect for side effects
* useInView for infinite scroll
* useDebounce for input
- Handle component lifecycle
- Follow component patterns
2. Error Handling:
- Use proper error states
- Implement error boundaries
- Show user-friendly errors:
* Use proper error components
* Show retry options
* Use toast notifications
- Handle async errors
- Log errors properly
3. Loading States:
- Use proper loading indicators
- Handle async operations:
* Show loading spinners
* Disable inputs
* Show progress
- Use proper Suspense
- Handle loading UI
- Follow loading patterns
4. UI Components:
- Use shadcn/ui components
- Follow accessibility:
* Use proper ARIA labels
* Handle keyboard navigation
* Follow a11y patterns
- Use proper styling:
* Use Tailwind classes
* Follow design system
- Handle responsive design
- Follow UI patterns
5. State Management:
- Handle loading states:
* isLoading
* isSending
* isConnecting
- Handle error states:
* error messages
* retry logic
* error boundaries
- Handle success states
- Use proper state updates
- Follow state patterns
examples:
- input: |
// Bad
function ChatComponent() {
const [data, setData] = useState()
useEffect(() => {
fetch('/api/chat').then(res => setData(res.json()))
}, [])
return <div>{data}</div>
}
// Good
interface ChatComponentProps {
conversationId?: string;
initialMessages?: ExtendedChatMessage[];
}
function ChatComponent({ conversationId, initialMessages }: ChatComponentProps) {
const [messages, setMessages] = useState<ExtendedChatMessage[]>(initialMessages ?? []);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const messagesEndRef = useRef<HTMLDivElement>(null);
const loadMessages = useCallback(async () => {
if (isLoading || !conversationId) return;
setIsLoading(true);
try {
const response = await chatApi.getMessages({
conversationId,
limit: 20
});
setMessages(response.messages);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load messages');
toast.error('Failed to load messages');
} finally {
setIsLoading(false);
}
}, [conversationId, isLoading]);
useEffect(() => {
loadMessages();
}, [loadMessages]);
if (error) {
return (
<div className="flex items-center justify-center p-4">
<AlertCircle className="h-6 w-6 text-destructive" />
<p className="ml-2 text-sm text-destructive">{error}</p>
<Button onClick={loadMessages} variant="outline" size="sm">
Retry
</Button>
</div>
);
}
if (isLoading) {
return (
<div className="flex items-center justify-center p-4">
<Loader2 className="h-6 w-6 animate-spin" />
</div>
);
}
return (
<div className="flex flex-col space-y-4">
{messages.map((message) => (
<MessageCard key={message.id} message={message} />
))}
<div ref={messagesEndRef} />
</div>
);
}
output: "Properly structured Next.js component with proper state management"
metadata:
priority: high
version: 1.0
</rule>