askesis

Next.js essentials: 50 cards on the App Router and caching

Next.js App Router basics: server vs client components, layouts, route handlers, server actions, caching, metadata, dynamic routes and middleware.

Web developmentIntermediate50 cardsFree

Practice now

Study without an account

0 of 50 seen0 graduated
What is the App Router?

Scheduled with the default Askesis timings. Progress is saved in this browser.

All 50 cards

  1. 1
    What is the App Router?
    Next.js’s router in the app/ directory: folders map to URL segments, special files like page.tsx and layout.tsx define the UI, and components are React Server Components by default
    The older Pages Router (pages/) is still supported.
  2. 2
    Which file makes a folder a public route?
    page.tsx (or .js, .jsx, .ts); without one the folder isn’t routable, so other files can be colocated safely
  3. 3
    Which URL does app/blog/[slug]/page.tsx serve?
    /blog/:slug, e.g. /blog/hello-world with slug set to "hello-world"
  4. 4
    Read a dynamic route parameter in a page
    tsx
    // app/blog/[slug]/page.tsx
    export default async function Page({
      params,
    }: {
      params: Promise<{ slug: string }>
    }) {
      const { slug } = await params
      return <h1>{slug}</h1>
    }
    params became a Promise in Next.js 15, and Next.js 16 removed synchronous access.
  5. 5
    [...slug] vs [[...slug]]
    app/docs/[...slug] matches /docs/a/b (slug = ["a", "b"]) but not /docs; the optional [[...slug]] also matches /docs
  6. 6
    What is a folder named (marketing)?
    A route group: it organizes routes or gives them a shared layout without adding a segment to the URL
    Folders starting with an underscore, like _components, are private and never become routes.
  7. 7
    Are App Router components server or client components by default?
    Server Components, unless their module has 'use client' or is imported from a module that does
  8. 8
    What can Server Components do that Client Components can’t?
    Be async, read databases, files and secrets directly, and keep their code and dependencies out of the browser bundle
    In exchange, they can’t use state, effects, event handlers or browser APIs.
  9. 9
    When does a component need 'use client'?
    When it uses state or effects (useState, useEffect), event handlers like onClick, browser APIs like localStorage, or hooks built on them
  10. 10
    Where should 'use client' go?
    At the very top of the file, before imports. Everything that module imports becomes client code, so put it on small interactive leaf components, not whole pages
  11. 11
    Are Client Components rendered on the server?
    Yes. They are prerendered to HTML for the first load and then hydrated in the browser; 'use client' means the code also ships to the browser, not that it only runs there
  12. 12
    How can a Client Component display a Server Component?
    Pass the Server Component as children (or another prop) from a server parent; a client module can’t import a Server Component
    tsx
    // app/page.tsx (server)
    <Modal>
      <Cart /> {/* still a Server Component */}
    </Modal>
  13. 13
    What props can a Server Component pass to a Client Component?
    Only serializable values: strings, numbers, plain objects, arrays, Dates, Promises and the like; not functions or class instances, except Server Actions
  14. 14
    What does import 'server-only' do?
    Makes the build fail if client code imports that module, so secrets and server logic can’t leak into the browser bundle
  15. 15
    Which environment variables reach the browser?
    Only those prefixed with NEXT_PUBLIC_; they are inlined into the JavaScript at build time. All others stay on the server
  16. 16
    What does layout.tsx do?
    Wraps a segment and its children (through the children prop) with shared UI; it keeps its state and doesn’t re-render when navigating between those child pages
  17. 17
    What must the root layout contain?
    app/layout.tsx is required and must render the <html> and <body> tags
  18. 18
    template.tsx vs layout.tsx
    A template also wraps child routes, but it remounts on every navigation, so state resets and effects run again
  19. 19
    What does loading.tsx do?
    Wraps the segment’s page in a React Suspense boundary and shows instantly while the page’s content streams in
  20. 20
    What does error.tsx do, and what must it be?
    An error boundary for its segment that renders a fallback with a way to retry; it must be a Client Component ('use client')
    Errors thrown in the root layout need global-error.tsx.
  21. 21
    What does calling notFound() do?
    Stops rendering and shows the nearest not-found.tsx with a 404 status; it comes from next/navigation
  22. 22
    Write a route handler
    tsx
    // app/api/users/route.ts
    export async function GET() {
      const users = await db.user.findMany()
      return Response.json(users)
    }
    
    export async function POST(request: Request) {
      const data = await request.json()
      return Response.json(await db.user.create({ data }), { status: 201 })
    }
    Export one function per HTTP method.
  23. 23
    Can page.tsx and route.ts share a folder?
    No. A segment is either a page or an endpoint; put handlers under their own path, such as app/api/…
  24. 24
    Are GET route handlers cached by default?
    Not since Next.js 15 (they were in 14). Opt in with export const dynamic = 'force-static'
  25. 25
    Create a post with a Server Action
    tsx
    export default function NewPost() {
      async function create(formData: FormData) {
        'use server'
        await db.post.create({ data: { title: String(formData.get('title')) } })
        revalidatePath('/posts')
      }
      return (
        <form action={create}>
          <input name="title" />
          <button>Save</button>
        </form>
      )
    }
    The form works even before JavaScript loads; Server Actions are called with POST requests.
  26. 26
    Why must every Server Action check auth and validate input?
    Each action is exposed as a public POST endpoint that anyone can call directly, not only through your form
  27. 27
    Can you define a Server Action inside a Client Component?
    No. Put 'use server' at the top of a separate file and import the action from there, or receive it as a prop
  28. 28
    Is fetch cached by default in a Server Component?
    Not since Next.js 15. Opt in per request with { cache: 'force-cache' } or { next: { revalidate: 3600 } }
    Next.js 14 cached fetch by default, which surprised many people.
  29. 29
    What does export const revalidate = 3600 do in a page?
    Time-based revalidation (ISR): the page is served from cache and regenerated in the background once it’s older than an hour
    Per request: fetch(url, { next: { revalidate: 3600 } }).
  30. 30
    Refresh cached data right after a mutation
    Call revalidatePath('/posts'), or revalidateTag('posts', 'max') for data fetched with { next: { tags: ['posts'] } }
    The second cacheLife profile argument to revalidateTag is new in Next.js 16; in Server Actions, updateTag gives read-your-own-writes.
  31. 31
    What does the 'use cache' directive do?
    With Cache Components enabled (cacheComponents: true, Next.js 16), it marks a function, component or route as cacheable; cacheLife() sets how long and cacheTag() tags it
    tsx
    async function getPosts() {
      'use cache'
      cacheLife('hours')
      return db.post.findMany()
    }
  32. 32
    What is request memoization?
    Identical fetch GET requests (same URL and options) made during one server render run only once; wrap other data functions in React’s cache() for the same effect
  33. 33
    Static vs dynamic rendering
    Routes are prerendered at build time by default; they render per request when they read request data like cookies(), headers() or searchParams, or use uncached data
    With Cache Components, a route can mix both: a prerendered shell with dynamic parts streamed inside <Suspense>.
  34. 34
    Prerender every blog post at build time
    tsx
    // app/blog/[slug]/page.tsx
    export async function generateStaticParams() {
      const posts = await getPosts()
      return posts.map((post) => ({ slug: post.slug }))
    }
  35. 35
    Read a cookie in a Server Component
    tsx
    import { cookies } from 'next/headers'
    
    const theme = (await cookies()).get('theme')?.value
    cookies() and headers() are async since Next.js 15 and make the route dynamic. Setting cookies only works in Server Actions and route handlers.
  36. 36
    Read the query string ?page=2 in a page
    tsx
    export default async function Page({
      searchParams,
    }: {
      searchParams: Promise<{ page?: string }>
    }) {
      const { page = '1' } = await searchParams
    }
    Reading searchParams makes the page render per request.
  37. 37
    Set a page’s title and description
    tsx
    import type { Metadata } from 'next'
    
    export const metadata: Metadata = {
      title: 'Pricing',
      description: 'Plans for teams of every size',
    }
    Export it from a page or layout; metadata only works in Server Components.
  38. 38
    Generate metadata from fetched data
    tsx
    export async function generateMetadata({ params }: Props): Promise<Metadata> {
      const { slug } = await params
      const post = await getPost(slug)
      return { title: post.title }
    }
    Fetches shared with the page are deduplicated.
  39. 39
    What is the page title?
    tsx
    // app/layout.tsx
    title: { template: '%s | Acme', default: 'Acme' }
    
    // app/pricing/page.tsx
    title: 'Pricing'
    Pricing | Acme; pages without a title fall back to Acme
  40. 40
    Which special files generate metadata?
    favicon.ico, icon.png, opengraph-image.png (or .tsx), sitemap.ts and robots.ts in app/; Next.js adds the tags and routes
  41. 41
    Redirect logged-out users with middleware
    tsx
    // middleware.ts (proxy.ts in Next.js 16)
    import { NextResponse, type NextRequest } from 'next/server'
    
    export function middleware(request: NextRequest) {
      if (!request.cookies.has('session')) {
        return NextResponse.redirect(new URL('/login', request.url))
      }
    }
    
    export const config = { matcher: ['/dashboard/:path*'] }
    Middleware runs before the route; returning nothing lets the request continue.
  42. 42
    What happened to middleware.ts in Next.js 16?
    It was renamed to proxy.ts with an exported proxy function that runs on the Node.js runtime; middleware.ts still works for the Edge runtime but is deprecated
  43. 43
    Is middleware enough to protect private pages?
    No. Treat it as an optimistic check and verify auth again next to the data: in Server Components, Server Actions and route handlers
    CVE-2025-29927 (March 2025) let a crafted header skip middleware entirely on unpatched versions.
  44. 44
    What does <Link> from next/link add over <a>?
    Client-side navigation without a full page reload, and in production it prefetches routes as their links enter the viewport
  45. 45
    Where do you import useRouter from in the App Router?
    next/navigation, not next/router (that’s the Pages Router). usePathname and useSearchParams live there too; all are Client Component hooks
  46. 46
    What is special about redirect()?
    It throws a special error to stop rendering, so code after it never runs; call it outside try/catch blocks
    redirect from next/navigation works in Server Components, Server Actions and route handlers.
  47. 47
    Why might useSearchParams() break the production build?
    On a statically rendered route, the Client Component calling it must be inside a <Suspense> boundary; otherwise the build fails with a missing Suspense boundary error
  48. 48
    What does next/image do?
    <Image> resizes images on demand, serves modern formats like WebP (AVIF can be enabled), lazy-loads by default and reserves space to avoid layout shift
    Remote images need width and height (or fill) and an allowed host in images.remotePatterns.
  49. 49
    How do you stream a slow part of a page?
    Wrap the slow async component in <Suspense fallback={…}>: the rest of the page is sent at once and that part streams in when its data is ready
  50. 50
    What is a folder named @modal?
    A parallel route slot: its page renders alongside the main page and reaches the parent layout as a modal prop
    Combined with intercepting routes like (.)photo/[id], it powers modals that keep a shareable URL.

Frequently asked questions

Which Next.js version does this deck cover?

The App Router as of Next.js 15 and 16, with notes where they differ from Next.js 14, such as fetch caching defaults and async params.

Does it cover the Pages Router?

No. It focuses on the App Router, which is the recommended way to build new Next.js apps. getServerSideProps and other Pages Router APIs aren’t included.

Should I learn React first?

Yes. Next.js builds on React, so components, props, state and hooks should feel familiar. Our React deck covers those basics.

Is middleware still a thing in Next.js 16?

It was renamed to proxy and now runs on the Node.js runtime. The old middleware file still works for Edge use cases but is deprecated.