← Workshops Β· Part 1 Β· Beginner

Build a Web App with Claude Code

Describe what you want in plain English and let Claude Code build it. This part takes you from nothing to a working app on your own machine. Getting it online is Part 2.

πŸ“ Test yourself ↓
18 min readBeginnerRead or present

What you'll build

A real web app β€” a page you can open in any browser β€” built with Next.js, without writing the code by hand. You'll describe what you want in plain English and let Claude Code do the typing. This part takes you from nothing to the app running on your own machine. Putting it online comes next, in Part 2.

🧭

Install a few tools β†’ describe your app to Claude Code β†’ preview it locally β†’ iterate. That's this whole part. Deploy is Part 2.

The tools you'll meet

πŸ’»

Claude Code

An AI coding assistant in your terminal. You talk; it writes and edits files.

⚑

Next.js

The framework your app is built with. Claude Code sets it up for you.

🟩

Node.js

The engine that runs your app while you build. You install it once.

πŸ™

Git & GitHub

Where your code lives. You'll need it when you deploy in Part 2.

Before you start

Step 1

Install Node.js

Install the LTS build from nodejs.org, then check it in your terminal (Mac: ⌘+Space β†’ "Terminal"; Windows: PowerShell):

node --version   # should print v22.x.x or similar
Step 2

Install Claude Code

npm install -g @anthropic-ai/claude-code

mkdir my-first-app && cd my-first-app
claude            # follow the login link the first time
πŸ’‘

The terminal isn't scary. It's a text box for commands β€” and Claude Code can run most of them for you when you ask.

Step 3

Ask Claude Code to build your app

Describe the purpose and the vibe; let it make the technical choices:

> Create a new Next.js app in this folder using TypeScript and the
  App Router. Build a one-page personal site with a hero, an "about"
  section, a list of projects as cards, and a contact footer. Clean
  dark theme, blue accent. Then start the dev server so I can see it.

It creates the files, installs what it needs, and asks before running commands β€” say yes.

What Claude Code actually runs

Behind that one request, it runs the same commands a developer would type by hand β€” and asks before each:

npx create-next-app@latest . --typescript --app   # scaffold the Next.js project here
npm install                                        # download the libraries it needs
npm run dev                                         # start the dev server
# ➜ Local:  http://localhost:3000

You don't have to remember any of these β€” Claude Code picks and runs them. Seeing them helps you follow along, and recognize them when it asks for permission.

Step 4

Run it locally β€” and stop here

npm run dev
# ➜ Local:  http://localhost:3000

Open http://localhost:3000. Leave it running β€” the page refreshes on every edit. Keep asking for changes until you like it. This is the finish line for Part 1: a working app on your machine. You don't need to deploy anything yet.

What all these files are: the Next.js layout

my-first-app/
β”œβ”€ app/                # your pages live here
β”‚  β”œβ”€ layout.tsx       # shared shell around every page
β”‚  β”œβ”€ page.tsx         # the homepage  β†’  "/"
β”‚  β”œβ”€ globals.css      # site-wide styles
β”‚  └─ about/
β”‚     └─ page.tsx      # the about page  β†’  "/about"
β”œβ”€ public/             # images & static files, served as-is
β”œβ”€ package.json        # dependencies + dev/build scripts
└─ node_modules/       # installed libraries (never edit)
πŸ—ΊοΈ

Don't memorize it. Ask Claude Code "give me a tour of my project."

npm, yarn, pnpm β€” what are these?

You keep typing npm. It's a package manager β€” it downloads the open-source libraries your app depends on (into node_modules/) and runs your project's scripts. There are three common ones; they do the same job, just faster or tidier:

ToolWhat it isInstall a packageRun a script
npmShips with Node.js β€” the default, always there.npm install xnpm run dev
yarnAn early faster alternative; still widely used.yarn add xyarn dev
pnpmFastest, saves disk space (shared package store).pnpm add xpnpm dev
🎯

Which should you use? As a beginner, stick with npm β€” it's built in and every tutorial assumes it. Pick one per project and don't mix them (each writes its own lock file β€” package-lock.json, yarn.lock, or pnpm-lock.yaml β€” that pins exact versions so everyone gets the same install).

What's in package.json?

package.json is your project's ID card β€” the one file that says what your app is called, what it depends on, and what commands it can run. Every package manager reads it:

A cardboard box labelled package.json β€” the manifest that lists what goes in your project.
One box, one packing list. Everything your project needs is declared here.
// package.json
{
  "name": "my-first-app",
  "scripts": {                 // the commands you can run
    "dev": "next dev",          // npm run dev  β†’ start locally
    "build": "next build",      // npm run build β†’ production build
    "start": "next start",
    "lint": "eslint"
  },
  "dependencies": {            // libraries your app needs to run
    "next": "^15.0.0",
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  },
  "devDependencies": {         // tools needed only while developing
    "typescript": "^5",
    "eslint": "^9"
  }
}
πŸ’‘

You rarely edit it by hand. npm install some-lib adds the dependency for you β€” or just ask Claude Code, "add and set up <library>."

Make it look designed, not default

Claude Code has Skills for design β€” ask for them by name so your app doesn't look templated:

🎨

frontend-design

Distinctive typography, spacing, and visual identity.

🧩

shadcn

Ready-made, accessible UI components that already look sharp.

> Use your frontend-design skill to give this a stronger visual
  identity β€” deliberate type, generous spacing, one accent color.
  Avoid a generic "AI landing page" look.

Start from a template β€” especially for dashboards

You don't have to build the layout from scratch. A template is a ready-made skin β€” the sidebar, top bar, cards, tables, and charts already arranged β€” so you just drop in your content and data. Dashboards are mostly the same furniture every time, which is exactly where a template saves the most work.

And yes β€” there are gallery pages you browse exactly like PrimeVue's templates showcase: preview a design, then clone it and start editing. The best for a Next.js + React app:

🧩

shadcn/ui blocks β†—

A gallery of copy-in "blocks" β€” including full dashboard layouts (sidebar, cards, data tables).

πŸ“Š

Tremor β†—

React components built for dashboards: KPI cards, charts, and tables, consistent out of the box.

β–²

Vercel Templates β†—

Clone a whole admin/SaaS starter β€” many are one-click deploy β€” and start editing.

🎨

Tailwind Plus β†—

Professionally-designed page & dashboard sections (formerly Tailwind UI).

πŸ”

Coming from PrimeVue? Its React sibling PrimeReact has the same templates gallery, and it works in Next.js too. Other free galleries worth a browse: Flowbite, Preline, and MUI templates.

Tell Claude Code to build on one instead of starting from a blank page. Notice how much of the thinking happens in the prompt β€” every line below closes off a decision you'd otherwise have to undo later:

> Goal: turn this into a dashboard.

  Shell: a left sidebar for navigation, a top bar with the page
  title, and a main content area β€” plain Tailwind, no second UI
  library.

  Data parts with Tremor: four stat cards across the top, a line
  chart of events over time, and a recent-activity table below it.

  Style: take every color, spacing value and radius from the @theme
  block in app/globals.css. Don't invent new ones.

  Data: seed realistic event-log rows β€” timestamp, source, level,
  message β€” so the chart and table have something to show. I'll
  wire the real API in Part 5.

  Constraints: put the shell in one <DashboardLayout> component so
  every page can reuse it, and make it work down to phone width.

  Build the dashboard page only. Show me it before going further.

Once you like it, roll it out β€” and keep the agent on a short leash while it touches pages that already work:

> Now move the existing pages onto it: wrap each one in
  <DashboardLayout>, swap any hand-rolled cards for Tremor's Card,
  and delete the CSS that's now unused. One page at a time β€” show
  me each before you start the next.
πŸ’‘

Why start from a skin: the fiddly part of a dashboard is the responsive layout and consistent spacing. Let a template own that, and spend your time on the content and data that make it yours. Ask Claude Code "what dashboard templates fit this?" and it'll pick one and wire it up.

Every one of those galleries is built on the same two things, and they do completely different jobs. A few minutes here saves a lot of confusion later β€” especially because you are already using one of them.

Tailwind CSS β€” how the styling gets written

The traditional way to style a page is two files: you invent a class name in your HTML, then write the rules for it in a stylesheet. Tailwind deletes the invention step. It gives you hundreds of tiny single-purpose classes β€” flex, p-6, rounded-xl β€” and you compose the design directly on the element:

// The traditional way β€” two files, and a name you had to think up
<div class="price-card"> … </div>

// styles.css
.price-card {
  display: flex;
  gap: 0.75rem;
  padding: 1.5rem;
  border-radius: 0.75rem;
  background: #1a2236;
}

// Tailwind β€” the same card, one file, nothing to name
<div class="flex gap-3 p-6 rounded-xl bg-slate-800"> … </div>

It looks noisy the first time you see it, and that reaction is normal. What you get back is worth the noise: the styling is where the element is. To change how something looks you edit that line β€” you never go hunting through a stylesheet wondering which rule is winning, and deleting a component deletes its CSS with it.

πŸ€–

This is why it pairs so well with Claude Code. "Make the cards tighter and give them a border" is a single-line edit in a single file. With hand-written CSS the agent has to find the right rule, check nothing else depends on it, and guess at specificity β€” that's where styling changes go wrong.

βœ…

You already have it. create-next-app sets up TypeScript, Tailwind, ESLint, the App Router and Turbopack by default β€” so those classes in the code Claude Code just wrote for you are Tailwind. Nothing to install.

⚠️

There is no tailwind.config.js any more. Tailwind v4 moved configuration into your CSS: @import "tailwindcss"; in app/globals.css, and your own colors and fonts in a @theme block. Older tutorials will confidently tell you to edit a config file that your project doesn't have.

Tremor β€” the dashboard parts Tailwind doesn't give you

Tailwind styles things. It does not give you things β€” there is no chart class, because a chart is not a style, it's a component. Tremor is a set of React components built for dashboards: KPI cards, charts, and data tables. Because it's built on Tailwind, it inherits the same spacing and color scale as the rest of your app instead of looking bolted on.

import { Card, LineChart } from '@tremor/react';

<Card>
  <LineChart data={revenue} index="month" categories={['eur']} />
</Card>
// ~4 lines for a chart that is responsive, themed, and has tooltips

How the pieces stack

Every gallery above sits somewhere on this ladder:

  your app        app/page.tsx β€” your content and your data
  ───────────────────────────────────────────────────────────
  components      shadcn/ui  β†’ buttons, dialogs, tables, forms
  (pick one)      Tremor     β†’ KPI cards, charts, dashboard tables
  ───────────────────────────────────────────────────────────
  Tailwind CSS    the utility classes both are built out of
🧯

Pick one component library and stay there. shadcn/ui and Tremor overlap β€” both have cards and tables. Installing three libraries gets you three design systems arguing with each other in the same page. Choose by what you're building: a dashboard leans Tremor, a general app leans shadcn/ui.

A good way to learn Tailwind is to make the agent teach you from your own code:

> Explain the Tailwind classes on this component line by line in
  plain English. Then pull the repeated ones into a reusable
  <StatCard> component so I'm not copying the same 12 classes.

How to prompt for web development

Good prompts answer four things β€” goal, context, style, constraints:

> Build a homepage for a coffee roaster called "Ember". Sections:
  hero with tagline, short "our story", three product cards with
  price, footer with address + Instagram. Warm palette (browns,
  cream), rounded corners. Must look great on a phone.

Give the project a CLAUDE.md

Drop a CLAUDE.md at the repo root so Claude Code knows your conventions every session (/init scaffolds one for you):

# CLAUDE.md

## What this is
Personal / marketing site. Next.js (App Router) + TypeScript. No backend yet.

## Commands
- Dev / Build / Lint: npm run dev / build / lint   (dev on :3000)

## Structure
- app/            routes (folder + page.tsx = a URL)
- app/layout.tsx  shared shell (nav, fonts)
- public/         static assets, served at /
- components/     reusable UI

## Conventions
- Dark theme, blue accent. Reuse tokens in app/globals.css β€” don't hardcode colors.
- One component per file; keep them small.

## Verify
Run the dev server; check the changed page on desktop + mobile.

…and a DESIGN.md for the look

CLAUDE.md tells the agent how you build. DESIGN.md tells it how you look β€” a single file at the repo root holding your colors, type scale, spacing and component rules, in a format agents read natively. It solves the problem you hit around page four: the new page is fine on its own, but it doesn't match the three you already have.

It's an open format from Google Labs β€” text, Git-versionable, readable by Claude Code, Cursor or Copilot alike. And you don't have to write one from scratch: getdesign.md is a catalog of a few hundred DESIGN.md files reverse-engineered from real products, so you can start from a visual language that already works.

Steps to implement it

  1. Pick a starting point. Browse the catalog at getdesign.md/design-md and grab the analysis whose feel is closest to what you're after β€” or skip the catalog and have Claude Code write one from your existing pages (step 3).
  2. Save it as DESIGN.md at the repo root, next to CLAUDE.md. YAML front matter carries the tokens an agent can act on; the prose below explains the intent:
    ---
    name: Ember
    colors:
      primary: "#1A1C1E"
      tertiary: "#B8422E"
      neutral: "#F7F5F2"
    typography:
      h1: { fontFamily: Public Sans, fontSize: 3rem }
      body-md: { fontFamily: Public Sans, fontSize: 1rem }
    rounded: { sm: 4px }
    spacing: { sm: 8px }
    ---
    
    ## Overview        ← the sections the spec expects, in this order
    ## Colors
    ## Typography
    ## Layout
    ## Elevation & Depth
    ## Shapes
    ## Components
    ## Do's and Don'ts
  3. Point Claude Code at it β€” once, in plain English:
    > Read DESIGN.md and restyle the homepage to match it exactly β€”
      its colors, type scale, spacing and radii. Don't invent values
      that aren't in the file. Then add a line to CLAUDE.md telling
      future sessions to follow DESIGN.md for anything visual.
    That last sentence is the important one: it makes the design brief stick across sessions instead of being a one-off instruction.
  4. Check it's valid. The official linter catches broken token references and flags contrast that fails accessibility checks:
    $ npx @google/design.md lint DESIGN.md
  5. Turn the tokens into Tailwind. This is where it meets the section above β€” export your tokens and paste them into the @theme block in app/globals.css, and your DESIGN.md colors become real utility classes:
    $ npx @google/design.md export --format json-tailwind DESIGN.md
  6. Commit it. Like CLAUDE.md, its whole value is being in the repo β€” every future session, and every teammate's agent, inherits the same visual language for free.
🎨

No catalog, no problem. Ask Claude Code to work backwards from what you've already built: "Read my components and app/globals.css, then write a DESIGN.md that documents the design system I actually have." You get an honest brief instead of an aspirational one β€” and it'll surface the inconsistencies you'd drifted into.

⚠️

Two caveats. The spec is young β€” Google Labs published it as a draft in April 2026, so expect the format to move. And a catalog entry is a starting point, not a brand: shipping a pixel-accurate copy of Stripe's design system gives you Stripe's identity, not your own. Take the structure, then change the colors and type until it's yours.

Let Claude Code see your app in the browser

Up to now you've been the messenger: you look at localhost:3000, spot something wrong, describe it, and copy the console error back into the terminal. The Chrome integration removes that round trip. Claude Code drives a real Chrome window β€” it opens your app, clicks through it, reads the console, and then fixes the code that caused the error, in one go.

Two pieces have to meet: the Claude in Chrome extension in your browser, and Claude Code started with the --chrome flag.

  1. Install the extension β€” Claude in Chrome from the Chrome Web Store (v1.0.36 or newer).
  2. Start Claude Code with the browser attached. The first launch shows a one-time dialog explaining how site permissions work:
    $ claude --chrome
  3. Ask it to go and look. Leave npm run dev running in its own terminal first:
    > Open localhost:3000, click through every link in the nav, and
      tell me if anything 404s or throws a console error.
    The first browser action asks permission to use the claude-in-chrome skill β€” approve it and a new tab opens.
  4. Use /chrome when something's off. It shows the connection status β€” you want Status: Enabled and Extension: Installed β€” and lets you manage site permissions or reconnect if the extension goes idle during a long session.
πŸ”—

This is where the last two sections pay off. Once it can see the page, "does it match?" becomes a question it can answer itself: "Open localhost:3000, compare it against DESIGN.md, and list every place the spacing or color doesn't match the tokens." Same for responsiveness β€” "check it at phone width and tell me what breaks."

βœ…

What you need: Chrome or Edge (other Chromium browsers like Brave and Arc work too), a direct Anthropic plan β€” Pro, Max, Team or Enterprise β€” and to be signed in with /login. An API key won't work; the extension can't authenticate with one. Not supported inside WSL.

πŸ”’

It's your real browser, with your real logins. That's what makes it useful and what makes it worth a moment's thought: the agent can act on any site you're signed into. Keep the extension's site permissions to the sites you actually want it touching, and treat a page's content as untrusted input β€” text on a web page can try to instruct the agent. For a beginner building on localhost, none of this bites; it matters the day you point it at the open web.

βš™οΈ

Tired of the flag? Run /chrome and pick Enabled by default. The trade-off is that browser tools are then always loaded, which uses more of your context window β€” so if sessions start feeling short, turn it back off and use --chrome only when you need it.

Tips for working with Claude Code

Check yourself

Quiz β€” 15 questions

Answer every question, then submit to see your score and the correct answers.

Want a hand getting started?

This whole site was built with Claude Code. If you’d like help getting going β€” or a production build done right β€” reach out.

βœ‰οΈ Get in touch ← Back to workshops