How to Create Pages in Nextjs

Introduction Next.js has become the de facto framework for building modern web applications in React, offering a powerful blend of server-side rendering, static site generation, and client-side hydration—all out of the box. As adoption grows, so does the complexity of implementing page structures correctly. Many developers, especially those new to Next.js, struggle with choosing the right approach

Oct 25, 2025 - 13:29
Oct 25, 2025 - 13:29
 0

Introduction

Next.js has become the de facto framework for building modern web applications in React, offering a powerful blend of server-side rendering, static site generation, and client-side hydrationall out of the box. As adoption grows, so does the complexity of implementing page structures correctly. Many developers, especially those new to Next.js, struggle with choosing the right approach to page creation, leading to performance bottlenecks, SEO issues, or maintenance nightmares.

This guide presents the top 10 trusted, battle-tested methods to create pages in Next.jseach validated by production usage, community feedback, and official documentation. Whether you're building a marketing site, an e-commerce platform, or a dynamic SaaS dashboard, these methods ensure reliability, scalability, and SEO-friendliness. Well explain not just how to implement them, but why they work, when to use them, and how they compare to alternatives.

By the end of this guide, youll have a clear, actionable framework for choosing the right page creation strategy in Next.jsno guesswork, no fluff, just proven techniques you can trust.

Why Trust Matters

In the fast-evolving world of JavaScript frameworks, trends come and go. Whats popular today may be deprecated tomorrow. Thats why trust isnt just a nice-to-haveits a necessity. When building pages in Next.js, choosing unverified or experimental patterns can lead to broken builds, poor Core Web Vitals, or search engine penalties.

Trusted methods are those that:

  • Are endorsed by the Next.js core team or documented in official guides
  • Have been tested across multiple environments and deployment platforms
  • Support SEO best practices, including proper metadata, structured data, and crawlability
  • Are maintainable over time with clear patterns and minimal technical debt
  • Integrate seamlessly with TypeScript, ESLint, and testing tools

Untrusted methods often rely on third-party libraries with poor maintenance, undocumented edge cases, or non-standard routing conventions. These may work in development but fail under load, during builds, or when deployed to production environments like Vercel, Netlify, or AWS Amplify.

Trust also extends to performance. A page that loads slowly or fails to render server-side wont rank well on Google. Search engines prioritize pages that deliver content quickly and accurately. Trusted Next.js page creation methods ensure optimal hydration, efficient code splitting, and proper cachingall critical for SEO and user experience.

In this guide, every method listed has been selected based on real-world usage in high-traffic applications, community consensus on GitHub and Stack Overflow, and alignment with Next.jss own architectural principles. Youre not just learning how to create pagesyoure learning how to create pages that last.

Top 10 How to Create Pages in Next.js

1. Use File-Based Routing with app/ Directory (Next.js 13+)

Since Next.js 13, the app directory has become the recommended way to structure pages. It replaces the older pages directory and introduces React Server Components, streaming, and improved data fetching.

To create a page, simply create a folder inside the app directory and add a page.js (or page.tsx) file. For example:

app/

??? page.js ? Homepage (/)

??? about/

? ??? page.js ? About page (/about)

??? blog/

? ??? page.js ? Blog listing (/blog)

??? blog/[slug]/

??? page.js ? Dynamic blog post (/blog/my-first-post)

This method is trusted because its the official standard. It supports Server Components by default, enabling you to fetch data directly inside the component using async/await without needing getServerSideProps or getStaticProps.

Example:

// app/blog/[slug]/page.js

export default async function BlogPost({ params }) {

const res = await fetch(https://api.example.com/posts/${params.slug});

const post = await res.json();

return (

<article>

<h1>{post.title}</h1>

<div>{post.content}</div>

</article>

);

}

Benefits: Built-in SEO support via metadata, automatic code splitting, improved performance, and seamless integration with React Server Components. This is the most future-proof method and should be your default choice for new projects.

2. Create Static Pages with getStaticProps and pages/ Directory (Legacy but Reliable)

If youre maintaining a legacy Next.js application (pre-v13), the pages/ directory with getStaticProps remains a highly trusted method for creating static pages.

Place your page files in the pages folder. For static content like blog posts, product pages, or documentation, use getStaticProps to fetch data at build time.

Example:

// pages/about.js

export default function About({ data }) {

return (

<div>

<h1>{data.title}</h1>

<p>{data.content}</p>

</div>

);

}

export async function getStaticProps() {

const res = await fetch('https://api.example.com/about');

const data = await res.json();

return {

props: { data },

revalidate: 60, // Rebuild every 60 seconds (ISR)

};

}

This method is trusted because its been battle-tested since Next.js 9. It enables full static generation, which delivers the fastest possible load times and excellent SEO. The revalidate option allows for Incremental Static Regeneration (ISR), making static sites dynamic without sacrificing performance.

Use this method if youre on Next.js 12 or earlier, or if you need maximum compatibility with older deployment environments. Its ideal for content-heavy sites like documentation, marketing pages, or e-commerce catalogs.

3. Generate Dynamic Pages with getStaticPaths and getStaticProps

When you need to generate hundreds or thousands of pages at build timesuch as blog posts, product listings, or user profilescombine getStaticPaths with getStaticProps.

Example for a blog with dynamic slugs:

// pages/blog/[slug].js

export default function BlogPost({ post }) {

return (

<article>

<h1>{post.title}</h1>

<div>{post.content}</div>

</article>

);

}

export async function getStaticPaths() {

const res = await fetch('https://api.example.com/posts');

const posts = await res.json();

const paths = posts.map(post => ({

params: { slug: post.slug },

}));

return { paths, fallback: 'blocking' };

}

export async function getStaticProps({ params }) {

const res = await fetch(https://api.example.com/posts/${params.slug});

const post = await res.json();

return { props: { post } };

}

The key to trust here is the fallback: 'blocking' option. It ensures that if a page isnt generated at build time, Next.js will server-render it on the first request, then cache it for future visits. This prevents 404s and ensures all dynamic routes are covered without bloating your build.

This method is widely used in production by companies like Shopify, GitHub, and The New York Times. Its the gold standard for generating large-scale static sites with dynamic content.

4. Use Server-Side Rendering with getServerSideProps

When content must be fetched on every requestsuch as user-specific dashboards, real-time data, or personalized feedsgetServerSideProps is the most trusted method.

Example:

// pages/dashboard.js

export default function Dashboard({ user }) {

return (

<div>

<h1>Welcome, {user.name}</h1>

<p>Last login: {user.lastLogin}</p>

</div>

);

}

export async function getServerSideProps(context) {

const { req } = context;

const token = req.cookies.authToken;

if (!token) {

return { redirect: { destination: '/login', permanent: false } };

}

const res = await fetch('https://api.example.com/user', {

headers: { Authorization: Bearer ${token} },

});

const user = await res.json();

return { props: { user } };

}

This method is trusted because it guarantees fresh data on every request and supports authentication flows, redirects, and server-side logic. Its ideal for admin panels, user profiles, and e-commerce carts.

While it doesnt offer the same performance benefits as static generation, its the only reliable way to deliver personalized content without client-side hydration delays. Use it sparinglyonly when necessaryto avoid compromising your sites speed.

5. Implement Dynamic Routes with the app/ Directory and Server Components

In Next.js 13+, dynamic routes in the app directory are simpler and more powerful than ever. You no longer need getStaticPaths or getServerSidePropsyou just fetch data directly in the component.

Example:

// app/blog/[slug]/page.js

export default async function BlogPost({ params }) {

const { slug } = params;

const post = await fetch(https://api.example.com/posts/${slug}, {

next: { revalidate: 3600 }, // ISR in app directory

}).then(res => res.json());

return (

<article>

<h1>{post.title}</h1>

<div>{post.content}</div>

</article>

);

}

The next: { revalidate: 3600 } option enables Incremental Static Regeneration directly in the componentno additional functions needed. This is a major simplification over the legacy pages/ system.

This method is trusted because its the future of Next.js. It reduces boilerplate, improves developer experience, and integrates seamlessly with React Server Components. Its the recommended approach for all new projects built on Next.js 13 or higher.

6. Use Layouts and Nested Routing for Consistent UI Structure

One of the most powerful features of the app directory is layout composition. You can define shared layouts for groups of pages using a layout.js file.

Example structure:

app/

??? layout.js ? Root layout

??? blog/

? ??? layout.js ? Blog-specific layout

? ??? page.js ? Blog list

? ??? [slug]/

? ??? page.js ? Blog post

??? dashboard/

??? layout.js ? Authenticated layout

??? page.js ? Dashboard

Each layout.js file wraps its children:

// app/blog/layout.js

export default function BlogLayout({ children }) {

return (

<div>

<nav>Blog Navigation</nav>

<main>{children}</main>

</div>

);

}

This method is trusted because it eliminates duplication, improves maintainability, and enables efficient data fetching at the layout level. You can even fetch data in layouts using Server Componentsideal for headers, footers, or navigation menus that appear on every page.

By using nested layouts, you create a scalable architecture where changes to a shared component propagate automatically across all child pages. This reduces bugs and speeds up development.

7. Add Metadata with the Metadata API (Next.js 13+)

SEO isnt just about contentits about structured metadata. Next.js 13 introduced a clean, component-based Metadata API that replaces the older next/head approach.

Example:

// app/blog/[slug]/page.js

export async function generateMetadata({ params }) {

const post = await fetch(https://api.example.com/posts/${params.slug}).then(r => r.json());

return {

title: post.title,

description: post.excerpt,

openGraph: {

title: post.title,

description: post.excerpt,

images: [post.image],

},

};

}

export default async function BlogPost({ params }) {

const post = await fetch(https://api.example.com/posts/${params.slug}).then(r => r.json());

return (

<article>

<h1>{post.title}</h1>

<div>{post.content}</div>

</article>

);

}

This method is trusted because metadata is generated at build time or request time (depending on data source), ensuring search engines and social platforms receive accurate, up-to-date information. It supports Twitter Cards, Open Graph, canonical URLs, and robots directivesall without third-party libraries.

For legacy projects using pages/, you can still use next/head, but the Metadata API is the future. Its more performant, type-safe (with TypeScript), and integrates with Next.jss internal rendering pipeline.

8. Implement Internationalization (i18n) with Built-in Routing

For global applications, Next.js provides built-in internationalized routing. This method is trusted because its officially supported, scalable, and requires no external libraries.

Configure next.config.js:

// next.config.js

/** @type {import('next').NextConfig} */

const nextConfig = {

i18n: {

locales: ['en', 'es', 'fr'],

defaultLocale: 'en',

},

};

Create language-specific pages:

app/

??? en/

? ??? about/

? ??? page.js

??? es/

? ??? about/

? ??? page.js

??? fr/

??? about/

??? page.js

Or use dynamic routing with locale detection:

// app/about/page.js

export default function About({ locale }) {

const translations = {

en: 'About Us',

es: 'Acerca de',

fr: ' propos',

};

return <h1>{translations[locale]}</h1>;

}

export function getStaticPaths() {

return {

paths: ['en', 'es', 'fr'].map(locale => ({ params: { locale } })),

fallback: false,

};

}

This method ensures that each language version is crawlable, indexable, and properly linked via hreflang tags. Next.js automatically generates these tags for you when using i18n routing.

Trusted by multinational brands like Airbnb and Spotify, this approach avoids the pitfalls of client-side language switching, which can hurt SEO and accessibility.

9. Use Middleware for Route Protection and Redirection

Middleware allows you to run code before a request is completedideal for authentication, redirects, A/B testing, or content localization.

Create a middleware.js file in your project root:

// middleware.js

import { NextRequest, NextResponse } from 'next/server';

export function middleware(request) {

const { pathname } = request.nextUrl;

// Redirect logged-out users from protected routes

if (pathname.startsWith('/dashboard') && !request.cookies.get('authToken')) {

return NextResponse.redirect(new URL('/login', request.url));

}

// Add language prefix if missing

if (!pathname.startsWith('/en') && !pathname.startsWith('/es')) {

return NextResponse.redirect(new URL(/en${pathname}, request.url));

}

}

This method is trusted because it runs at the edge (on Vercels network), making it extremely fast and scalable. It doesnt require server resources or delay page rendering.

Use middleware to handle authentication flows, enforce HTTPS, redirect old URLs, or inject headers. Its far more efficient than handling redirects inside individual page components.

Middleware is especially valuable in large applications where page-level logic becomes unmanageable. It centralizes control and improves maintainability.

10. Optimize Images and Assets with Next.js Image and Font Components

Page performance is a ranking factor. Next.js provides built-in components to optimize images and fonts without third-party tools.

Use next/image for responsive, lazy-loaded images:

import Image from 'next/image';

export default function BlogPost({ post }) {

return (

<article>

<Image

src={post.image}

alt={post.title}

width={1200}

height={630}

priority={true} // Load above-the-fold images first

/>

<h1>{post.title}</h1>

</article>

);

}

Use next/font for self-hosted fonts with automatic optimization:

import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export default function MyApp({ children }) {

return (

<html lang="en">

<body className={inter.className}>

{children}

</body>

</html>

);

}

This method is trusted because it automatically converts images to WebP, generates multiple sizes, and serves them via CDN. It also prevents layout shift by reserving space before images load.

For fonts, next/font eliminates render-blocking resources and reduces CLS (Cumulative Layout Shift). Both components are zero-config and fully compatible with SEO best practices.

Never use <img> or @font-face directly in Next.js without these componentstheyre the industry standard for performance-critical applications.

Comparison Table

Method Next.js Version Best For SEO Friendly Performance Complexity Recommended
File-based Routing (app/) 13+ New projects, dynamic content Yes Excellent Low Yes
getStaticProps (pages/) 912 Static marketing sites Yes Excellent Medium Yes (legacy)
getStaticPaths + getStaticProps 912 Large static sites (blogs, products) Yes Excellent Medium Yes (legacy)
getServerSideProps 913 Personalized content, auth pages Yes Good Medium Yes (when needed)
Layouts (app/) 13+ Shared UI components Yes Excellent Low Yes
Metadata API 13+ SEO metadata management Yes Excellent Low Yes
i18n Routing 10+ Multi-language sites Yes Excellent Low Yes
Middleware 12+ Auth, redirects, edge logic Yes Excellent Medium Yes
next/image 10+ Image optimization Yes Excellent Low Yes
next/font 13+ Font optimization Yes Excellent Low Yes

Use this table as a decision matrix. Prioritize methods marked Yes under Recommended for new projects. For legacy codebases, migrate gradually to the app directory and modern APIs.

FAQs

Can I mix app/ and pages/ directories in the same project?

Yes, Next.js supports a hybrid mode where both directories coexist. This is useful for gradual migration from legacy code to the new app directory. However, avoid mixing routing logic between the twokeep them separate to prevent conflicts.

Do I need to use TypeScript with Next.js?

No, but its strongly recommended. TypeScript improves code quality, reduces bugs, and enhances developer experience. Next.js has first-class TypeScript support, and all modern methods in this guide work seamlessly with it.

How do I handle API calls in Server Components?

Use native fetch() directly inside Server Components. Next.js automatically optimizes and caches these calls. Avoid using libraries like Axiosstick with the built-in fetch for best performance and compatibility.

Is getServerSideProps slower than getStaticProps?

Yes. getServerSideProps runs on every request, so its slower than static generation. Use it only when content changes frequently or is user-specific. For most content, prefer static generation with ISR.

How do I test Next.js pages?

Use Jest or Vitest for unit testing components, and Cypress or Playwright for end-to-end testing. Next.js provides a testing utility library called @testing-library/react that works out of the box. Always test both server and client behavior.

Can I use external CSS libraries like Tailwind CSS?

Absolutely. Tailwind CSS is widely adopted in the Next.js ecosystem. Install it via npm, configure tailwind.config.js, and import it in your root layout. It works perfectly with Server Components and the app directory.

Whats the difference between ISR and SSR?

Incremental Static Regeneration (ISR) generates pages at build time and revalidates them lateroffering static performance with dynamic freshness. Server-Side Rendering (SSR) generates pages on every request. ISR is preferred unless real-time data is required.

How do I optimize for Core Web Vitals?

Use next/image, next/font, code splitting, and lazy loading. Avoid large third-party scripts. Monitor performance with Lighthouse and Next.jss built-in performance metrics in the DevTools.

Should I use dynamic imports for heavy components?

Yes. Use dynamic() to load heavy UI components (like charts or editors) only when needed. This reduces initial bundle size and improves load times.

What happens if I dont use proper metadata?

Your pages may not appear correctly in search results or social media shares. Missing titles, descriptions, or images can lead to low click-through rates and poor rankings. Always define metadata explicitly.

Conclusion

Creating pages in Next.js isnt just about writing React componentsits about building experiences that are fast, accessible, SEO-friendly, and maintainable. The ten methods outlined in this guide represent the most trusted, production-proven approaches available today.

For new projects, start with the app/ directory, Server Components, the Metadata API, and built-in optimizations like next/image and next/font. These are not just featurestheyre the foundation of modern web development.

For legacy projects, prioritize migration to the app directory, but dont rush. Use the hybrid mode to migrate page by page. Replace getServerSideProps with Server Components where possible, and migrate metadata to the new API.

Trust in these methods isnt based on popularityits based on results. Companies like Twitter, Uber, and Airbnb rely on these patterns to deliver millions of pages to users every day. They work because theyre designed by engineers who understand performance, scalability, and user experience.

Dont experiment with unverified patterns. Dont rely on outdated tutorials. Use the methods in this guide, and youll build pages that not only function correctly todaybut will continue to perform well for years to come.

Next.js evolves quickly, but the principles behind these trusted methods remain constant: render fast, fetch smart, structure clearly, and optimize relentlessly. Master these, and youll master Next.js.