The whole course in one tree
Here is 'Microblog', a complete mini-app using every unit you finished:
app/ ├── layout.js ← root shell, next/font, global CSS (U2, U8) ├── page.js ← static landing page (U7) ├── blog/ │ ├── layout.js ← blog section shell (U2) │ ├── page.js ← async list, revalidate: 60 → ISR (U4, U7) │ ├── loading.js ← instant skeleton (U4) │ ├── error.js ← failure boundary (U4) │ └── [slug]/ │ └── page.js ← await params, generateStaticParams, │ generateMetadata, notFound() (U5, U7) ├── search/ │ └── page.js ← await searchParams (?q=), dynamic (U5, U7) ├── new/ │ └── page.js ← form → createPost server action (U6) ├── actions.js ← "use server": insert + revalidatePath (U6) ├── api/ │ └── posts/route.js ← public JSON API (U6) └── like-button.js ← "use client" leaf on post pages (U3)
Read it folder by folder and name the unit that taught each line. If any annotation feels foggy, that is your signal to revisit that unit before building your own.
Two requests, traced
A reader opens /blog/hello-world. The page was prerendered (its slug came from generateStaticParams), so the server returns finished HTML instantly, with real <title> metadata for SEO. The only JavaScript shipped is the like-button.js island — the pattern name for a small interactive client component embedded in otherwise-static HTML — which hydrates and starts counting clicks.
An author publishes from /new. The form's action is the createPost server action: form data travels to the server, the post is inserted, and revalidatePath("/blog") invalidates the cached list, so the next visit to /blog shows the new post. Meanwhile the mobile app fetches GET /api/posts from the route handler, the public door.
Every arrow in those two paragraphs is something you can now build.
Quiz
In Microblog, why does the reader's browser download JavaScript for like-button.js but not for the post page itself?
Code exercise · javascript
Final logic exercise: rebuild the route table that next build prints. Write routeTable(files): keep only page.js files, convert each path to its URL (like your Unit 2 routeFromPath, the homepage is "/"), and return the URLs sorted alphabetically. Note that layout.js and route.js files must not appear.
Problem
Your turn to ship. You extend Microblog with an author dashboard at /dashboard that greets the signed-in user via a session cookie. Per Unit 7, will next build mark this route static or dynamic?