Loading
A practical walkthrough of the app directory, server components, and routing changes in Next.js 13.
Next.js 13 changed a lot about how you structure and think about a React app. The app directory, server components, and new routing conventions are the big ones. Here's a breakdown of what actually matters and how to use it.
Next.js 13 ships with an app/ directory that sits alongside the old pages/ directory. You don't have to migrate everything at once — they coexist. But the new structure gives you layouts, nested routing, and server components out of the box.
app / layout.js;
page.js;
about / page.js;
blog / [slug] / page.js;
page.js;
The app directory uses React Server Components by default, offering several advantages:
Layouts in the app directory allow you to share UI between multiple pages. Here's how to create a basic layout:
// app/layout.js
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<header>
<nav>{/* Your navigation components */}</nav>
</header>
<main>{children}</main>
<footer>{/* Your footer components */}</footer>
</body>
</html>
);
}
Server Components represent a fundamental shift in how we build React applications. They execute on the server, reducing the JavaScript bundle sent to the client.
Server Components are ideal for:
Here's an example of a Server Component fetching data:
// app/posts/page.js
async function getPosts() {
const res = await fetch("https://api.example.com/posts");
return res.json();
}
export default async function Posts() {
const posts = await getPosts();
return (
<div>
<h1>Blog Posts</h1>
<div className="grid">
{posts.map((post) => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
</div>
);
}
Next.js 13 introduces a more intuitive routing system with built-in loading and error states.
Create loading UI that shows while content loads:
// app/posts/loading.js
export default function Loading() {
return (
<div className="loading-spinner">
<div className="spinner"></div>
<p>Loading posts...</p>
</div>
);
}
Implement error boundaries at the page level:
// app/posts/error.js
"use client";
export default function Error({ error, reset }) {
return (
<div className="error-container">
<h2>Something went wrong!</h2>
<p>{error.message}</p>
<button onClick={() => reset()}>Try again</button>
</div>
);
}
Next.js 13 provides powerful data fetching capabilities with built-in caching:
async function getData() {
const res = await fetch("https://api.example.com/data", {
next: {
revalidate: 3600, // Revalidate every hour
},
});
if (!res.ok) {
throw new Error("Failed to fetch data");
}
return res.json();
}
While Server Components are the default, you can still use Client Components when necessary:
"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>
);
}
Embrace Server Components Use Server Components by default and only switch to Client Components when necessary (for interactivity or browser APIs).
Optimize Images Use the built-in Next.js Image component for automatic optimization:
import Image from "next/image";
export default function Profile() {
return (
<Image
src="/public/assets/resume.png"
alt="Profile picture"
width={300}
height={300}
priority
/>
);
}
Implement Progressive Enhancement Build your application to work without JavaScript first, then enhance with client-side features.
Use Metadata API Implement dynamic metadata for better SEO:
export async function generateMetadata({ params }) {
return {
title: "Your Dynamic Title",
description: "Your Dynamic Description",
openGraph: {
images: ["/some-image.jpg"],
},
};
}
Next.js 13 is a solid step forward if you're already in the React ecosystem. Server components alone save you a ton of unnecessary client-side JS, and the app directory makes project structure way more intuitive once you get used to it.
The short version:
"use client" only when you need interactivity or browser APIsIf you're starting a new project, there's not much reason to stick with the pages directory anymore.
Software Developer & Tech Enthusiast