AlgoInsight

Q&A

How to implement routing in Next.js

By AlgoInsight Team2026-06-07nextjsreact-hooksjavascript

Overview

Unlike React Router where you declare routes in code, Next.js derives routes from your folder structure - the file system is the route table. There are two systems: the newer App Router (app/, with React Server Components, layouts, and richer conventions) and the legacy Pages Router (pages/). New projects should use the App Router.

graph TD
    A[File-system routing] --> B["App Router: app/ (modern)"]
    A --> C["Pages Router: pages/ (legacy)"]
    B --> B1["folder/page.tsx → /folder"]
    B --> B2["[id]/page.tsx → dynamic /folder/:id"]
    B --> B3[layout.tsx → shared nested layouts]
    C --> C1["pages/about.tsx → /about"]
    style B fill:#1e1b4b,color:#fff

App Router (Next 13+, recommended)

A folder becomes a route segment; a page.tsx inside it makes that segment a navigable page:

app/
  page.tsx            → /
  about/page.tsx      → /about
  blog/
    page.tsx          → /blog
    [slug]/page.tsx   → /blog/:slug   (dynamic)
  dashboard/
    layout.tsx        → shared layout for everything under /dashboard
    page.tsx          → /dashboard
    settings/page.tsx → /dashboard/settings

Dynamic segments

Brackets capture URL parameters:

// app/blog/[slug]/page.tsx
export default function Post({ params }: { params: { slug: string } }) {
  return <h1>Post: {params.slug}</h1>;
}

Variants: [...slug] (catch-all), [[...slug]] (optional catch-all).

Layouts (nested, persistent)

layout.tsx wraps all pages in its segment and below, persisting across navigation:

// app/dashboard/layout.tsx
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
  return <div><nav>Dashboard nav</nav><main>{children}</main></div>;
}

Special files include loading.tsx (Suspense fallback), error.tsx (error boundary), and not-found.tsx.

Pages Router (legacy)

Each file under pages/ is a route:

pages/
  index.tsx        → /
  about.tsx        → /about
  blog/[slug].tsx  → /blog/:slug
// pages/blog/[slug].tsx
import { useRouter } from "next/router";
export default function Post() {
  const { slug } = useRouter().query;     // dynamic param
  return <h1>{slug}</h1>;
}

Navigation

<Link> (client-side, prefetched)

import Link from "next/link";
<Link href="/about">About</Link>
<Link href={`/blog/${slug}`}>Read post</Link>

<Link> does client-side transitions (no full reload) and prefetches in the background for speed.

Programmatic navigation

// App Router
import { useRouter } from "next/navigation";
const router = useRouter();
router.push("/dashboard");
router.back();

// Pages Router
import { useRouter } from "next/router";   // note: different import path

A common gotcha: the App Router imports useRouter from next/navigation, the Pages Router from next/router - they're different.

Reading Route Info (App Router)

import { usePathname, useSearchParams, useParams } from "next/navigation";
const pathname = usePathname();        // "/blog/hello"
const query = useSearchParams();        // ?key=value
const params = useParams();             // { slug: "hello" }

Why This Matters in Interviews

Next.js interviews center on routing. Key points: routing is file-system based (folders/files define routes, no manual config); the App Router uses page.tsx per segment, [param] for dynamic routes, and layout.tsx for nested persistent layouts (plus loading/error/not-found); navigate with <Link> (prefetched client transitions) or useRouter().push. The biggest practical gotcha to mention: App Router vs Pages Router differences, especially useRouter coming from next/navigation vs next/router.

Common Pitfalls

References

More answers