Getting Started with Next.js · Lesson 3 of 24
Next.js Routing: Pages and Links
Next.js uses file-system routing: the folder structure inside app/ is your URL structure. There's no route configuration to write – create a folder with a page.tsx in it and the URL exists. Links between pages use the <Link> component, which navigates without a full page reload and prefetches pages before you click.
In this lesson
- Folders,
page.tsxand nested routes - Linking with
next/link - Highlighting the active link
- Route groups and private folders
Folders are routes
| File | URL |
|---|---|
app/page.tsx | / |
app/about/page.tsx | /about |
app/courses/page.tsx | /courses |
app/courses/react/page.tsx | /courses/react |
app/courses/components/Card.tsx | no URL – no page file |
Pages and links
// app/layout.tsx
import Link from "next/link";
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<nav>
<Link href="/">Home</Link> · <Link href="/courses">Courses</Link> · <Link href="/about">About</Link>
</nav>
{children}
</body>
</html>
);
}
// app/page.tsx
export default function Home() {
return <h1>Learn to code for free</h1>;
}
// app/courses/page.tsx
import Link from "next/link";
export default function Courses() {
return (
<main>
<h1>All courses</h1>
<Link href="/courses/react">React.js →</Link>
</main>
);
}
// app/courses/react/page.tsx
export default function ReactCourse() {
return <h1>React.js – 31 lessons</h1>;
}
// app/about/page.tsx
export default function About() {
return <h1>About LearnFrenzy</h1>;
}
URL: / Home · Courses · About Learn to code for free › click “Courses” URL: /courses Home · Courses · About All courses React.js → › click “React.js →” URL: /courses/react Home · Courses · About React.js – 31 lessons › click “About” URL: /about Home · Courses · About About LearnFrenzy › browser back URL: /courses/react Home · Courses · About React.js – 31 lessons
<Link> renders a normal <a> tag, so the links work without JavaScript and are crawlable by search engines. Once the app has loaded, clicks are handled on the client: Next.js fetches only the new page's content, keeps the layout as it is, and updates the URL. Links visible on screen are prefetched in the background, so navigation usually feels instant.
Highlighting the active link
To know the current URL, use the usePathname hook. Hooks run in the browser, so this small component is a Client Component – marked with "use client" at the top of the file (covered in detail later in the course):
// app/nav-link.tsx
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
export function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
const pathname = usePathname();
const active = href === "/" ? pathname === "/" : pathname.startsWith(href);
return (
<Link href={href} aria-current={active ? "page" : undefined} className={active ? "font-bold underline" : ""}>
{active ? "▸ " : ""}{children}
</Link>
);
}
// app/layout.tsx
import { NavLink } from "./nav-link";
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<nav>
<NavLink href="/">Home</NavLink> · <NavLink href="/courses">Courses</NavLink>
</nav>
{children}
</body>
</html>
);
}
// app/page.tsx
export default function Home() {
return <h1>Home</h1>;
}
// app/courses/page.tsx
export default function Courses() {
return <h1>Courses</h1>;
}
URL: / ▸ Home · Courses Home › click “Courses” URL: /courses Home · ▸ Courses Courses
Route groups and private folders
| Folder name | Effect | Example |
|---|---|---|
(marketing) | route group: organises files, not part of the URL | app/(marketing)/pricing/page.tsx → /pricing |
_components | private folder: never a route | app/_components/Button.tsx |
[slug] | dynamic segment (next chapter) | app/courses/[slug]/page.tsx → /courses/anything |
Route groups are handy for giving different sections different layouts – for example (marketing) with a big footer and (dashboard) with a sidebar – without changing any URLs.
Use Link for internal pages
A plain <a href="/courses"> works, but it reloads the whole page and loses client state and prefetching. Use <Link> for pages in your app, and <a> for external sites and file downloads.
Practice
Try it yourself
Create a
/contactpage inside a(marketing)route group, and link to it from the home page.Show solution
// app/(marketing)/contact/page.tsx export default function Contact() { return <h1>Contact: hello@learnfrenzy.com</h1>; }// app/page.tsx import Link from "next/link"; export default function Home() { return <Link href="/contact">Contact us</Link>; }URL: / Contact us › click “Contact us” URL: /contact Contact: hello@learnfrenzy.com
Quick check
Which file makes /blog a page?
app/blog/page.tsx.
Does (shop) appear in the URL?
No – parentheses make a route group that only organises files.
Why is a component using usePathname marked "use client"?
Hooks like usePathname run in the browser, so the component must be a Client Component.
Summary
- Folders inside app/ are URL segments; a page.tsx makes the segment a page.
- next/link renders real anchor tags, navigates on the client and prefetches.
- Route groups (name) organise without changing URLs; _private folders never become routes.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.