Next.js
100 challenges · 0 mastered
Next.js is a React framework built on top of React that adds features like server-side rendering, static site generation, file-based routing, API routes, and built-in optimizations for images, fonts, and scripts.
React is the engine; Next.js is the whole car built around that engine so you can actually drive somewhere without assembling the rest yourself.
Plain React is a client-side library that renders entirely in the browser, while Next.js adds server rendering, routing, data fetching conventions, and production optimizations out of the box. Next.js can render on the server or at build time, improving SEO and performance.
Plain React is a bag of LEGO bricks. Next.js is a LEGO kit with instructions, extra tools, and a baseplate already set up.
Key features include file-based routing, multiple rendering strategies (SSR, SSG, ISR), Server Components, Server Actions, API routes/route handlers, automatic code splitting, and built-in image, font, and script optimization.
It's a Swiss Army knife for web apps: routing, rendering, data, and optimization tools all folded into one handle.
You use the create-next-app CLI, which scaffolds a project with sensible defaults and prompts you for options like TypeScript, ESLint, Tailwind, and the App Router.
npx create-next-app@latest my-app
cd my-app
npm run devIt's like ordering a furnished apartment instead of an empty room; everything is already set up when you walk in.
The Pages Router (in the pages/ directory) is the older system using getServerSideProps/getStaticProps and client components by default. The App Router (in the app/ directory, stable since Next 13.4) uses React Server Components, nested layouts, and Server Actions as the modern default.
Pages Router is the old neighborhood map; App Router is the new GPS with live traffic and smarter routing.
Yes, Next.js has built-in TypeScript support; create-next-app can scaffold a TypeScript project and Next.js auto-generates a tsconfig and type definitions. You just rename files to .ts/.tsx and Next.js handles the rest.
npx create-next-app@latest --typescript
// pages and components use .tsx filesIt's like a car that already speaks your language; you don't have to install a translator before driving.
Routes are derived from the file system. In the Pages Router, files in pages/ map to URLs; in the App Router, folders under app/ define routes and a page.js/page.tsx file makes a route publicly accessible.
// App Router
app/page.tsx -> /
app/about/page.tsx -> /about
app/blog/page.tsx -> /blogYour folders are like rooms in a house, and the URL is just the path you walk to reach each room.
You wrap a folder or file name in square brackets. In the App Router, app/blog/[slug]/page.tsx matches /blog/anything and the segment value is passed in as a param.
// app/blog/[slug]/page.tsx
export default function Post({ params }) {
return <h1>Post: {params.slug}</h1>;
}It's a fill-in-the-blank address: /blog/____ where the blank can be any word.
A catch-all route uses [...slug] to match multiple path segments, and an optional catch-all uses [[...slug]] to also match the base path. It is useful for docs or CMS-driven nested paths.
// app/docs/[...slug]/page.tsx
// matches /docs/a, /docs/a/b, /docs/a/b/c
export default function Docs({ params }) {
return <div>{params.slug.join('/')}</div>;
}It's like a mail forwarding rule that catches anything addressed to the whole building, no matter how many floors deep.
page.tsx (or page.js) defines the unique UI for a route segment and makes that segment publicly routable. Without a page file, a folder is just a route segment with no public URL.
// app/dashboard/page.tsx
export default function Dashboard() {
return <h1>Dashboard</h1>;
}A folder is a room, but page.tsx is the door that lets visitors actually enter it.
A layout.tsx file wraps its route segment and all children, preserving shared UI like headers or sidebars across navigations without re-rendering. The root layout is required and must include html and body tags.
// app/layout.tsx
export default function RootLayout({ children }) {
return (
<html><body>
<nav>Menu</nav>
{children}
</body></html>
);
}A layout is the picture frame that stays put while you swap out the photo (the page) inside it.
Route groups wrap a folder name in parentheses like (marketing). They organize routes and let you apply different layouts without affecting the URL path, since the group name is omitted from the URL.
// app/(marketing)/about/page.tsx -> /about
// app/(shop)/cart/page.tsx -> /cart
// the (marketing) and (shop) names are invisible in the URLIt's like sorting papers into labeled binders for your own organization, but the labels never show up on the printed page.
Nested folders create nested URL segments, and each level can have its own layout. Layouts compose from the root down, so deeper pages inherit all parent layouts.
// app/dashboard/layout.tsx wraps
// app/dashboard/settings/page.tsx -> /dashboard/settingsLike Russian nesting dolls: each folder sits inside the previous one, and outer shells wrap every doll inside.
You use the built-in Link component from next/link for client-side navigation, which prefetches and avoids full page reloads. For programmatic navigation you use the useRouter hook.
import Link from 'next/link';
export default function Nav() {
return <Link href="/about">About</Link>;
}Link is like a teleport pad inside the app; you jump rooms without re-entering the whole building.
Link enables client-side navigation and automatic prefetching of the destination, so transitions are fast and don't reload the entire page. A plain anchor triggers a full server round-trip and reloads all assets.
<Link href="/about">About</Link>
// vs full reload:
<a href="/about">About</a>Link is an internal elevator; a plain link is walking out the front door and back in through reception.
Prefetching is when Next.js loads the code and data for a linked route in the background before the user clicks, making navigation feel instant. Links in the viewport are prefetched automatically in production.
It's like a waiter starting to prepare your likely next dish before you've even finished ordering it.
You import useRouter from next/navigation (not next/router) and call methods like push, replace, back, and refresh. This hook only works in Client Components.
'use client';
import { useRouter } from 'next/navigation';
export default function Btn() {
const router = useRouter();
return <button onClick={() => router.push('/home')}>Go</button>;
}It's a remote control that lets your code change the channel instead of waiting for a click.
Dynamic segment params are passed to Server Components via the params prop, and query strings come from the searchParams prop in pages or the useSearchParams hook in Client Components.
// Server Component
export default function Page({ params, searchParams }) {
return <p>{params.id} {searchParams.tab}</p>;
}params is the room number on the door; searchParams are the extra sticky notes attached to your request.
not-found.tsx defines custom UI shown when a route segment cannot be found or when notFound() is called in code. It replaces the default 404 page for that segment.
// app/not-found.tsx
export default function NotFound() {
return <h1>404 - Page not found</h1>;
}It's the friendly 'oops, wrong door' sign instead of a blank brick wall when a page doesn't exist.
Static files go in the public/ folder at the project root and are served from the base URL. A file at public/logo.png is available at /logo.png.
// public/logo.png
<img src="/logo.png" alt="Logo" />public/ is the lobby display case; anything you put there is visible to everyone at the front address.
You import a global stylesheet once in the root layout (App Router) or _app.js (Pages Router). Global CSS can only be imported from those entry points.
// app/layout.tsx
import './globals.css';Global CSS is the house paint applied to every room; you choose it once at the main entrance.
CSS Modules are stylesheets named *.module.css that scope class names locally to the component that imports them, preventing naming collisions. Next.js supports them out of the box.
// styles.module.css -> .title { color: blue; }
import styles from './styles.module.css';
<h1 className={styles.title}>Hi</h1>Each component gets its own labeled toolbox so its 'hammer' never gets confused with another component's hammer.
You can enable Tailwind during create-next-app or install it manually, configure tailwind.config, and import its directives in your global CSS. Then you apply utility classes directly in JSX.
// globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
// usage
<div className="p-4 text-blue-500">Hi</div>Tailwind is a box of pre-cut stickers; instead of mixing paint you just slap on labeled utility stickers.
Yes, Next.js has built-in Sass support; you just install the sass package and rename files to .scss or .sass. You can use both global SCSS and SCSS modules.
npm install --save-dev sass
// styles.module.scss
.box { .title { color: red; } }It's the same painting job but with fancier brushes that let you nest and reuse strokes more easily.
You build the className string dynamically using template literals or a helper like clsx/classnames, toggling classes based on state or props. This works the same in Next.js as in React.
<button className={isActive ? 'btn active' : 'btn'}>
Click
</button>It's like choosing which jacket to wear based on the weather; the rule picks the right one automatically.
