Stage 1: Getting Started

Getting Started · Lesson 05

Build a Real Web App with React + Next.js

Components, props and useState — then deploy the resulting app straight from your own repository.

Getting Started12 min readFree lesson

Audience: Students who have completed Lessons 1–4 (HTML/CSS/JS basics, Git push, DOM manipulation) Time: A 1–2 hour special lecture Prerequisites: A laptop with Node.js installed, VS Code, a GitHub account Deliverable: A real web app built with Next.js, deployed to Vercel — https://my-next-app.vercel.app


The Lesson Flow at a Glance

Time Step What You Learn
0:00 ~ 0:15 1. What are React and Next.js? Why we need them
0:15 ~ 0:30 2. Installing Node.js & creating a project Preparing the environment
0:30 ~ 0:50 3. Understanding the Next.js project structure What each folder is for
0:50 ~ 1:15 4. Components and props The core of React
1:15 ~ 1:35 5. Managing state with useState Dynamic UI
1:35 ~ 1:50 6. Adding pages & routing Building multiple pages
1:50 ~ 2:00 7. Deploying to Vercel & wrapping up The real main event

1. What Are React and Next.js? (15 minutes)

The Limits of What We Built Through Lesson 4

So far we have crammed everything into a single page.

<!-- index.html -->
<head>
    <style>...hundreds of lines of CSS...</style>
</head>
<body>
    ...hundreds of lines of HTML...
    <script>
        ...hundreds of lines of JS...
    </script>
</body>

What happens when the site grows to 10 pages, or 100? Copy and paste the same header every time? It would be nice if fixing one place fixed them all...

The React Idea

"Break the screen into small parts (components) and assemble them."

[App]
  ├─ [Header]
  ├─ [Hero]
  ├─ [CardList]
  │     ├─ [Card]
  │     ├─ [Card]
  │     └─ [Card]
  └─ [Footer]

Once you build each part, you can use it anywhere, and a change in one place shows up everywhere.

What Is Next.js?

React is "a tool for building parts," and that alone does not make a website. You also need routing, SEO, builds, server features, and more.

Next.js = React + everything a website needs

💡 If React is the "engine," Next.js is "the finished car with the engine installed."

Why Does Vercel Emphasize It?

Next.js is a framework built by Vercel itself. That is why deploying to Vercel automatically optimizes everything.

Next.js code → GitHub → Vercel
                          ↓
        automatically a fast site, automatic SEO, automatic image optimization...

Do Real Companies Use It?

Yes. Netflix, TikTok, Toss, Karrot, Woowa Brothers, and countless other companies use Next.js + Vercel or a variant of it. For a beginner, it is the shortest path that leads straight into professional work.


2. Installing Node.js & Creating a Project (15 minutes)

2-1. Why Do We Need Node.js?

Until now we have run JS only in the browser. Node.js is a runtime that lets you run JS on your own computer. You need it to create a Next.js project, build it, and start the development server.

2-2. Installation

https://nodejs.org → download the LTS version → install (keep every option at its default).

Verify:

node --version    # around v20.x.x
npm --version     # around 10.x.x

💡 npm is the package manager that is installed together with Node. You use it to pull in libraries other people have written.

2-3. Creating a Next.js Project

Move to your working folder, then:

npx create-next-app@latest my-next-app

When the prompts appear, answer as follows (you can press Enter to accept the defaults):

Would you like to use TypeScript?      → No
Would you like to use ESLint?          → Yes
Would you like to use Tailwind CSS?    → Yes
Would you like your code inside `src/`?→ Yes
Would you like to use App Router?      → Yes (recommended)
Use Turbopack for `next dev`?          → Yes
Would you like to customize import alias? → No

When the install finishes:

cd my-next-app
npm run dev

Open http://localhost:3000 in your browser — you will see the Next.js welcome screen. A web app is already running.

⚠️ Leave the terminal window exactly as it is. If you close it, the server shuts down. Keep this window open for the whole time you are editing code.


3. Understanding the Next.js Project Structure (20 minutes)

Open the my-next-app folder in VS Code.

3-1. Key Folders and Files

my-next-app/
├── src/
│   └── app/
│       ├── page.js        ← the main page (/)
│       ├── layout.js      ← the shared layout for every page
│       └── globals.css    ← global CSS
├── public/                ← static files such as images and icons
├── package.json           ← project info and the dependency list
└── next.config.mjs        ← Next.js configuration

3-2. The Core Rule: Folder = Route

app/page.js              → /            (main)
app/about/page.js        → /about       (about page)
app/blog/page.js         → /blog        (blog)
app/blog/post/page.js    → /blog/post

Creating a folder = creating a new page. This is the automated version of making a separate about.html back in Lesson 1.

3-3. Opening page.js

Open src/app/page.js and you will see:

export default function Home() {
    return (
        <main>
            <h1>Welcome to Next.js</h1>
        </main>
    );
}

This is a component. One function draws one part of the screen.

3-4. Your First Edit

Replace the contents of page.js with the following:

export default function Home() {
    return (
        <main style={{ padding: 40, fontFamily: "sans-serif" }}>
            <h1>Hi, I'm Alex Kim 👋</h1>
            <p>My first page built with Next.js!</p>
        </main>
    );
}

Save → the browser refreshes automatically → the change appears immediately. (This is called Hot Reload.)

3-5. Wait, Is This HTML or JS?

return (
    <main>
        <h1>Hello</h1>
    </main>
);

This is JSX — syntax that lets you write HTML directly inside JavaScript.

How it differs from HTML:

  • class → className
  • for → htmlFor
  • Styles are objects: style={{ color: "red" }}
  • Every tag must be closed: <img />, <br />

4. Components and props (25 minutes) ⭐ Core

4-1. Creating Your First Component

Create a Card.js file inside src/app/:

export default function Card() {
    return (
        <div style={{
            padding: 20,
            background: "#f3f4f6",
            borderRadius: 8,
            marginTop: 20
        }}>
            <h2>Interests</h2>
            <p>Web development</p>
        </div>
    );
}

Use it in page.js:

import Card from "./Card";

export default function Home() {
    return (
        <main style={{ padding: 40, fontFamily: "sans-serif" }}>
            <h1>Hello 👋</h1>
            <Card />
            <Card />
            <Card />
        </main>
    );
}

Three identical cards appear. This is the first moment you build a part and reuse it.

4-2. But Every Card Looks the Same?

What if you want them to differ? You use props.

Edit Card.js:

export default function Card({ title, content }) {
    return (
        <div style={{
            padding: 20,
            background: "#f3f4f6",
            borderRadius: 8,
            marginTop: 20
        }}>
            <h2>{title}</h2>
            <p>{content}</p>
        </div>
    );
}

In page.js:

import Card from "./Card";

export default function Home() {
    return (
        <main style={{ padding: 40, fontFamily: "sans-serif" }}>
            <h1>Hello 👋</h1>
            <Card title="Interests" content="Web frontend, game development" />
            <Card title="Contact" content="[email protected]" />
            <Card title="Favorites" content="Coffee ☕" />
        </main>
    );
}

Each card now renders with different content.

4-3. props Are the Core

[Parent component] ──(passing props)──> [Child component]
     page.js                          Card.js

It is the same idea as passing arguments to a function. Thanks to this structure, you can build endlessly varied screens out of the same part.

4-4. Keeping It Clean with an Array

As the data grows, manage it with an array:

import Card from "./Card";

const cards = [
    { title: "Interests", content: "Web frontend" },
    { title: "Contact", content: "[email protected]" },
    { title: "Favorites", content: "Coffee ☕" },
];

export default function Home() {
    return (
        <main style={{ padding: 40, fontFamily: "sans-serif" }}>
            <h1>Hello 👋</h1>
            {cards.map((c, i) => (
                <Card key={i} title={c.title} content={c.content} />
            ))}
        </main>
    );
}

map turns each item in the array into a component. Add data and the screen grows automatically.


5. Managing State with useState (20 minutes)

5-1. Rebuilding the Lesson 4 Counter in React

Let's rebuild the click counter from Lesson 4 in React. Create Counter.js inside app/:

"use client";

import { useState } from "react";

export default function Counter() {
    const [count, setCount] = useState(0);

    return (
        <div style={{ marginTop: 20 }}>
            <p>Button clicks: {count}</p>
            <button onClick={() => setCount(count + 1)}>
                Try clicking
            </button>
        </div>
    );
}

Use it in page.js:

import Counter from "./Counter";

// ... add <Counter /> inside the Home function

5-2. What Just Happened?

useState(0) = "create a state whose value starts at 0."

The two things it returns:

  • count — the current value
  • setCount — the function that changes the value
const [count, setCount] = useState(0);
//      ↑          ↑           ↑
//  current value  setter   initial value

5-3. Why Not Just Use a Plain Variable?

let count = 0;  // ❌ does not work in React
count = count + 1;

The value does change, but React has no idea it should redraw the screen. You have to use setCount so React thinks "oh, the value changed — I should redraw the screen" and updates automatically.

5-4. What Is "use client"?

Next.js components are server components by default. To react to user actions (a click, for example), a component has to run in the browser, so you write "use client"; at the very top of the file.

💡 At first, just memorize it as "if you use useState or onClick, add "use client"." The details can wait.


6. Adding a Page & Routing (15 minutes)

6-1. Creating the About Page

Create an about folder inside src/app/ → create page.js inside it:

export default function About() {
    return (
        <main style={{ padding: 40, fontFamily: "sans-serif" }}>
            <h1>About</h1>
            <p>I'm Alex Kim, and I'm learning web development.</p>
        </main>
    );
}

Open http://localhost:3000/about in your browser — the new page appears. All you did was create a file, and a new URL exists.

6-2. Linking Between Pages

Add this to page.js:

import Link from "next/link";

// ... wherever it fits
<Link href="/about">Go to the About page</Link>

Using <Link> instead of <a> switches pages without a full reload (a core Next.js optimization).


7. Deploying to Vercel & Wrapping Up (10 minutes)

7-1. Pushing to GitHub

git init
git add .
git commit -m "Initial Next.js project"

Create a new repository called my-next-app on GitHub (do not generate a README).

git remote add origin https://github.com/your-username/my-next-app.git
git branch -M main
git push -u origin main

7-2. Deploying to Vercel

https://vercel.com/dashboard → Add New → Project → Import my-next-app → Deploy.

You do not need to touch a single setting. Vercel detects Next.js automatically and takes care of everything for you.

Thirty seconds to a minute later — the deployment is done. A real web app is live at https://my-next-app-xxx.vercel.app.

💡 The difference from Lesson 1: back then it was static HTML, but this time a build step is involved. Vercel handling that automatically is the real magic.

7-3. What We Learned Today

What React/Next.js means: assembling a web app from parts
   ↓
Creating a project (npx create-next-app)
   ↓
Folder = page routing
   ↓
Reuse with components + props
   ↓
Dynamic state with useState
   ↓
Automatic deployment with Vercel

You now know the basics of the tools professional frontend developers use every day.

Good Things to Learn Next

When What Why
Next week Using Tailwind CSS in earnest Faster design
After that fetch + API Routes Talking to a backend
In a month Connecting a database (Supabase, Prisma) A real app
In two months Authentication (NextAuth.js) Login features
After that TypeScript Safer code

Recommended Learning Resources (All Free)

One Last Word

Across five lessons you have gone from a single line of HTML → a real web app.

Things that felt vague at first have probably become familiar words by now.

  • HTML / CSS / JS / Git / GitHub / Vercel / React / Next.js / components / routing / deployment

Having those words roll off your tongue means you now own the basic vocabulary of the developer world. From here, just grow naturally by building whatever you want to build.

The app you made today is still live, and real code has piled up in your GitHub. The real beginning starts now. 🚀


Appendix A. Frequently Asked Questions (FAQ)

Q. npm install is taking forever. The first time, it has to download every dependency, so it takes 1–3 minutes. After that it is cached and fast. If it seems stuck for more than 5 minutes, stop it with Ctrl+C and try again.

Q. The node_modules folder is huge. Does it get pushed to GitHub? No. The .gitignore that Next.js creates automatically includes node_modules. Vercel just reads package.json and reinstalls everything itself.

Q. I got a build error.

  • Search for the first line of the red message in the terminal, word for word.
  • Common causes: a missing "use client", a typo in an import path, a component name starting with a lowercase letter (component names always start with a capital letter!)

Q. Can I skip Tailwind and just use CSS files? Yes. Create a file like Card.module.css and import it. Still, once you learn Tailwind you will move much faster. We will cover it in the next lesson.

Q. React vs Vue vs Svelte — which is best? For beginners, React is overwhelmingly recommended. It has the most learning material, the most jobs, and good frameworks like Next.js behind it. Once you master one well, you can pick up the others quickly.

Q. Can I build mobile apps? Once you know React, you can build mobile apps with React Native. The same concepts carry over directly, so the barrier to entry is low.


Appendix B. Teaching Tips for Instructors

  • Run through the option prompts of npx create-next-app once right before class. The options are added or changed every year or two.
  • The className pitfall in JSX can never be emphasized enough. Bring it up at least three times in the first session.
  • Forgetting "use client" and getting stuck is the most common accident. Simplify it for students: any component that uses useState or onClick always gets it.
  • Tell students to open two terminals: one for npm run dev (kept running), the other for git commands.
  • Sometimes Hot Reload just will not work: the file was not saved, the app is running on a different port, and so on. Restart the server calmly.
  • Resist the urge to split everything into components. At the beginner stage, the priority is splitting out just something like Card so that the idea of props lands clearly, rather than chopping everything into tiny pieces.
  • Set aside 5 minutes for a quick tour of Tailwind. Beginners wonder where strange strings like bg-blue-500 come from.

Written: 2026-05 / License: free to modify and redistribute

Example files

Complete, runnable files used in this lesson. Copy them into your project and experiment.

about/page.jsJavaScript
import Link from "next/link";

export default function About() {
    return (
        <main style={{ padding: 40, fontFamily: "sans-serif", maxWidth: 600, margin: "0 auto" }}>
            <h1 style={{ color: "#2563eb" }}>About</h1>
            <p>I'm Alex Kim, and I'm learning web development.</p>
            <p>Across Lessons 1–5 I went from the very beginning to building a Next.js app.</p>

            <p style={{ marginTop: 40 }}>
                <Link href="/">← Back to Home</Link>
            </p>
        </main>
    );
}
Card.jsJavaScript
export default function Card({ title, content }) {
    return (
        <div style={{
            padding: 20,
            background: "#f3f4f6",
            borderRadius: 8,
            marginTop: 20
        }}>
            <h2>{title}</h2>
            <p>{content}</p>
        </div>
    );
}
Counter.jsJavaScript
"use client";

import { useState } from "react";

export default function Counter() {
    const [count, setCount] = useState(0);

    return (
        <div style={{
            padding: 20,
            background: "#f3f4f6",
            borderRadius: 8,
            marginTop: 20
        }}>
            <h2>Click Counter</h2>
            <p>Button clicks: {count}</p>
            <button
                onClick={() => setCount(count + 1)}
                style={{
                    padding: "10px 20px",
                    background: "#2563eb",
                    color: "white",
                    border: "none",
                    borderRadius: 6,
                    cursor: "pointer"
                }}
            >
                Try clicking
            </button>
        </div>
    );
}
page.jsJavaScript
import Card from "./Card";
import Counter from "./Counter";
import Link from "next/link";

const cards = [
    { title: "Interests", content: "Web frontend, game development" },
    { title: "Contact", content: "[email protected]" },
    { title: "Favorites", content: "Coffee ☕" },
];

export default function Home() {
    return (
        <main style={{ padding: 40, fontFamily: "sans-serif", maxWidth: 600, margin: "0 auto" }}>
            <h1 style={{ color: "#2563eb" }}>Hi, I'm Alex Kim 👋</h1>
            <p>This is the first page built with Next.js.</p>

            {cards.map((c, i) => (
                <Card key={i} title={c.title} content={c.content} />
            ))}

            <Counter />

            <p style={{ marginTop: 40 }}>
                <Link href="/about">Go to the About page →</Link>
            </p>
        </main>
    );
}

Assignment

Assignment 05 — Build a React + Next.js app

Create a small multi-page app with components, props and state, then deploy it.

Setup

npx create-next-app@latest my-next-app
cd my-next-app
npm run dev

Choose the App Router and JavaScript (or TypeScript if you have completed Stage 4).

Pages

  1. / — a hero with a title and a short description.
  2. /about — a second page linked from the navigation.
  3. A shared Header component with links to both pages.

Components

Card — accepts title, description and optional href. Renders a heading, text and a link when href is provided.

Counter — a client component using useState with increment and reset buttons. Show the count in the button label or beside it.

Requirements

  1. Header and Card live in their own files under components/.
  2. The homepage renders at least three Cards from an array with map and a stable key.
  3. Counter is marked "use client" and works after hydration.
  4. Navigation between pages does not trigger a full reload (next/link).
  5. Styling uses CSS modules or Tailwind — no inline style objects for layout.
  6. The page title and description are set with the Metadata API.

Deploy

  1. Push to GitHub.
  2. Import the repository on Vercel.
  3. Open the production URL and test both routes and the counter.

Done when

  • Both routes work on the live URL, including a direct visit to /about.
  • The counter works on mobile.
  • No console errors or hydration warnings.
  • The repository has a README with the live URL.

Learn this lesson with a mentor

Work through the Build Your Homepage series on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now