How to Create Pages in Nextjs
How to Create Pages in Next.js Next.js has rapidly become the go-to framework for building modern, high-performance web applications in React. Its intuitive file-based routing system, server-side rendering (SSR), static site generation (SSG), and built-in optimization features make it ideal for everything from simple blogs to enterprise-scale applications. At the heart of Next.js is its powerful p
How to Create Pages in Next.js
Next.js has rapidly become the go-to framework for building modern, high-performance web applications in React. Its intuitive file-based routing system, server-side rendering (SSR), static site generation (SSG), and built-in optimization features make it ideal for everything from simple blogs to enterprise-scale applications. At the heart of Next.js is its powerful page creation system a clean, convention-driven approach that eliminates the need for complex routing configurations. In this comprehensive guide, youll learn exactly how to create pages in Next.js, from the most basic setup to advanced patterns that scale with your application. Whether youre new to Next.js or looking to refine your workflow, this tutorial will equip you with the knowledge to build fast, SEO-friendly, and maintainable applications with confidence.
Step-by-Step Guide
Setting Up a Next.js Project
Before you can create pages, you need a working Next.js project. The fastest way to get started is by using the official create-next-app CLI tool. Open your terminal and run the following command:
npx create-next-app@latest my-next-app
The CLI will prompt you with a series of options. For a standard setup, accept the defaults: choose TypeScript if you prefer type safety, ESLint for code quality, and Tailwind CSS if you want a pre-configured styling framework. When prompted to use the App Router, select Yes this is the modern, recommended approach in Next.js 13+.
Once the installation completes, navigate into your project folder:
cd my-next-app
Start the development server:
npm run dev
Open http://localhost:3000 in your browser. Youll see the default Next.js welcome page. This confirms your project is running successfully.
Understanding the App Router Structure
Next.js 13 introduced the App Router, which replaced the older Pages Router. The App Router organizes pages using a hierarchical folder structure inside the app directory. This structure is more flexible and enables advanced features like nested layouts, server components, and streaming.
By default, your app folder contains a page.tsx (or page.js) file. This file represents the root route of your application /. When a user visits your sites homepage, Next.js renders the content of this file.
To create additional pages, simply add new folders inside the app directory and include a page.tsx file in each. For example:
app/page.tsx?/app/about/page.tsx?/aboutapp/blog/page.tsx?/blogapp/contact/page.tsx?/contact
Each page.tsx file is a React component that returns JSX. Heres an example of a simple About page:
// app/about/page.tsx
export default function AboutPage() {
return (
<div>
<h1>About Us</h1>
<p>We are a team of developers building the future of the web.</p>
</div>
);
}
After saving this file, refresh your browser and navigate to /about. Youll immediately see your new page rendered without any additional configuration.
Creating Dynamic Pages with Square Brackets
One of Next.jss most powerful features is its ability to generate dynamic routes using square brackets. This is essential for content-heavy sites like blogs, e-commerce platforms, or user profiles.
To create a dynamic page, wrap the dynamic segment in square brackets. For example, to create a blog post page that accepts a dynamic slug:
- Create a folder named
app/blog/[slug]. - Inside that folder, create a
page.tsxfile.
Now, your route will match any value after /blog/. For example:
/blog/my-first-post/blog/nextjs-tutorial/blog/seo-best-practices
In your page.tsx, you can access the dynamic segment using the params prop:
// app/blog/[slug]/page.tsx
export default function BlogPost({ params }: { params: { slug: string } }) {
return (
<div>
<h1>Blog Post: {params.slug}</h1>
<p>This is the content for the post titled "{params.slug}"</p>
</div>
);
}
For production use, youll typically fetch data based on the slug. Next.js provides the generateStaticParams function for static generation and generateMetadata for SEO optimization.
Using generateStaticParams for Static Generation
If youre using static site generation (SSG), you need to tell Next.js which dynamic routes to pre-render at build time. This is done using the generateStaticParams function.
Lets say you have a list of blog posts stored in a JSON file or fetched from a CMS. Heres how youd implement it:
// app/blog/[slug]/page.tsx
import { getBlogPosts } from '@/lib/data';
export default function BlogPost({ params }: { params: { slug: string } }) {
const post = getBlogPosts().find(p => p.slug === params.slug);
if (!post) {
return <h1>Post not found</h1>;
}
return (
<div>
<h1>{post.title}</h1>
<time>{post.date}</time>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</div>
);
}
export async function generateStaticParams() {
const posts = getBlogPosts();
return posts.map(post => ({
slug: post.slug,
}));
}
When you run npm run build, Next.js will automatically generate HTML files for each blog post listed in your data source. This ensures lightning-fast load times and excellent SEO performance.
Creating Nested Routes
Next.js supports nested routing, allowing you to build complex UIs with shared layouts. For example, you might want a blog section with subpages like /blog/categories and /blog/authors.
To achieve this, create nested folders:
app/blog/page.tsx?/blogapp/blog/categories/page.tsx?/blog/categoriesapp/blog/authors/page.tsx?/blog/authors
You can also create a layout that wraps all blog pages. Create a layout.tsx file inside the app/blog folder:
// app/blog/layout.tsx
export default function BlogLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
<nav>
<ul>
<li><a href="/blog">All Posts</a></li>
<li><a href="/blog/categories">Categories</a></li>
<li><a href="/blog/authors">Authors</a></li>
</ul>
</nav>
<main>
{children}
</main>
</div>
);
}
Now, every page inside the blog directory will automatically include this navigation bar. This reduces code duplication and improves maintainability.
Handling 404 Pages
Next.js automatically renders a built-in 404 page when a route doesnt exist. However, you can customize it by creating a not-found.tsx file in your app directory.
// app/not-found.tsx
export default function NotFound() {
return (
<div style={{ padding: '4rem', textAlign: 'center' }}>
<h1>404 Page Not Found</h1>
<p>The page youre looking for doesnt exist.</p>
<a href="/">Go Home</a>
</div>
);
}
This file will be displayed whenever a user visits a route that doesnt match any page in your app. Its a simple but essential part of user experience.
Using Server Components for Better Performance
By default, all components in the App Router are Server Components. This means they execute on the server, reducing client-side JavaScript and improving performance and SEO.
You dont need to do anything special just write your components normally. For example:
// app/dashboard/page.tsx
import { getDashboardData } from '@/lib/api';
export default function Dashboard() {
const data = getDashboardData(); // This runs on the server
return (
<div>
<h1>Your Dashboard</h1>
<p>Welcome back, {data.user.name}</p>
<ul>
{data.items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}
Server Components are ideal for fetching data, reading files, or interacting with databases. They eliminate the need for client-side data fetching in many cases, resulting in faster initial loads.
Client Components When Needed
Some interactions like handling form submissions, animations, or user input require client-side JavaScript. To mark a component as a Client Component, add the use client directive at the top of the file:
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
Use Client Components sparingly only when you need interactivity. Overusing them can increase bundle size and hurt performance.
Best Practices
Use Meaningful File and Folder Names
Consistency in naming improves readability and collaboration. Use lowercase, hyphen-separated names for routes: /contact-us instead of /ContactUs. Avoid special characters, spaces, or uppercase letters in folder names.
Organize by Feature, Not Type
Instead of grouping files by type (e.g., all components in one folder, all pages in another), group them by feature or module. For example:
app/user/profile/page.tsxapp/user/settings/page.tsxapp/user/settings/layout.tsx
This structure makes it easier to locate and maintain related code as your project grows.
Always Use generateMetadata for SEO
Next.js provides the generateMetadata function to dynamically set page titles, descriptions, Open Graph tags, and more. This is critical for search engine visibility and social sharing.
// app/blog/[slug]/page.tsx
import { getBlogPost } from '@/lib/data';
export default function BlogPost({ params }: { params: { slug: string } }) {
const post = getBlogPost(params.slug);
if (!post) return <h1>Not Found</h1>;
return (
<div>
<h1>{post.title}</h1>
<article>{post.content}</article>
</div>
);
}
export async function generateMetadata({
params,
}: {
params: { slug: string };
}) {
const post = getBlogPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [post.image],
},
};
}
Never rely on default metadata. Always define it explicitly to ensure consistent SEO performance across all pages.
Prefer Static Generation Over Server-Side Rendering
While Next.js supports both SSR and SSG, SSG is generally preferred for public-facing content. Pages generated at build time are cached by CDNs and delivered instantly to users worldwide. SSR is useful for highly personalized or frequently changing content (like dashboards), but it adds latency.
Use generateStaticParams and revalidate (for ISR) to balance freshness and performance.
Optimize Images and Assets
Next.js includes a built-in Image component that automatically optimizes images. Always use next/image instead of standard <img> tags:
import Image from 'next/image';
export default function HomePage() {
return (
<div>
<Image
src="/hero-image.jpg"
alt="Hero banner"
width={1200}
height={600}
priority
/>
</div>
);
}
The Image component automatically converts images to WebP, serves responsive sizes, and lazy-loads offscreen images. This can drastically improve Lighthouse scores.
Implement Proper Navigation
Use next/link for client-side navigation between pages. Avoid using standard anchor tags (<a>) unless linking to external sites.
import Link from 'next/link';
export default function Navbar() {
return (
<nav>
<ul>
<li><Link href="/">Home</Link></li>
<li><Link href="/about">About</Link></li>
<li><Link href="/blog">Blog</Link></li>
</ul>
</nav>
);
}
This enables SPA-like navigation with faster transitions and preserved state.
Test Your Pages Across Devices and Networks
Use Chrome DevTools to simulate mobile devices and slow 3G connections. Test your pages with Lighthouse to identify performance bottlenecks. Aim for scores above 90 in performance, accessibility, and SEO.
Version Control and Deployment
Always commit your node_modules folder to .gitignore. Deploy your Next.js app using Vercel (the creators of Next.js), Netlify, or any platform that supports Node.js. Vercel offers automatic preview deployments for every pull request a huge productivity boost for teams.
Tools and Resources
Official Next.js Documentation
The Next.js documentation is comprehensive and regularly updated. It includes guides, API references, and code examples for every feature. Bookmark it as your primary reference.
Next.js Examples Repository
GitHub hosts an official examples repository with dozens of real-world templates from blogs and e-commerce stores to CMS integrations. These are invaluable for learning advanced patterns.
VS Code Extensions
Install these extensions to improve your workflow:
- ESLint for code quality
- Prettier for consistent formatting
- Next.js Snippets for quick code generation
- Path Intellisense for auto-completing file paths
Content Management Systems (CMS)
Integrate Next.js with headless CMS platforms to manage content dynamically:
- Sanity flexible, developer-friendly
- Contentful enterprise-grade
- Strapi open-source, self-hosted
- WordPress REST API for migrating existing sites
Use the getStaticProps or generateStaticParams functions to fetch content at build time.
Analytics and Monitoring
Integrate analytics tools like Google Analytics, Plausible, or PostHog to track user behavior. Next.js makes it easy to add tracking scripts via the app/layout.tsx file:
// app/layout.tsx
import Script from 'next/script';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<head>
<Script strategy="afterInteractive">
{
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
}
</Script>
</head>
<body>
{children}
</body>
</html>
);
}
Testing Tools
Use Jest and React Testing Library to write unit and integration tests for your pages and components. Test both the UI and data-fetching logic to ensure reliability.
Performance Auditing Tools
- Lighthouse built into Chrome DevTools
- Web Vitals measure real user experience
- Bundlephobia analyze package sizes
- Next.js Analytics (Vercel) track performance metrics in production
Real Examples
Example 1: Personal Blog with Markdown
Many developers use Next.js to build personal blogs powered by Markdown files. Heres how it works:
- Store blog posts as
.mdfiles incontent/posts/. - Use
remarkandrehypeto convert Markdown to HTML. - Read files using
fs(Node.js) ingenerateStaticParams. - Render posts with
dangerouslySetInnerHTMLor a Markdown component.
Benefits:
- No database required
- Fast, static builds
- Easy to version control
- Perfect for SEO
Example 2: E-Commerce Product Pages
For an e-commerce site, you might have:
app/products/page.tsxlists all productsapp/products/[id]/page.tsxindividual product detailapp/products/category/[slug]/page.tsxfiltered by category
Each product page fetches data from an API like Shopify or Medusa. Youd use generateStaticParams to pre-render thousands of product pages at build time. For frequently updated inventory, use Incremental Static Regeneration (ISR) with a revalidate value of 60 seconds:
export async function generateStaticParams() {
const products = await fetch('https://api.example.com/products').then(res => res.json());
return products.map(product => ({ id: product.id }));
}
export default async function ProductPage({ params }: { params: { id: string } }) {
const product = await fetch(https://api.example.com/products/${params.id}).then(res => res.json());
return (
<div>
<h1>{product.name}</h1>
<p>${product.price}</p>
<button>Add to Cart</button>
</div>
);
}
export const revalidate = 60; // Re-generate every minute
Example 3: Multi-Language Site
Next.js supports internationalization (i18n) out of the box. Configure it in next.config.js:
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
i18n: {
locales: ['en', 'es', 'fr'],
defaultLocale: 'en',
},
};
module.exports = nextConfig;
Then create locale-specific folders:
app/en/page.tsxapp/es/page.tsxapp/fr/page.tsx
Next.js automatically prefixes routes with the locale: /es/about, /fr/contact, etc. You can use next-intl or next-i18next for advanced translation management.
FAQs
Can I use Next.js without TypeScript?
Yes. Next.js fully supports JavaScript. When creating a new project, choose No for TypeScript. However, TypeScript is strongly recommended for larger applications due to improved code reliability and developer experience.
Do I need a server to run Next.js?
No. Next.js apps can be deployed as static sites (SSG) and served from any CDN. You only need a server if youre using Server Components with data fetching that requires backend access (like database queries). Even then, platforms like Vercel handle serverless functions automatically.
How do I add custom fonts in Next.js?
Use the app/layout.tsx file to import fonts. For Google Fonts:
// app/layout.tsx
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'] });
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
</html>
);
}
Whats the difference between App Router and Pages Router?
The App Router (introduced in Next.js 13) uses the app directory and supports Server Components, nested layouts, and streaming. The Pages Router (legacy) uses the pages directory and relies on client-side components. New projects should use the App Router. Existing projects can gradually migrate.
Can I use Next.js for mobile apps?
Next.js is designed for web applications. However, you can use frameworks like Expo + Next.js or React Native Web to share code between web and mobile platforms. Next.js itself does not build native mobile apps.
How do I handle authentication in Next.js?
Use NextAuth.js (now Auth.js) the official authentication library for Next.js. It supports OAuth, email/password, and social logins. Store sessions in cookies or JWT, and protect routes using middleware or server components.
Is Next.js good for SEO?
Yes. Next.js excels at SEO due to server-side rendering, static generation, automatic meta tags, and optimized asset loading. Pages are rendered with clean HTML, making them easily crawlable by search engines.
How do I deploy a Next.js app?
The easiest way is to deploy to Vercel simply push your code to GitHub, and Vercel auto-deploys it. You can also deploy to Netlify, AWS Amplify, or any Node.js-compatible host. For static sites, you can even upload the out folder (generated by next export) to any static hosting service.
Conclusion
Creating pages in Next.js is one of the most straightforward and powerful aspects of the framework. With its file-based routing system, you can build complex, scalable applications without writing a single line of routing configuration. From simple static pages to dynamic, data-driven content, Next.js adapts to your needs whether youre building a portfolio, a blog, an e-commerce store, or a full-fledged SaaS product.
By following the best practices outlined in this guide organizing your app structure logically, leveraging static generation, optimizing metadata, and using the right tools youll not only create faster, more reliable websites, but also future-proof your development workflow. The App Router, server components, and built-in performance optimizations make Next.js the most developer-friendly and SEO-optimized framework available today.
Start small, experiment with dynamic routes, integrate a CMS, and gradually add complexity. The more you build, the more youll appreciate Next.jss elegance and power. Whether youre a beginner or an experienced developer, mastering page creation in Next.js is a foundational skill that will elevate your web development career.