Basics
Fundamentals of Next.js, project setup, configuration, and core concepts for building React applications.
Getting Started
Installation and Setup
# Create a new Next.js app
npx create-next-app@latest my-app
npx create-next-app@latest my-app --typescript
npx create-next-app@latest my-app --tailwind
# With specific options
npx create-next-app@latest my-app --typescript --tailwind --eslint --app --src-dir --import-alias "@/*"
# Navigate to project
cd my-app
# Start development server
npm run dev
# or
yarn dev
# or
pnpm dev
Manual Installation
# Create new project
mkdir my-nextjs-app
cd my-nextjs-app
npm init -y
# Install Next.js and React
npm install next react react-dom
# Install TypeScript (optional)
npm install --save-dev typescript @types/react @types/node
# Install ESLint (optional)
npm install --save-dev eslint eslint-config-next
Package.json Scripts
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"type-check": "tsc --noEmit"
}
}
Project Structure
App Router Structure (Next.js 13+)
my-app/
├── app/
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Home page
│ ├── loading.tsx # Loading UI
│ ├── error.tsx # Error UI
│ ├── not-found.tsx # 404 page
│ ├── globals.css # Global styles
│ ├── about/
│ │ └── page.tsx # /about route
│ ├── blog/
│ │ ├── page.tsx # /blog route
│ │ └── [slug]/
│ │ └── page.tsx # /blog/[slug] route
│ └── api/
│ └── users/
│ └── route.ts # API route
├── components/
│ ├── ui/
│ └── shared/
├── lib/
├── public/
├── styles/
├── next.config.js
├── package.json
└── tsconfig.json
Pages Router Structure (Legacy)
my-app/
├── pages/
│ ├── _app.tsx # App component
│ ├── _document.tsx # Document component
│ ├── index.tsx # Home page
│ ├── about.tsx # /about route
│ ├── blog/
│ │ ├── index.tsx # /blog route
│ │ └── [slug].tsx # /blog/[slug] route
│ └── api/
│ └── users.ts # API route
├── components/
├── lib/
├── public/
├── styles/
├── next.config.js
├── package.json
└── tsconfig.json
Next.js Configuration
next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// Enable experimental features
experimental: {
appDir: true,
serverActions: true,
serverComponentsExternalPackages: ['sequelize'],
},
// Image optimization
images: {
domains: ['example.com', 'images.unsplash.com'],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
formats: ['image/webp', 'image/avif'],
},
// Redirects
async redirects() {
return [
{
source: '/old-page',
destination: '/new-page',
permanent: true,
},
];
},
// Rewrites
async rewrites() {
return [
{
source: '/api/:path*',
destination: 'https://api.example.com/:path*',
},
];
},
// Headers
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'X-Custom-Header',
value: 'my-custom-value',
},
],
},
];
},
// Environment variables
env: {
CUSTOM_KEY: 'value',
},
// Build output
output: 'standalone', // or 'export'
// Webpack configuration
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// Custom webpack config
return config;
},
// TypeScript configuration
typescript: {
ignoreBuildErrors: false,
},
// ESLint configuration
eslint: {
ignoreDuringBuilds: false,
},
};
module.exports = nextConfig;
TypeScript Configuration
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "es6"],
"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"
}
],
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@/components/*": ["./components/*"],
"@/lib/*": ["./lib/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
Core Concepts
App Router (Next.js 13+)
// app/layout.tsx - Root Layout
import './globals.css';
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'] });
export const metadata = {
title: 'My App',
description: 'Generated by create next app',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
<header>
<nav>Navigation</nav>
</header>
<main>{children}</main>
<footer>Footer</footer>
</body>
</html>
);
}
// app/page.tsx - Home Page
export default function HomePage() {
return (
<div>
<h1>Welcome to Next.js</h1>
<p>This is the home page</p>
</div>
);
}
// app/about/page.tsx - About Page
export default function AboutPage() {
return (
<div>
<h1>About Us</h1>
<p>This is the about page</p>
</div>
);
}
Pages Router (Legacy)
// pages/_app.tsx - App Component
import type { AppProps } from 'next/app';
import '../styles/globals.css';
export default function App({ Component, pageProps }: AppProps) {
return (
<div>
<header>
<nav>Navigation</nav>
</header>
<main>
<Component {...pageProps} />
</main>
<footer>Footer</footer>
</div>
);
}
// pages/index.tsx - Home Page
import Head from 'next/head';
export default function HomePage() {
return (
<>
<Head>
<title>My App</title>
<meta name="description" content="Generated by create next app" />
</Head>
<div>
<h1>Welcome to Next.js</h1>
<p>This is the home page</p>
</div>
</>
);
}
Environment Variables
.env Files
# .env.local (local development)
DATABASE_URL=localhost:5432
API_KEY=your-api-key
NEXTAUTH_SECRET=your-secret
# .env.production (production)
DATABASE_URL=production-db-url
API_KEY=production-api-key
# .env (all environments)
NEXT_PUBLIC_API_URL=https://api.example.com
Using Environment Variables
// Server-side only
const databaseUrl = process.env.DATABASE_URL;
// Client-side accessible (must start with NEXT_PUBLIC_)
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
// In next.config.js
module.exports = {
env: {
CUSTOM_KEY: process.env.CUSTOM_KEY,
},
};
Built-in Components
Link Component
import Link from 'next/link';
export default function Navigation() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
<Link href="/blog/hello-world">Blog Post</Link>
{/* Dynamic routes */}
<Link href={`/users/${userId}`}>User Profile</Link>
{/* Query parameters */}
<Link href="/search?q=nextjs">Search</Link>
{/* External links */}
<Link href="https://nextjs.org" target="_blank">
Next.js Docs
</Link>
{/* Programmatic navigation */}
<button onClick={() => router.push('/dashboard')}>
Go to Dashboard
</button>
</nav>
);
}
Image Component
import Image from 'next/image';
export default function ImageExample() {
return (
<div>
{/* Local images */}
<Image
src="/hero-image.jpg"
alt="Hero Image"
width={800}
height={600}
priority
/>
{/* Remote images */}
<Image
src="https://example.com/image.jpg"
alt="Remote Image"
width={500}
height={300}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>
{/* Responsive images */}
<Image
src="/responsive-image.jpg"
alt="Responsive Image"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
className="object-cover"
/>
</div>
);
}
Head Component (Pages Router)
import Head from 'next/head';
export default function SEOPage() {
return (
<>
<Head>
<title>Page Title</title>
<meta name="description" content="Page description" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
{/* Open Graph */}
<meta property="og:title" content="Page Title" />
<meta property="og:description" content="Page description" />
<meta property="og:image" content="/og-image.jpg" />
{/* Twitter Card */}
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Page Title" />
<meta name="twitter:description" content="Page description" />
{/* Custom styles */}
<style jsx>{`
.custom-class {
color: blue;
}
`}</style>
</Head>
<div>
<h1>SEO Optimized Page</h1>
<p>This page has proper SEO metadata</p>
</div>
</>
);
}
Development Tools
Next.js CLI Commands
# Development
npm run dev # Start development server
npm run dev -- -p 3001 # Start on different port
# Build
npm run build # Build for production
npm run start # Start production server
# Analysis
npm run build -- --analyze # Bundle analysis
npm run lint # Run ESLint
npm run type-check # TypeScript check
# Export static site
npm run build && npm run export
Development Features
// Hot reloading is automatic in development
// Error overlay shows detailed error information
// Fast refresh preserves React state during edits
// Automatic TypeScript compilation
// Built-in ESLint support
File-based Routing
Basic Routes
app/page.tsx → /
app/about/page.tsx → /about
app/blog/page.tsx → /blog
app/blog/[slug]/page.tsx → /blog/hello-world
Dynamic Routes
// app/blog/[slug]/page.tsx
export default function BlogPost({ params }: { params: { slug: string } }) {
return <h1>Blog Post: {params.slug}</h1>;
}
// app/user/[id]/page.tsx
export default function UserProfile({ params }: { params: { id: string } }) {
return <h1>User ID: {params.id}</h1>;
}
Catch-all Routes
// app/docs/[...slug]/page.tsx
export default function DocsPage({ params }: { params: { slug: string[] } }) {
return <h1>Docs: {params.slug.join('/')}</h1>;
}
// Matches: /docs/getting-started, /docs/api/reference, etc.
Quick Reference
Essential Commands
npx create-next-app@latest- Create new Next.js appnpm run dev- Start development servernpm run build- Build for productionnpm run start- Start production servernpm run lint- Run ESLint
Key Concepts
- App Router - New routing system (Next.js 13+)
- Pages Router - Legacy routing system
- Server Components - React components that run on server
- Client Components - React components that run on client
- File-based Routing - Routes based on file structure
Built-in Components
<Link>- Client-side navigation<Image>- Optimized images<Head>- HTML head management (Pages Router)<Script>- Script optimization
Configuration Files
next.config.js- Next.js configurationtsconfig.json- TypeScript configuration.env.local- Environment variablespackage.json- Project dependencies and scripts
Best Practices
- Use TypeScript for better development experience
- Implement proper SEO with metadata
- Optimize images with Next.js Image component
- Use environment variables for configuration
- Follow Next.js file and folder conventions
- Enable ESLint for code quality