ZG
Zafer GökBlog

Next.js Getting Started Guide: Build Modern Web Applications

ZG
Zafer Gök
30.01.2026
25 dk
Next.js GuideReact frameworkApp RouterWhat are SSR and SSG?Next.js installationweb development
Next.js Getting Started Guide: Build Modern Web Applications

What is Next.js?

Next.js is a React-based web development framework that complements many features missing in React. Developed by Vercel, this framework is optimized for building production-ready web applications.

While Next.js is based on React's component-based approach, it offers server-side rendering (SSR), static site generation (SSG), file-based routing, API routes, and much more. These features simplify the development process while increasing performance.

One of the most important features of Next.js is the "zero configuration" philosophy with its predefined configurations. This allows developers to start developing quickly without having to deal with complex webpack or babel configurations.

Creating a Project

Starting a new project with Next.js is quite easy. The following command will create a modern Next.js application:

npx create-next-app@latest my-nextjs-app
# or
yarn create next-app my-nextjs-app
# or
pnpm create next-app my-nextjs-app

This command will ask for preferences regarding TypeScript support, ESLint configuration, and other modern features. Default values will often be sufficient.

After the project is created, you can start the development server with the following command:

cd my-nextjs-app
npm run dev

You can see your application by going to http://localhost:3000 in your browser.

File-Based Routing

One of the most powerful features of Next.js is its file system-based routing mechanism. This means you don't need to do any special router configuration to organize your application's pages and routes.

In Next.js 13 and later versions, the 'App Router' structure is used. In this structure, each folder within the

app

directory corresponds to a route. Within each route folder, there is a <code>page.js</code> or <code>page.tsx</code> file that creates the content of the page:

app/                  # Main app directory
├── page.tsx          # Home page (/)
├── about/            # Folder for About page
│   └── page.tsx      # About page (/about)
├── blog/             # Folder for Blog route
│   ├── page.tsx      # Blog main page (/blog)
│   └── [slug]/       # Folder for dynamic route
│       └── page.tsx  # Specific blog post (/blog/my-post)

File names have special meanings:

  • page.tsx: Defines the UI component for a route

  • ayout.tsx: Defines the common layout for one or more routes

  • loading.tsx: Shows the loading status for a route

  • error.tsx: Shows the error status for a route

  • not-found.tsx: Shows the 404 page

Dynamic routes are created with folder names in square brackets. For example, <code>[slug]</code> defines a dynamic parameter and this parameter can be accessed from within the component.

A Simple Page Example

Creating a page in Next.js is very simple. Here's a simple home page example in <code>app/page.tsx</code>:

// app/page.tsx
export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <h1 className="text-4xl font-bold">
        My First Page with Next.js
      </h1>
      <p className="mt-4 text-xl">
        Congratulations on starting to use Next.js!
      </p>
      <div className="mt-8">
        <a 
          href="https://nextjs.org/docs" 
          className="text-blue-500 hover:text-blue-700 transition-colors"
        >
          Documentation →
        </a>
      </div>
    </main>
  );
}

In Next.js 13 and later versions, all components are Server Components by default. If you want a component to run on the client side, you must add the <code>'use client'</code> directive to the top of the file.

Data Fetching Methods

Data fetching in Next.js is an important issue that determines how your application will be created. Next.js offers three basic data fetching methods:

1. Data Fetching with Server Components: It is the default and recommended method.


// app/users/page.tsx
async function getUsers() {
  const res = await fetch('https://api.example.com/users')
  if (!res.ok) throw new Error('Failed to load users')
  return res.json()
}

export default async function UsersPage() {
  const users = await getUsers()
  
  return (
    <div>
      <h1>Users</h1>
      <ul>
        {users.map(user => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  )
}

2. Data Fetching with useEffect in Client Components: Can be used in components running on the client side.

3. Using SWR or React Query: More advanced libraries can be used for client-side data fetching, caching, and revalidation.

In the Next.js App Router, data fetching with Server Components is generally the preferred method because it:

  • Data fetching process happens on the server side, not on the client side

  • Reduces JavaScript bundle size

  • Does not send sensitive information such as API keys to the client side

  • Provides better SEO results

Creating an API Route

Next.js also allows you to create your own API endpoints. This allows you to manage your application's server-side logic within the same project.

With the App Router, API routes are defined with <code>route.js</code> or <code>route.ts</code> files under the <code>app/api</code> directory:

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

export async function GET() {
  // Connecting to database, fetching data etc.
  const users = [
    { id: 1, name: "Ali Yilmaz" },
    { id: 2, name: "Ayse Kaya" }
  ]
  
  return NextResponse.json(users)
}

export async function POST(request: Request) {
  try {
    // receiving request body
    const body = await request.json()
    
    // actions required to create a new user
    // for example, saving to database
    
    return NextResponse.json(
      { message: "User created", user: body },
      { status: 201 }
    )
  } catch (error) {
    return NextResponse.json(
      { message: "An error occurred" },
      { status: 500 }
    )
  }
}

You can use these API routes from the client side as follows:

// To get data
const response = await fetch('/api/users')
const users = await response.json()
// To send data
const response = await fetch('/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'New User' })
})
const result = await response.json()

Next.js Component Structure

With Next.js 13, the concepts of Server and Client Components arrived. This distinction determines where components will be rendered and what features they will have.

Server Components (Default)

  • Rendered on the server and sent to the client as HTML

  • Reduces JavaScript load

  • Can directly access database, file system etc.

  • Cannot use React hooks such as <code>useState</code>, <code>useEffect</code>

  • Cannot access browser APIs

Client Components

  • Defined with the <code>'use client'</code> directive

  • Rendered on the client side (in the browser)

  • Can use interactive state and event management

  • Can use React hooks

  • Can access browser APIs

// Server Component example (app/users/page.tsx)
import UserProfile from './user-profile' // Client component

async function getUsers() {
  // Database or API call
  return [
    { id: 1, name: "Ali", email: "ali@example.com" },
    { id: 2, name: "Zeynep", email: "zeynep@example.com" }
  ]
}

export default async function UsersPage() {
  const users = await getUsers()
  
  return (
    <div>
      <h1 className="text-2xl font-bold mb-4">Users</h1>
      
      {users.map(user => (
        // Client component is being used within a Server Component
        <UserProfile key={user.id} user={user} />
      ))}
    </div>
  )
}

// Client Component example (app/users/user-profile.tsx)
'use client'

import { useState } from 'react'

export default function UserProfile({ user }) {
  const [expanded, setExpanded] = useState(false)
  
  return (
    <div className="border p-4 mb-2 rounded">
      <h2 className="font-semibold">{user.name}</h2>
      
      <button 
        onClick={() => setExpanded(!expanded)}
        className="text-blue-500 mt-2"
      >
        {expanded ? 'Hide' : 'Show Details'}
      </button>
      
      {expanded && (
        <div className="mt-2 text-gray-600">
          <p>Email: {user.email}</p>
        </div>
      )}
    </div>
  )
}

Image Optimization

Next.js provides image optimization for the modern web with the <code>Image</code> component:

  • Automatically optimizes images (formats like WebP, AVIF)

  • Makes images responsive

  • Applies lazy loading

  • Prevents Cumulative Layout Shift (CLS)

    import Image from 'next/image'
    
    export default function ProductCard() {
      return (
        <div className="relative w-full h-64">
          <Image
            src="/images/product.jpg"    // Image path
            alt="Product image"           // Alt text for accessibility
            fill                         // Fills the main container
            sizes="(max-width: 768px) 100vw, 50vw" // Responsive size
            priority={false}             // Lazy loading (default)
            className="object-cover rounded-lg" // Tailwind classes
          />
        </div>
      )
    }

Best Practices and Tips

Some best practices and tips to consider for efficiency and performance when developing with Next.js:

  • File and Folder Structure

  • Separate page and component logic with App Router (<code>app/</code> directory)

  • Keep general components in the <code>components/</code> folder

  • Collect helper functions under <code>lib/</code> or <code>utils/</code>

Performance Improvements

  • Prefer Server Components as much as possible

  • Use the <code>Image</code> component for image optimization

  • Render static content as statically as possible

Security Recommendations

  • Always validate input data in API routes

  • Store secret keys and credentials in environment variables

  • Add CSRF and XSS protections

These tips and best practices will help you have a smooth experience while developing with Next.js and create high-quality applications.

Next.js Getting Started Guide: Build Modern Web Applications | Zafer Gök | Zafer Gök