PART 4: LAYOUTS – SHARING UI ACROSS PAGES
What is a Layout?
A layout is a shared template that wraps multiple pages. Think of it like a frame that stays the same while the content inside changes.
Real-world example: YouTube
When you’re on YouTube:
- The header (search bar, profile, notifications) is always there
- The sidebar is always there
- Only the main content changes when you navigate
That header and sidebar are a layout!
How Layouts Work
In your app/layout.js file, you have:
export const metadata = {
title: "My App",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
</body>
</html>
);
}
Let’s break this down:
export const metadata – This defines the page title and description. Important for SEO.
export default function RootLayout({ children }) – This is the main layout component. Every page gets wrapped inside this.
{children} – This is where the page content goes. It’s a special React prop that means “put the page component here”.
The flow is:
- User visits
/about - Next.js finds
app/about/page.js - It wraps it inside
RootLayout - The layout becomes:
<html>
<body>
<!-- about page content goes here -->
</body>
</html>
Adding Navigation to Your Layout
Let’s add a navigation bar that appears on every page:
export const metadata = {
title: "My App",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<nav style={{ backgroundColor: '#333', padding: '20px' }}>
<h1 style={{ color: 'white', margin: 0 }}>My Website</h1>
</nav>
{children}
</body>
</html>
);
}
Now every page will have this navigation bar at the top. Try visiting different pages—the nav stays!
Adding a Navigation Menu
Let’s make the navigation interactive:
import Link from 'next/link';
export const metadata = {
title: "My App",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<nav style={{ backgroundColor: '#333', padding: '20px' }}>
<div style={{ display: 'flex', gap: '20px' }}>
<Link href="/" style={{ color: 'white', textDecoration: 'none' }}>
Home
</Link>
<Link href="/about" style={{ color: 'white', textDecoration: 'none' }}>
About
</Link>
<Link href="/contact" style={{ color: 'white', textDecoration: 'none' }}>
Contact
</Link>
</div>
</nav>
{children}
</body>
</html>
);
}
Wait, you might be confused about the Link component. Let’s explain it next.
PART 5: NAVIGATION WITH LINKS
What is the Link Component?
The Link component is how you navigate between pages in Next.js. It’s special because it:
- Prefetches the page (loads it before you click)
- Doesn’t reload the whole page (instant navigation)
- Updates the URL without a full page refresh
In regular HTML, you’d use <a> tags:
<a href="/about">About</a>
But in Next.js, you use Link:
import Link from 'next/link';
export default function Home() {
return (
<Link href="/about">About</Link>
);
}
Why Link is Better Than <a>
Let’s say someone clicks an <a> tag:
<a href="/about">About</a>
What happens:
- Browser makes a new request to the server
- Server sends the entire HTML page
- Browser reloads everything
- It’s slow and resets your state
With Link:
<Link href="/about">About</Link>
What happens:
- JavaScript intercepts the click
- Next.js loads only the new page content
- URL updates but no full page refresh
- It’s fast and smooth
In a real app like YouTube, if navigation had a full page reload every time you clicked, it would feel slow and sluggish. That’s why Link exists.
Comparing to Regular Links
Let me show the difference:
// ❌ Don't do this in Next.js
<a href="/about">About</a>
// ✅ Do this in Next.js
import Link from 'next/link';
<Link href="/about">About</Link>
// ✅ You can still use <a> for external links
<a href="https://google.com">Google</a>
External links (going to other websites) should use <a> tags because they need a full page reload.
Dynamic Links
You can create links dynamically. For example, in a blog listing all posts:
import Link from 'next/link';
export default function BlogList() {
const posts = [
{ id: 1, title: "Learning React" },
{ id: 2, title: "Next.js Guide" },
{ id: 3, title: "Web Development Tips" }
];
return (
<main>
<h1>Blog Posts</h1>
<ul>
{posts.map(post => (
<li key={post.id}>
<Link href={`/blog/${post.id}`}>
{post.title}
</Link>
</li>
))}
</ul>
</main>
);
}
Notice the template literal: href={`/blog/${post.id}`}
This creates links like:
/blog/1/blog/2/blog/3
Real-World Example: Netflix Navigation
Netflix has movies and shows. Each one has its own page:
/movie/123/show/456/movie/789
They could render them like:
import Link from 'next/link';
export default function Movies() {
const movies = [
{ id: 123, title: "Stranger Things" },
{ id: 456, title: "The Crown" },
];
return (
<div>
{movies.map(movie => (
<Link key={movie.id} href={`/movie/${movie.id}`}>
{movie.title}
</Link>
))}
</div>
);
}
When you click a movie, it navigates to /movie/123 instantly without reloading the page.
Common Beginner Mistake #3: Forgetting to Import Link
New developers often try to use Link without importing it:
// ❌ This will error
export default function Home() {
return <Link href="/about">About</Link>;
}
// ✅ Always import first
import Link from 'next/link';
export default function Home() {
return <Link href="/about">About</Link>;
}
Next.js will give you an error: “Link is not defined”.
Understanding Prefetching
This is cool: Next.js automatically prefetches links when it thinks you might click them.
When you have:
<Link href="/about">About</Link>
Next.js detects this link and automatically loads the /about page in the background. If the user clicks, it’s already loaded and appears instantly!
You can control prefetching:
// Prefetch enabled (default)
<Link href="/about">About</Link>
// Disable prefetching
<Link href="/about" prefetch={false}>About</Link>
Most of the time, leave prefetching enabled. It makes your app feel faster.
Exercise 2: Build a Navigation Menu
Create a website with these pages:
- Home (
/) - Services (
/services) - About (
/about) - Blog (
/blog) - Contact (
/contact)
Add a navigation menu in the layout that links to all pages using the Link component.
PART 6: STATIC ASSETS (IMAGES, FONTS, ETC.)
What are Static Assets?
Static assets are files that don’t change:
- Images
- Fonts
- Videos
- PDFs
- Icons
These live in the public/ folder. Everything in public/ is served as-is to users.
Using Images from the Public Folder
You can put images in public/ and use them:
Create public/my-image.jpg (upload your image)
Then use it in a page:
export default function Home() {
return (
<div>
<h1>Welcome</h1>
<img src="/my-image.jpg" alt="My image" />
</div>
);
}
Notice the src starts with /. This means “look in the public folder”.
The Image Component (Better Than img)
Next.js has a special Image component that’s better than regular <img>:
import Image from 'next/image';
export default function Home() {
return (
<div>
<h1>Welcome</h1>
<Image
src="/my-image.jpg"
alt="My image"
width={800}
height={600}
/>
</div>
);
}
The Image component:
- Optimizes automatically – Converts images to modern formats
- Lazy loads – Only loads images when visible
- Responsive – Works on all screen sizes
- Prevents layout shift – You specify width/height so space is reserved
This makes your website faster. Especially important for websites like YouTube that load many images.
When to Use Image vs img
Use Image for:
- Regular images on your website
- Images you control (yours or from your server)
Use <img> for:
- External images (from other websites)
- When you don’t know the width/height
Using Google Fonts
You can use Google Fonts in Next.js. First, import from next/font/google:
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'] });
export const metadata = {
title: "My App",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
</html>
);
}
This applies the Inter font to your entire website. You can choose from thousands of fonts on Google Fonts.
Directory Structure Best Practices
Organize your public folder like this:
public/
├── images/
│ ├── logo.png
│ ├── hero.jpg
│ └── icons/
│ ├── home.svg
│ └── menu.svg
├── fonts/
└── videos/
Then reference them:
<Image src="/images/logo.png" alt="Logo" width={100} height={100} />
<Image src="/images/icons/home.svg" alt="Home" width={24} height={24} />
SVG Images
SVGs are special images that are infinitely scalable. Use them for logos and icons:
<Image src="/images/icons/home.svg" alt="Home" width={24} height={24} />
Or as a React component:
import HomeSvg from '@/public/images/icons/home.svg';
export default function Header() {
return <HomeSvg width={24} height={24} />;
}
Common Beginner Mistake #4: Wrong Image Paths
New developers often do this:
// ❌ Wrong - looking in the wrong place
<img src="./my-image.jpg" alt="image" />
// ✅ Correct - looks in public/
<img src="/my-image.jpg" alt="image" />
Remember: Static assets in Next.js always start with / and come from the public/ folder.
Real-World Example: E-commerce Website
An e-commerce site like Amazon has:
- Product images
- Logo
- Icons for categories
- Banner images
Structure:
public/
├── images/
│ ├── logo.png
│ ├── products/
│ │ ├── phone-123.jpg
│ │ ├── laptop-456.jpg
│ │ └── shoes-789.jpg
│ ├── categories/
│ │ ├── electronics.svg
│ │ └── clothing.svg
│ └── banners/
│ └── summer-sale.jpg
Then in a product page:
import Image from 'next/image';
export default function ProductPage() {
return (
<div>
<Image
src="/images/products/phone-123.jpg"
alt="Phone"
width={500}
height={500}
/>
<h1>Amazing Phone</h1>
<p>Price: $999</p>
</div>
);
}
Exercise 3: Add Images to Your Website
- Create images in the public folder
- Use the
Imagecomponent to display them - Import a Google Font and use it in your layout
- Organize your public folder properly