← All courses

Prototyping from a Design Idea

This course is for designers who can shape a screen in Figma but have never turned one into something a person can actually click. By the end you'll carry a real design all the way to a working, shareable prototype, built with rules that keep it from falling apart.

6Modules
1Capstone
~3hPer week
2–3Weeks
BeginnerSkill level

A mockup shows what a screen looks like. A prototype shows what it feels like to use, and that gap is where the real design questions live: does the flow make sense, does the timing feel right, would a stranger get stuck. With Claude Code, you can describe a screen you've already designed and have something clickable in minutes.

Speed without rules means drift. A fourth shade of gray sneaks in, spacing wanders, and by the fifth screen it looks like four different people made it. This course teaches one habit to prevent that: write the rules down before you need them. The designers who build twenty coherent screens wrote their design law first and made Claude follow it.

Module 00

From Static to Living

why a working prototype beats a perfect mockup

Why it matters

You already know how to make a screen look right. What a static mockup can't tell you is whether it works: whether the flow holds together, whether a real person can get from start to finish without you standing over their shoulder. The difference between a prototype you can keep building on and one that falls apart by screen five comes down to one habit: writing your rules somewhere the tool can read them.

Concepts

Mockup, prototype, product: three different things. A mockup is a picture of a screen. A prototype is one that responds, with real components and real interaction running on fake data. A product is a prototype hardened for strangers, with real data, accounts, and error handling. This course lives in the middle. You're building prototypes real enough to test and share, without the weight of a full product.

Mockup

A static picture of a screen. Looks right, does nothing.

Prototype

Clickable and alive. Real components, real interaction, fake data.

Product

A prototype hardened for real users. Not our scope here.

Drift

When a design slowly loses consistency as it grows.

The stack this course uses. You'll build with React, Vite, and TypeScript. It's a deliberate choice, not the only one. React gives you components that map cleanly onto how designers already think. Vite runs your project and shows it in a browser quickly. TypeScript adds guardrails that catch mistakes before they reach the screen. Other stacks work fine too, and you should know they exist.

What we useThe alternativeWhy we picked ours
React + ViteNext.jsNext.js is built for production apps with servers. For prototypes, Vite is lighter and starts faster.
TypeScriptPlain JavaScriptTypes are guardrails. They catch a whole class of mistakes before you ever see them in the browser.
ReactVue, SvelteAll fine choices. React has the biggest community and Claude knows it best, so you'll hit fewer dead ends.

You don't need to learn TypeScript before starting. You'll pick it up by reading what Claude writes and correcting it. The goal is to direct the build and judge whether the result is right, not to memorize syntax.

Build with Claude Code

Open Claude Code in an empty folder and start with the smallest possible thing. Prompt: "Set up a new React project with Vite and TypeScript, then show me one screen from this description: [describe one screen you've already designed]." Don't worry yet about whether it matches your design exactly. The point here is to feel the loop: describe, build, look, correct. Notice how close Claude gets from a plain-English description, and write down where it missed.

Exercises

  • Pick one screen from a project you've designed. It will be your running example for the whole course.
  • Get a React + Vite + TypeScript project running and open in your browser.
  • Describe your screen to Claude in plain English and have it build a first version.
  • Write down three ways the result differs from what you pictured. You'll fix these as the course goes.

You've got it when…

You have a React project running in your browser showing a rough first version of one of your own screens, and you can clearly say what a prototype needs to prove that a mockup can't.

Module 01

Writing Your Design Law

the rules that keep your prototype from drifting

Why it matters

Left to its own devices, the tool will give you a slightly different button every time you ask for one. As a designer, you hold the whole system in your head and enforce consistency by eye. A prototype that drifts loses that fast. The fix is to write the rules down once, in a file the tool reads before every build. That file is what keeps your prototype coherent as it grows.

Concepts

Persistent context beats repeated instruction. Drift happens because you re-explain your intentions every time, slightly differently, and the tool fills the gaps with its own guesses. When the rules live in a file that's read automatically instead, every build inherits the same law. You stop repeating yourself, and the guessing stops with it.

Two files, two jobs. A CLAUDE.md is your project's operating manual: Claude Code reads it automatically at the start of every session, and it holds the stack, conventions, and pointers to other docs. A DESIGN.md is your design law: tokens, spacing scale, type scale, component rules, and a do-not list. You keep them separate because they answer different questions, and you point CLAUDE.md at DESIGN.md so the design law loads every session without you pasting it in again.

CLAUDE.md
# Project: Onboarding Prototype

## Stack
- React + Vite + TypeScript
- All styling uses design tokens. Never hardcode colors or spacing.

## Design rules
Read DESIGN.md before building or changing any UI.
It is the source of truth for color, spacing, type, and components.

## Conventions
- One component per file.
- Components live in src/components.

A DESIGN.md is your design system, written so a machine can obey it. This is the document you always wished engineering would follow. Here, Claude follows it because you made it cheap to. Define your tokens as named values, your scales as fixed steps, and your rules as plain statements. The more specific you are, the less Claude guesses.

DESIGN.md
# Design Law

## Color tokens (use these names, never raw hex)
- color-ink:     #1a1a1a   # primary text
- color-muted:   #6b7280   # secondary text
- color-accent:  #c4633f   # actions, links
- color-surface: #f5f5f4   # cards, panels

## Spacing scale (only these steps, in px)
4, 8, 12, 16, 24, 32, 48, 64

## Type scale
- h1: 32px / 600   - body: 16px / 400
- h2: 24px / 600   - small: 13px / 400

## Rules
- Buttons use color-accent. Never invent a new button color.
- One accent color only. No gradients.
- Border radius is always 6px.

## Do not
- Do not hardcode hex values. Use a token.
- Do not introduce a spacing value outside the scale.

This is a skill you already have. You enforce these rules by eye every day; now you're writing them down. The hard part is being honest and specific about what your design actually allows. Vague rules produce vague results.

Build with Claude Code

Don't write DESIGN.md from a blank page. Extract it from work you've already done. Prompt: "Look at this screen / these Figma values and propose a DESIGN.md with my color tokens, spacing scale, type scale, and component rules. List anything you had to guess so I can correct it." Then edit it for taste. Claude can find the values; it can't know which gray you actually meant or which rule matters most to you. The "list anything you had to guess" clause surfaces exactly where your design was ambiguous, which is the part only you can fix.

Exercises

  • Create a DESIGN.md with your real color tokens, spacing scale, and type scale.
  • Write at least three component rules and three do-not rules in plain language.
  • Create a CLAUDE.md that names your stack and points to DESIGN.md as the source of truth.
  • Rebuild your Module 00 screen and confirm it now follows your tokens without you repeating them.

You've got it when…

You have a DESIGN.md Claude reads before it builds, a CLAUDE.md that points to it, and you can explain in one sentence why writing the rules down prevents drift.

Module 02

Reading Your Design Like a Brief

translating visual intent into instructions Claude can act on

Why it matters

The quality of your prototype is mostly set the moment you describe it. A vague brief gets a vague build, no matter how good the tool is. Designers are already good at this: handing off intent is half the job. You've just never pointed that skill at a build tool. Your brief tells Claude what this screen is; your DESIGN.md tells it how everything must look. Done right, the first version comes back close.

Concepts

Break a screen into four layers. Before you describe anything, look at your design and separate it into structure (what regions exist and how they stack), hierarchy (what's primary, what's secondary), states (what this screen looks like when empty, loading, or full), and behavior (what happens when someone interacts). Most weak briefs only cover structure and skip the other three. States matter especially: an empty list and a full list are different screens, and a prototype that ignores the empty case feels fake the moment someone tests it.

Structure

The regions of the screen and how they're arranged.

Hierarchy

What the eye should hit first, second, third.

States

Empty, loading, full, error. Each is its own picture.

Behavior

What changes when the user does something.

Specify what matters; delegate the rest. You don't need to dictate every pixel; that's what DESIGN.md is for. Name the things that carry your intent and let Claude handle the rest. If you find yourself describing a color or a spacing value in your brief, stop: that belongs in your design law, not repeated in every prompt.

A screenshot is a starting point. You can hand Claude Code a Figma frame and describe the regions in words alongside it. The screenshot anchors the layout; your words fill in the intent a picture can't carry, like what's clickable and what each state should show.

This is where Klarita fits. The discovery work you do before a prototype (the problem statement, the user flows, the decisions about what a screen needs to prove) is the front half of this exact workflow. A good brief is just that thinking, written down. If you've done the discovery, the brief mostly writes itself.

Build with Claude Code

Feed the design and direct the scaffold, then correct where it guessed. Prompt: "Here's a screenshot of my screen and a description of its structure, states, and behavior. Build it following DESIGN.md. Where my brief was unclear, tell me what you assumed instead of guessing silently." Ask for assumptions out loud because you want them surfaced early, while they're one sentence to fix rather than a tangle to unwind later.

Exercises

  • Take your running screen and write its brief across all four layers: structure, hierarchy, states, behavior.
  • Describe at least one non-obvious state, such as what the screen shows when it's empty.
  • Have Claude build from the brief plus DESIGN.md and list every assumption it made.
  • Fix the two assumptions that matter most by tightening the brief, not by hand-editing the output.

You've got it when…

You can hand Claude a design and a brief and get back a recognizable first version that follows your design law, and you fix problems by sharpening the brief rather than patching the result by hand.

Module 03

Components & Catching Drift

your design system is a component tree, and a lint check keeps it honest

Why it matters

Designers already think in reusable pieces. Code works the same way, which makes components the most natural bridge between the two worlds. The problem is drift: the second time you build a card, if Claude doesn't know about your first one, you get a slightly different version. Do that ten times and your "system" is ten near-identical components that all disagree. This module closes that hole two ways: by registering components in your design law as you build them, and by adding an automated check that catches violations you'd otherwise miss by eye.

Concepts

A component is a Figma component that runs. It's a reusable piece you define once and place many times. The configurable parts (the label, the color variant, whether it's disabled) are called props. Nesting one component inside another is composition, the same as nesting frames. If you already think in components in Figma, React components will feel familiar.

TypeScript
// One component, defined once. The props are its knobs.
type ButtonProps = {
  label: string;
  variant: 'primary' | 'secondary';
  disabled?: boolean;
};

function Button({ label, variant, disabled }: ButtonProps) {
  return (
    <button className={`btn btn-${variant}`} disabled={disabled}>
      {label}
    </button>
  );
}

Register components in your design law as you build them. Every time you create a real component, add a line to DESIGN.md naming it and its props. Your design law grows into a living component inventory, and the next time you need a card, Claude already knows about it. That single habit stops the ten-disagreeing-cards problem before it starts.

The second layer is a check that proves the rules were followed. A DESIGN.md tells Claude the rules; a linter checks whether they were actually obeyed. Think of a linter as a spell-checker for your code's style: it reads every file and flags anything that breaks a rule you've set. Tools like Stylelint and ESLint can be configured against your tokens so that a stray hardcoded color or an off-scale margin fails the check automatically. The tool flags; you decide.

Terminal
# Run the linter against your project
npm run lint

# A violation gets caught before it spreads:
src/components/Card.tsx
  14:18  error  Unexpected hardcoded color "#3a3a3a".
                Use a token from DESIGN.md  design/no-raw-color

The three-layer defense, in order of trust. Each layer catches what the one above it can't. Your DESIGN.md sets the rules. The linter catches violations a machine can prove. Claude-assisted review catches the judgment-level drift a linter can't see, but it's the least certain layer, and you stay the final check.

1 · DESIGN.md

The rules. Sets the law every build inherits.

2 · Linter

Deterministic. Catches what a machine can prove: raw hex, off-scale spacing.

3 · Claude review

Judgment. Catches "wrong button for this context." Least certain. You verify.

Be honest about the third layer. Claude-assisted review can miss real drift and flag things that are perfectly fine. The linter is deterministic; Claude's judgment is not. Treat the review as a second pair of eyes you still overrule, never as the final word.

A note on data. Your prototype needs content to feel real, but it doesn't need a database yet. For everything in this course, keep your data in a local JSON file and import it. Realistic sample content is fine and expected at the prototype stage; it's what makes a stakeholder react honestly instead of squinting past Lorem ipsum. Just know where the line is: on a real project with real users, that data moves to a real backend, and how you handle live data, privacy, and persistence becomes its own serious concern. A JSON file is the right tool for prototyping. When you're building for real users, it needs to be replaced.

Build with Claude Code

First, componentize. Prompt: "Find repeated UI in this screen, turn it into reusable components following DESIGN.md, and add each new component with its props to DESIGN.md."

Then set up the gate: "Configure ESLint and Stylelint to enforce my DESIGN.md tokens, flag any hardcoded color or off-scale spacing as an error, and add an npm lint script."

Then test the gate the way you'd test any safety net: plant a deliberate violation. Paste a component with a raw hex value and an off-scale margin, run the linter, and confirm it turns red. If a broken rule passes the check, your check is checking the wrong thing.

Finally, run the judgment layer: "Review this diff against DESIGN.md and flag any drift the linter can't catch, like the wrong component used in the wrong place." Read its answer critically. Find one thing it got wrong or missed, because it will.

Exercises

  • Find one repeated chunk of UI and turn it into a reusable component with typed props.
  • Register that component and its props in DESIGN.md.
  • Set up a lint check that flags a hardcoded color, and add an npm run lint script.
  • Plant a deliberate violation and confirm the linter catches it. If it passes, fix the rule.
  • Run a Claude-assisted design review on a change and find one thing it got wrong or missed.
  • Wire your prototype to a local JSON file of realistic sample content.

You've got it when…

You build a second component and it matches the first without re-explaining anything, a hardcoded value fails your lint check automatically, and you can run a Claude-assisted review while telling a real flag from a false one.

Module 04

Making It Move

state and interaction, without the jargon

Why it matters

What makes a prototype feel alive instead of like a slideshow is what happens when you click something. A tab switches, a modal opens, a toggle flips. That is state: the screen remembering something and changing in response. Once you add that, your prototype stops being a fancy picture and starts answering the questions you actually built it to answer.

Concepts

State is what the screen remembers right now: whether the menu is open, which tab is selected, what the user typed. An event is what the user did: a click, a keystroke, a hover. The loop is straightforward: an event changes the state, and the changed state re-draws the screen. Once you see it, interaction stops feeling complicated.

TypeScript
import { useState } from 'react';

function Menu() {
  // "open" is the state. "setOpen" changes it.
  const [open, setOpen] = useState(false);

  return (
    <div>
      // the click event flips the state
      <button onClick={() => setOpen(!open)}>Menu</button>
      {open && <nav>...</nav>}
    </div>
  );
}

The same handful of patterns covers most prototypes. Toggles, tabs, modals, and form inputs are the workhorses. Learn to recognize them and you'll see that most interaction is a variation on "something is open or closed" and "something is selected." You rarely need anything exotic to make a prototype convincing.

State

What the screen remembers at this moment.

Event

What the user did: click, type, hover.

Toggle

A state that flips between two values.

Controlled input

A form field whose value lives in state.

Build with Claude Code

Describe the behavior, then review the logic. Don't just check that it works on the happy path. Prompt: "Make this tab bar switch panels when clicked, following DESIGN.md. Then walk me through the state: what's stored, what changes it, and what happens on the first render before anyone clicks." State bugs hide in the cases you didn't click: what the screen shows before any selection, what happens if two things try to be open at once. The build looking right is not proof the logic is right.

Exercises

  • Add one real interaction to your screen: a toggle, tabs, or a modal.
  • Have Claude explain what's stored in state and what changes it, in plain English.
  • Check the first-render state: what does the screen show before any interaction?
  • Break the behavior on purpose, then describe to Claude what should happen instead and fix it.

You've got it when…

You can describe an interaction in plain words, get it built following your design law, and verify that the state logic matches the intended behavior, including the cases you didn't click.

Module 05

Sharing It So People Can Click It

from your machine to a link you can send

Why it matters

A prototype nobody can open is a private sketch. The entire point of building something clickable is to get it in front of people and watch them use it. A live link does what no screen-share or screenshot can: it lets someone poke at your work on their own, in their own time, and tell you the truth about where it breaks down.

Concepts

Deploying means putting your project somewhere with a public URL. On your machine, your prototype runs on a local address only you can reach. Deploying copies it to a host that serves it to anyone with the link. For a Vite project, this is close to one command: services like Vercel and Netlify detect your setup, build it, and hand you a URL.

Terminal
# Build the production version, then deploy
npm run build
npx vercel deploy

# You get back a shareable URL:
# https://your-prototype.vercel.app

Know the difference between a preview link and a product. A deployed prototype is fast to share and perfect for feedback, but it's still running on fake data with no accounts and no hardening. That's fine; it's exactly what a prototype should be. Just don't let a slick URL trick anyone, including you, into thinking it's ready for real users.

Local

Runs only on your machine, at an address like localhost.

Deploy

Copy your project to a host that serves it publicly.

Preview link

A shareable URL of your prototype. Great for feedback.

Build

The optimized version of your project made for hosting.

Build with Claude Code

Let Claude handle the mechanics and explain the result. Prompt: "Deploy this Vite prototype to a shareable URL and tell me, in plain terms, what just happened and what the link can and can't do." The explanation matters: you want to understand what you're sending before you send it. When the link comes back looking consistent across every screen, that's your DESIGN.md and your lint check doing exactly the job you set them up to do.

Exercises

  • Deploy your prototype to a live URL.
  • Open the link on your phone and click through every flow you built.
  • Send it to one person and watch or listen as they use it without your help.
  • Write down the first place they hesitated. That's your most valuable finding.

You've got it when…

You have a live URL you can text to someone, it looks consistent across every screen, and you've watched at least one real person use it.

Capstone

Prototype One Real Screen From Your Own Work

brief to live link, with rules that hold

The brief

Carry one screen the full distance

Pick a screen from a project you actually care about: a portfolio piece, a Klarita output, a client idea, something with stakes. Take it the entire way: write its brief, set up your design law, scaffold it, componentize it under a lint check, make it interactive, fill it with convincing data, and deploy it to a link you can share. The project ships with its DESIGN.md and a working lint check, as part of the deliverable.

The process:

  1. Choose your screen and write its brief across structure, hierarchy, states, and behavior.
  2. Write a DESIGN.md for it and a CLAUDE.md that points to it.
  3. Scaffold the screen from your brief plus your design law.
  4. Componentize the repeated parts, registering each in DESIGN.md.
  5. Set up a lint check that enforces your tokens, and prove it catches a planted violation.
  6. Add the interactions that make the screen answer its real question.
  7. Wire in realistic data from a local JSON file.
  8. Deploy to a live URL and share it with one person.

You're done when you can hand someone a working link, and when you build a second screen for the same project later, it still matches the first without you re-explaining a single rule. Rigor written down early is what lets you move fast and stay coherent.

Ref

Prototyping Vocabulary Cheat Sheet

every term in plain English, with the design analogy where one fits
TermWhat it means
mockupA static picture of a screen. Looks right, does nothing.
prototypeA clickable, living version of a screen. Real components, real interaction, fake data.
driftWhen a design slowly loses consistency as it grows: stray colors, wandering spacing, forking components.
ReactA library for building UIs out of reusable components. The framework this course uses.
ViteThe tool that runs your project locally and builds it for hosting. Fast to start.
TypeScriptJavaScript with types. The types act as guardrails that catch mistakes early.
componentA reusable piece of UI you define once and place many times. Like a Figma component that runs.
propAn input that configures a component. The knobs you can turn on it.
compositionBuilding bigger UI by nesting components, like nesting frames.
stateWhat a screen remembers right now: open or closed, which tab, what was typed.
eventWhat the user did: a click, a keystroke, a hover.
CLAUDE.mdYour project's operating manual, read automatically each session. Holds stack and conventions.
DESIGN.mdYour design law: tokens, scales, component rules, and a do-not list. The source of truth for how things look.
design tokenA named design value, like color-accent, used everywhere instead of a raw hex code.
persistent contextRules stored in a file Claude reads every session, so you don't re-explain them and it stops guessing.
linterA tool that reads your code and flags style-rule violations. A spell-checker for consistency.
lint ruleA single check the linter enforces, like "no hardcoded colors."
three-layer defenseDesign law sets rules, the linter proves them mechanically, Claude review catches judgment-level drift. Trusted in that order.
mock dataRealistic sample content, kept in a local file, that makes a prototype feel real without a backend.
deployCopy your project to a host that serves it at a public URL.
preview linkA shareable URL of your deployed prototype. Great for feedback, not a finished product.
buildThe optimized version of your project, made for hosting.