- Use Next.js 14 with TypeScript and Tailwind CSS for optimal developer experience and type safety.
- Use
bun
for all package installations and management. - Implement the App Router, which is the recommended routing system for Next.js 14.
- Utilize Server Components by default, using Client Components only when necessary for interactivity or client-side state.
- Leverage Server Actions for handling data mutations and form submissions.
- Implement proper caching strategies using Next.js built-in caching mechanisms.
- Ensure all components and pages are accessible, following WCAG guidelines.
- Use environment variables for configuration following Next.js conventions.
- Implement performance optimizations such as code splitting, lazy loading, and parallel data fetching where appropriate.
- Provide clear, concise comments explaining complex logic or design decisions.
-
Use the
app
directory for all components and pages. -
Implement the following file conventions in the
app
directory:layout.tsx
: For shared UI across multiple pagespage.tsx
: For unique page contentloading.tsx
: For loading UIerror.tsx
: For error handling UInot-found.tsx
: For 404 pages
-
Use Server Components by default. Add the
'use client'
directive only when creating Client Components. -
Define components using arrow function syntax with TypeScript:
import { FC } from 'react'; interface ComponentProps { // Props definition } const Component: FC<ComponentProps> = ({ prop1, prop2 }) => { // Component logic }; export default Component;
-
For page components, use default exports:
export default function Page() { // Page component logic }
-
If explicit typing is needed, prefer
React.FC
orReact.ReactNode
:import React from 'react'; const ComponentName: React.FC = () => { // Component logic }; // OR const ComponentName = (): React.ReactNode => { // Component logic };
-
Implement nested routing using folder structure in the
app
directory. -
Use the
<Link>
component fromnext/link
for client-side navigation:import Link from 'next/link'; <Link href="/about">About</Link>
-
Implement dynamic routes using folder names with square brackets (e.g.,
[id]
). -
Use
generateStaticParams
for generating static paths in dynamic routes.
-
Use Server Components and the
fetch
API for data fetching, leveraging Next.js automatic request deduplication:async function getData() { const res = await fetch('<https://api.example.com/data>', { next: { revalidate: 3600 } }); if (!res.ok) throw new Error('Failed to fetch data'); return res.json(); } export default async function Page() { const data = await getData(); // Render component using data }
-
Implement Server Actions for data mutations:
'use server'; import { revalidatePath } from 'next/cache'; export async function updateData(formData: FormData) { // Update data in your database revalidatePath('/data'); }
-
Use route handlers (route.ts) for API routes in the App Router.
-
Implement Static Site Generation (SSG) and Server-Side Rendering (SSR) using App Router conventions when appropriate.
-
Use Server Actions for form submissions and data mutations:
import { updateData } from './actions'; export default function Form() { return ( <form action={updateData}> <input type="text" name="data" /> <button type="submit">Update</button> </form> ); }
-
Implement React hooks for client-side state management when necessary.
-
Use the
useState
anduseEffect
hooks in Client Components for local state and side effects.
-
Use Tailwind CSS classes exclusively for styling. Avoid inline styles:
<div className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"> {/* Component content */} </div>
-
Create custom Tailwind classes in the
tailwind.config.js
file for reusable styles. -
Use CSS Modules for component-specific styles when needed.
-
Implement automatic static optimization for eligible pages.
-
Use dynamic imports for code splitting:
import dynamic from 'next/dynamic'; const DynamicComponent = dynamic(() => import('../components/DynamicComponent'));
-
Utilize the Image component from
next/image
for automatic image optimization:import Image from 'next/image'; <Image src="/image.jpg" alt="Description" width={500} height={300} />
-
Implement proper caching strategies using the Data Cache and Full Route Cache.
-
Use Next.js 14's built-in caching and revalidation features for optimal performance:
import { unstable_cache } from 'next/cache'; const getCachedUser = unstable_cache( async (id: string) => getUser(id), ['user-cache'], { revalidate: 3600 } // Revalidate every hour );
-
Use on-demand revalidation when appropriate:
import { revalidatePath, revalidateTag } from 'next/cache'; export async function updateData() { // Update data in your database revalidatePath('/data'); // Revalidate a specific path revalidateTag('data-tag'); // Revalidate all entries with this tag }
-
Implement parallel data fetching for improved performance:
async function ParallelDataFetch() { const dataPromise = fetch('<https://api.example.com/data>'); const userPromise = fetch('<https://api.example.com/user>'); const [data, user] = await Promise.all([ dataPromise.then(res => res.json()), userPromise.then(res => res.json()) ]); return { data, user }; }
-
Create error.tsx files for error boundaries:
'use client'; export default function Error({ error, reset, }: { error: Error & { digest?: string }; reset: () => void; }) { return ( <div> <h2>Something went wrong!</h2> <button onClick={() => reset()}>Try again</button> </div> ); }
-
Implement loading.tsx files for managing loading states.
-
Use React Suspense for more granular loading states:
import { Suspense } from 'react'; export default function Page() { return ( <Suspense fallback={<Loading />}> <SomeComponent /> </Suspense> ); }
-
Use the Metadata API for SEO optimization:
import type { Metadata } from 'next'; export const metadata: Metadata = { title: 'Page Title', description: 'Page description', };
-
Implement dynamic metadata using generateMetadata for pages with dynamic content.
- When using Composer mode, provide clear, natural language descriptions of desired changes or additions.
- For multi-file operations, specify the files involved and their relationships.
- When requesting code generation, provide context about the desired functionality and how it fits into the existing project structure.
- For refactoring tasks, describe the current code structure and the desired outcome.
- When addressing errors, provide details about the error message and the surrounding code context.
Remember to adapt these rules based on specific project requirements and personal preferences. Always prioritize clean, efficient, and maintainable code that adheres to Next.js 14 best practices.