Skip to Content
React in a Week
Day 7 · Production with Next.js

Day 7 overview

Take your Reading List to production with Next.js, Server Components, Server Functions, an accessibility pass, and a real deploy.

For six days your React code has run in one place: the browser. That is a great way to learn, but real apps also need a server. Something has to store data, keep secrets out of the browser, send fast HTML on the first load, and put the app on the internet.

Today you hand those jobs to a framework. The React team recommends starting new apps with one, and the most widely used is Next.js. You will port the Reading List to the Next.js App Router, so some components run on the server and read data directly. A form will call a function that runs on the server. Then you will make sure everyone can use the app, deploy it to a public URL, and plan what to build next.

Next.js apps need a real server and a file system, so they can't run inside the in-page sandboxes. Today most code appears as static, highlighted files that you type into a project on your own computer. Where a concept is plain React (a Client Component, a form, an accessibility fix), you still get a live sandbox.

Time plan

LessonTimeWhat you'll do
Next.js and the App Router50 minCreate a Next.js app, learn file-based routing, layouts, links and dynamic routes
Server and Client Components60 minRead data on the server, decide where 'use client' goes, stream with Suspense
Server Functions50 minAdd books with 'use server', useActionState and revalidatePath
Data and caching40 minUnderstand static vs dynamic, try 'use cache', turn on the React Compiler
Accessibility50 minLabels, real buttons, alt text, focus, aria-live, and lint rules
Deploy to Vercel30 minBuild for production and ship it from GitHub or the CLI
What's next20 minRecap the week, pick a capstone, and choose what to read next

That is about five hours. If you run short on time, deploy first and do the accessibility pass afterwards. A deployed app you can share is a great motivator.

What you'll build today

By the end of today the Reading List will:

  • run as a Next.js app, with app/page.tsx as a Server Component that reads books from lib/books.ts;
  • have a detail page at /books/[id], built by app/books/[id]/page.tsx;
  • add books through a Server Function called addBook in app/actions.ts, called from a Client Component form;
  • refresh the list after each change with revalidatePath('/');
  • pass an accessibility review: labelled inputs, real buttons, visible focus, a skip link and announced status messages;
  • live at a public vercel.app URL.

Today's lessons

Project checkpoint · Day 7 · Reading List

Port the Reading List to Next.js

This is the full Day 7 version of the project. Each lesson builds one part of it and explains the decisions, so if something here looks new, that lesson is where it is explained. You can also come back to this section at the end of the day and check your files against it.

Create the project

Open a terminal in the folder where you keep your projects and run:

npx create-next-app@latest reading-list-next --yes
cd reading-list-next

The --yes flag accepts the recommended defaults: TypeScript, ESLint, Tailwind CSS, the App Router, and Cache Components. You need Node.js 20.9 or newer.

Turn on the React Compiler

You turned the compiler on for the Vite app on Day 6. Next.js has a built-in switch for it, but it needs the Babel plugin installed:

npm install -D babel-plugin-react-compiler

Then edit next.config.ts to match the file in the tabs below.

Add the files

Create or replace each file in the tabs below. Delete anything else the starter put in app/page.tsx, and replace the whole of app/globals.css, including the Tailwind import, with the version here. Create the lib and components folders at the project root, next to app.

Run it

npm run dev

Open http://localhost:3000. Add a book, change a status, open a book's detail page, then press Tab from the top of the page and check that you can reach and use everything with the keyboard.

lib/types.ts
export type Status = 'want' | 'reading' | 'done';

export interface Book {
  id: string;
  title: string;
  author: string;
  status: Status;
  rating?: number;
}

export const statusLabels: Record<Status, string> = {
  want: 'Want to read',
  reading: 'Reading',
  done: 'Done',
};

// What the addBook Server Function sends back to the form.
export type FormState = {
  error: string | null;
  message: string | null;
};

When everything works, commit the project to GitHub and follow the Deploy to Vercel lesson to put it online.

Day 7 progress

0/8

On this page