Appearance
Web Apps from Natural Language
You have an idea for a web application. A dashboard for tracking freelance projects. A searchable recipe collection. A tool that converts a CSV into a formatted report. In a traditional workflow, you would spend the first hour setting up a project: framework, build tool, routing, state management, CSS pipeline. Before you wrote a single line of application logic, you would have written a hundred lines of boilerplate.
In a vibe coding workflow, you describe the application in a paragraph. The agent scaffolds the project, builds the first page, and has something running in the browser before you finish your coffee. This lesson walks through that process end to end, with real prompts and real outcomes. The example is a project dashboard, but the pattern applies to any web application you want to build.
What you'll learn
- Scaffolding a web project is one prompt: describe the stack, the framework, and the first page
- Each subsequent page or feature is another prompt, building on the work the agent already did
- The agent handles boilerplate: routing, state management, build configuration, CSS setup
- Your job is describing what the user should see and do, and reviewing the output to make sure it matches
The problem: from idea to running app without writing boilerplate
You want a web app. You know what it should do. You do not want to spend two hours configuring Vite, setting up React Router, choosing a CSS framework, wiring up state management, and creating a folder structure before you write the first line of actual application code.
Traditional development treats boilerplate as a necessary evil. Vibe coding treats it as something the agent handles while you focus on the application. The skill is not knowing which npm packages to install. The skill is describing the outcome clearly enough that the agent produces a working scaffold on the first try.
Options & when to use each
| Framework | What it is good for | What it costs you | When to pick it |
|---|---|---|---|
| React + Vite | Most LLM training data, widest ecosystem, largest community for troubleshooting | Heavier than necessary for simple pages; JSX can be verbose | Any interactive application; when you want the agent to have the most reference material to draw from |
| Next.js | Server-side rendering, file-based routing, built-in API routes | More opinionated; agent needs to understand the Next.js conventions to produce consistent output | Apps that need SEO, server-rendered pages, or built-in backend endpoints |
| Vue + Vite | Simpler learning curve, single-file components, good LLM support | Smaller ecosystem than React; fewer community examples in training data | When you prefer Vue or when the app is primarily forms and data display |
| Plain HTML/CSS/JS | Zero build step, runs anywhere, smallest possible output | No component model; gets unwieldy past a few pages | Static sites, prototypes, anything that does not need a framework |
Build it: a project dashboard from one paragraph
Step 1: Scaffold the project
Open Claude Code in an empty directory and describe what you want:
> Create a React project with Vite and TypeScript. It is a freelance project
dashboard. Users see a list of their active projects with client name,
deadline, budget, and status. They can add new projects, edit existing ones,
and mark projects as complete. Use Tailwind CSS for styling. Use React Router
for navigation: a home page listing projects, a detail page for each project,
and a form page for adding/editing. Use localStorage for persistence so data
survives page reloads. Do not add a backend. Make it look professional: clean,
modern, good use of whitespace and color.The agent will:
- Run
npm create vite@latestwith the React TypeScript template - Install dependencies:
react-router-dom,tailwindcss,@tailwindcss/vite - Configure Tailwind and the Vite plugin
- Create the folder structure:
/src/components/,/src/pages/,/src/hooks/ - Build a
ProjectListcomponent with mock data - Set up React Router with routes for
/,/projects/:id,/projects/new,/projects/:id/edit - Add basic Tailwind styling that looks clean out of the box
Review the output. The agent will show you the files it created. Look for: routing setup in App.tsx, the project list component, and the Tailwind configuration. If anything is missing, describe it: "Add a navigation bar with links to Home and New Project." The agent adds it.
Step 2: Build the landing page
The scaffold has a basic project list. Now make it real:
> Replace the mock project data with a custom hook that reads and writes to
localStorage. The hook should expose: projects array, addProject(),
updateProject(), deleteProject(), toggleComplete(). Use TypeScript types for
the Project interface. The landing page should show a card for each project
with: client name (bold), deadline (formatted date), budget (formatted as
currency), status badge (colored by status: active=green, completed=blue,
overdue=red). Add a search bar that filters projects by client name. Add a
sort dropdown: sort by deadline, budget, or status. Use Tailwind utility
classes for all styling.The agent builds:
- A
useProjectshook in/src/hooks/useProjects.tswith full CRUD over localStorage - A
ProjectTypeScript interface - A
ProjectCardcomponent with status badges - A search bar with filtered results
- A sort dropdown
Step 3: Add the detail page
> Build the project detail page at /projects/:id. It shows: full project
information (client, deadline, budget, status, description), a button to
edit the project (links to /projects/:id/edit), a button to mark as complete
(calls toggleComplete), a delete button with a confirmation dialog, and a
back button to the project list. Handle the case where the project ID does
not exist: show a "Project not found" message with a link back to the list.Step 4: Add the form page
> Build the add/edit project form at /projects/new and /projects/:id/edit.
Fields: client name (text), project description (textarea), deadline (date
picker), budget (number with dollar sign), status (dropdown: active, on hold,
completed). Validate: client name required, budget must be positive number,
deadline must be in the future. Show validation errors inline below each
field. On submit, save to localStorage and redirect to the project detail
page. If editing, pre-fill the form with existing project data.Step 5: Polish and deploy
> Audit the app for visual consistency. All cards should have the same padding
and border radius. All buttons should use the same style (primary blue,
secondary gray, danger red). The nav bar should be fixed at the top. Add a
footer with a link to the GitHub repo. The app should be fully responsive:
project cards in a single column on mobile, two columns on tablet, three on
desktop. Build for production and tell me how to deploy to a static host.The agent runs npm run build, produces a dist/ folder, and tells you to deploy it to Netlify, Vercel, or GitHub Pages.
What goes wrong
| Mistake | How you notice it | The fix |
|---|---|---|
| Describing too much in one prompt | The agent produces a scaffold that has routing, state, styling, and data management but none of them work correctly because it tried to do everything at once | Break it into steps. Scaffold first. Then data. Then pages one at a time. Each step builds on working output from the previous step |
| Not specifying the CSS framework | The agent picks a default (often plain CSS or a framework you did not want). Styling is inconsistent or hard to modify | Name the CSS framework in your first prompt. "Use Tailwind CSS" or "Use vanilla CSS modules" |
| Letting the agent invent a component architecture | Components become deeply nested, props drilling gets out of hand, and editing one component breaks three others | Specify the component tree early: "Use these components: App > Layout (nav + footer) > Page components. Each page component is self-contained." |
| Not handling empty and error states | The app works perfectly with data but shows a blank page or crashes when the project list is empty or an ID is invalid | Explicitly ask for empty states and error states in every prompt. "Handle the case where there are no projects." "Handle invalid project IDs." |
| Building without testing in the browser | The agent says it is done. The code looks right. You deploy it and the first user finds a broken button | Run npm run dev after every major step. Click through the app. Confirm each feature works before moving to the next prompt |
Confirm it worked
Run npm run dev and open the browser. You should see a project dashboard with a search bar, sort dropdown, and a grid of project cards. Click "New Project" and fill out the form. Submit it. The new project appears in the list. Click it to see the detail page. Edit it. Mark it complete. Delete it. Refresh the page: the data persists in localStorage.
Then open Claude Code again and ask it to add a new feature: "Add a project statistics bar at the top of the dashboard showing total projects, active projects, total budget across all projects, and number of overdue projects." The agent should add this feature without breaking existing functionality. If it does, you have a working vibe-coded web app that can survive feature additions. If it breaks something, re-read the prompting patterns from Day 1: your system prompt or context management needs adjustment.
Next: Working with APIs & External Services -- connect your app to real external services the same way you built this one.