Built for developers, by XinhND

v2.1.0

Ready

Next.js Cheat Sheet

Complete reference guide for Next.js with interactive examples and live playground links

Getting Started

Create a New Project

Create a new Next.js project with TypeScript

Next.js
# Create a new Next.js project with TypeScript
npx create-next-app@latest my-app --typescript

# Using pnpm
pnpm create next-app my-app --typescript

# Using Yarn
yarn create next-app my-app --typescript

Project Structure

Basic structure of a Next.js project with TypeScript

Next.js
my-app/
├── app/             # App Router (Next.js 13+)
│   ├── layout.tsx   # Root layout
│   ├── page.tsx     # Home page
│   └── [...]/       # Other routes
├── pages/           # Pages Router (traditional)
│   ├── _app.tsx     # Custom App component
│   ├── _document.tsx # Custom Document
│   ├── index.tsx    # Home page
│   └── api/         # API routes
├── public/          # Static files
├── components/      # React components
├── styles/          # CSS files
├── next.config.js   # Next.js configuration
├── tsconfig.json    # TypeScript configuration
└── package.json     # Dependencies

TypeScript Configuration

Default TypeScript configuration for Next.js

Next.js
// tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}

Routing

App Router (Next.js 13+)

File-based routing with the App Router (Next.js 13+)

Next.js
// app/page.tsx - Home page
export default function Home() {
  return <h1>Hello, Next.js!</h1>
}

// app/about/page.tsx - About page
export default function About() {
  return <h1>About Us</h1>
}

// app/blog/[slug]/page.tsx - Dynamic route
export default function BlogPost({ params }: { params: { slug: string } }) {
  return <h1>Blog Post: {params.slug}</h1>
}

// app/blog/[...slug]/page.tsx - Catch-all route
export default function BlogPosts({ params }: { params: { slug: string[] } }) {
  return <h1>Blog Posts: {params.slug.join('/')}</h1>
}

Pages Router (Traditional)

File-based routing with the Pages Router using TypeScript

Next.js
// pages/index.tsx - Home page
import type { NextPage } from 'next'

const Home: NextPage = () => {
  return <h1>Hello, Next.js!</h1>
}

export default Home

// pages/blog/[slug].tsx - Dynamic route
import type { GetServerSideProps, NextPage } from 'next'

interface Props {
  slug: string
}

const BlogPost: NextPage<Props> = ({ slug }) => {
  return <h1>Blog Post: {slug}</h1>
}

export const getServerSideProps: GetServerSideProps = async ({ params }) => {
  const slug = params?.slug as string
  return { props: { slug } }
}

export default BlogPost

Data Fetching

Server Components (App Router)

Server Components for data fetching with TypeScript

Next.js
// app/users/page.tsx
// Server Component (default in App Router)
interface User {
  id: number
  name: string
  email: string
}

async function UsersPage() {
  // This runs on the server
  const res = await fetch('https://api.example.com/users')
  const users: User[] = await res.json()
  
  return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  )
}

export default UsersPage

Client Components (App Router)

Client Components with TypeScript

Next.js
// app/components/counter.tsx
'use client' // Mark as Client Component

import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState<number>(0)
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  )
}

API Routes

API Routes (Pages Router)

Creating API endpoints with TypeScript

Next.js
// pages/api/users.ts
import type { NextApiRequest, NextApiResponse } from 'next'

type User = {
  id: number
  name: string
}

type ResponseData = {
  users?: User[]
  message?: string
}

export default function handler(
  req: NextApiRequest,
  res: NextApiResponse<ResponseData>
) {
  const { method } = req
  
  switch (method) {
    case 'GET':
      // Get users
      res.status(200).json({ 
        users: [
          { id: 1, name: 'John' },
          { id: 2, name: 'Jane' }
        ] 
      })
      break
    case 'POST':
      // Create user
      const { name } = req.body
      res.status(201).json({ message: `User ${name} created` })
      break
    default:
      res.setHeader('Allow', ['GET', 'POST'])
      res.status(405).end(`Method ${method} Not Allowed`)
  }
}

Route Handlers (App Router)

Creating API endpoints with App Router and TypeScript

Next.js
// app/api/users/route.ts
import { NextResponse } from 'next/server'

interface User {
  id: number
  name: string
}

// GET handler
export async function GET() {
  const users: User[] = [
    { id: 1, name: 'John' },
    { id: 2, name: 'Jane' }
  ]
  return NextResponse.json(users)
}

// POST handler
export async function POST(request: Request) {
  const data = await request.json()
  return NextResponse.json({ message: 'User created', data })
}

// Dynamic route handler
// app/api/users/[id]/route.ts
export async function GET(
  request: Request,
  { params }: { params: { id: string } }
) {
  const id = params.id
  return NextResponse.json({ id, name: 'John Doe' })
}

TypeScript Patterns

Common Types

Common TypeScript types and patterns for Next.js

Next.js
// Common TypeScript types for Next.js

// Pages Router
import type { 
  NextPage,
  GetStaticProps,
  GetStaticPaths,
  GetServerSideProps,
  NextApiRequest,
  NextApiResponse
} from 'next'

// Page component with props
interface HomeProps {
  posts: Post[]
  totalCount: number
}

const Home: NextPage<HomeProps> = ({ posts, totalCount }) => {
  // ...
}

// GetStaticProps with typed return
export const getStaticProps: GetStaticProps<HomeProps> = async () => {
  // ...
  return {
    props: {
      posts: [],
      totalCount: 0
    },
    revalidate: 60
  }
}

// App Router
// Route params
interface PageParams {
  slug: string
}

// Page props
interface PageProps {
  params: PageParams
  searchParams: { [key: string]: string | string[] | undefined }
}

export default function Page({ params, searchParams }: PageProps) {
  // ...
}

Type-Safe API Calls

Type-safe API calls in Next.js

Next.js
// Define API response types
interface User {
  id: number
  name: string
  email: string
}

// Type-safe API client function
async function fetchUsers(): Promise<User[]> {
  const res = await fetch('/api/users')
  
  if (!res.ok) {
    throw new Error('Failed to fetch users')
  }
  
  return res.json()
}

// Using with SWR
import useSWR from 'swr'

function UserList() {
  const { data, error, isLoading } = useSWR<User[], Error>(
    '/api/users',
    fetchUsers
  )
  
  if (error) return <div>Failed to load</div>
  if (isLoading) return <div>Loading...</div>
  
  return (
    <ul>
      {data?.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  )
}

Optimization

Image Component

Using the Next.js Image component with TypeScript

Next.js
// Using the Image component with TypeScript
import Image from 'next/image'

interface ProfileProps {
  src: string
  alt: string
  priority?: boolean
}

export function Profile({ src, alt, priority = false }: ProfileProps) {
  return (
    <div>
      <Image
        src={src}
        alt={alt}
        width={500}
        height={300}
        priority={priority}
      />
    </div>
  )
}

// Usage
<Profile 
  src="/images/profile.jpg"
  alt="User profile"
  priority
/>

Environment Variables

Type-safe environment variables

Next.js
// env.d.ts - Type definitions for environment variables
declare namespace NodeJS {
  interface ProcessEnv {
    NEXT_PUBLIC_API_URL: string
    DATABASE_URL: string
    API_KEY: string
  }
}

// Using environment variables
const apiUrl = process.env.NEXT_PUBLIC_API_URL
const apiKey = process.env.API_KEY // Only available server-side

Next.js - Interactive Developer Reference

Hover over code blocks to copy or run in live playground