0Pricing
TypeScript Academy · Lesson

App Router types; server vs client components

Understand the App Router defaults (server components), when to opt into client components, and how to type route handlers.

App Router types; server vs client components is a free TypeScript Academy lesson on CoddyKit — lesson 1 of 3. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 3 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Intro

Goal: Use App Router with TypeScript confidently. You will see server components (default), opt into client components when needed, and type route handlers for API endpoints.

  • Server vs client capabilities
  • Passing typed props between them
  • Typed NextRequest/NextResponse

Server component

Files under app/ are server components by default. You can run server-only code and fetch data before render.

// app/page.tsx (server component by default)
export default async function Page() {
  // Server code: read env, fetch data, call DB (conceptually)
  const data: { message: string } = { message: "Hello from server component" }
  return (
    <main style={{ display: "grid", gap: 8 }}>
      <h1>Home</h1>
      <p>{data.message}</p>
    </main>
  )
}

Client component

Add the directive "use client" at the top to enable hooks and event handlers. Client components run in the browser.

"use client"

import { useState } from "react"

// app/components/Counter.tsx (client component)
export default function Counter() {
  const [n, setN] = useState(0)
  return (
    <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
      <button onClick={() => setN(n - 1)}>-</button>
      <span>{n}</span>
      <button onClick={() => setN(n + 1)}>+</button>
    </div>
  )
}

Server → client props

Compute data on the server and pass it as typed props to client components. Keep server-only logic off the client.

// app/page.tsx (server) + client import
import Counter from "./components/Counter"

export default async function Page() {
  const initial = 5 // fetched or computed on the server
  return (
    <main style={{ display: "grid", gap: 12 }}>
      <h2>Dashboard</h2>
      <CounterWithStart start={initial} />
    </main>
  )
}

// app/components/CounterWithStart.tsx
"use client"
import { useState } from "react"

export default function CounterWithStart({ start }: { start: number }) {
  const [n, setN] = useState(start)
  return (
    <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
      <button onClick={() => setN(n - 1)}>-</button>
      <span>{n}</span>
      <button onClick={() => setN(n + 1)}>+</button>
    </div>
  )
}

Route handlers

Use NextRequest/NextResponse for typed handlers under app/api/*/route.ts. Return JSON with status codes.

// app/api/hello/route.ts (App Router API)
import { NextRequest, NextResponse } from "next/server"

export async function GET(req: NextRequest) {
  const name = req.nextUrl.searchParams.get("name") ?? "world"
  const body: { message: string } = { message: `Hello, ${name}!` }
  return NextResponse.json(body, { status: 200 })
}

export async function POST(req: NextRequest) {
  const payload = (await req.json()) as { name?: string }
  const body = { created: true, name: payload.name ?? "anon" }
  return NextResponse.json(body, { status: 201 })
}

Tips

Tips:

  • Default to server components; opt into client only when you need interactivity.
  • Keep props small and serializable between server and client.
  • Use typed NextResponse.json shapes consistently.

App Router client check

Quick check: How do you enable hooks in a component file under App Router?

Recap

Recap: App Router defaults to server components; add "use client" for interactivity, pass typed props across the boundary, and type route handlers with NextRequest/NextResponse.

Frequently asked questions

Is the “App Router types; server vs client components” lesson free?

Yes — the full text of “App Router types; server vs client components” is free to read here on the web, and the TypeScript Academy course includes 3 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “App Router types; server vs client components”?

Understand the App Router defaults (server components), when to opt into client components, and how to type route handlers. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start TypeScript Academy?

No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 3, so you can start here or from the beginning and move at your own pace.

How long does the “App Router types; server vs client components” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this TypeScript Academy lesson?

Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. App Router types; server vs client components
  2. Data fetching & action typing
  3. Env typing and config
← Back to TypeScript Academy