Skip to content
Ship Like Crazy
Map›Part II · How software fits together🪔 Day 4 / 30⏱ ~70 minFree

Chapter 3. The Dining Room

What a UI is: websites, web apps, mobile and watch

Act II · Opening the Doors · with Pixel

Chapter title card with the chapter's host character and the day of the countdown.

🎬 Scene🪔 Day 4 / 30

The grey button

Day 4, mid-morning. Meera's Corner smells of cardamom and steamed milk. Pixel, the design student who works weekend shifts, leans over Jo's shoulder at the corner table and looks at the live menu page for exactly two seconds.

Pixel
Let me guess. Purple gradient, rounded cards, a little sparkle icon, and a grey "Learn more" button nobody will ever press.
Jo
It's orange, actually.
Pixel
Orange gradient. Rounded cards. Sparkle icon.

Jo scrolls. There is, in fact, a sparkle icon.

Sous
I think it looks very modern, chef!
Pixel
It looks like every app an AI made this year. If it looks like everything else, nobody remembers it.

Meera Aunty sets down two cuttings and pulls up a stool.

Meera Aunty
I don't care if it's modern. Rohit stands in my queue every morning, phone in one hand, bag in the other. Can he order with his thumb before he reaches the counter?
Pixel
Now that's a design brief.

Pixel flips over a paper napkin and draws four boxes in a row: Menu → Item → Cart → Pay.

Pixel
This is the dining room. Everything the customer sees and touches. We design it for one thumb, on a cracked phone, in a queue. And then we ask what happens when it goes wrong.
Jo
Goes wrong how? It's a menu.
Pixel
Oh, Jo. Everything goes wrong in the dining room.

Yesterday you put a page on the internet. Today you turn it into something people can use: the user interface, the part of software you can see and touch. This chapter is about what a UI is made of, the different places a UI can live, and one rule about the dining room that every app-builder has to learn.

🎯 By the end of this chapter you can…
  • Name the parts of any screen: layout, components, states and navigation
  • Choose between a website, web app, mobile app, desktop app or watch app, and explain why a web app comes first
  • Use five design basics to make AI-built screens look intentional, not generic
  • Build QueueLess's menu and cart with every state handled
  • Explain why anything in the browser can be changed by the user

What a UI actually is

A UIUI (user interface)Everything a person sees and taps in an app: screens, menus, buttons and forms. (user interface) is everything between a person and the software: the screens, buttons, text, colours, sounds and even the little vibration when you tap "Pay". Some people say UX (user experience) too. UI is what it looks like; UX is what it's like to use. Good UX is Rohit ordering one-handed without thinking.

The anatomy of a screen

Every screen you've ever used, from WhatsApp to your bank, is made of the same four things. Once you can name them, you can describe any screen to Sous precisely.

Layout

LayoutLayoutWhere things sit on a screen: header, content, sidebars, a bar fixed to the bottom. is where things sit. A header at the top, a list in the middle, a button stuck to the bottom. On a phone, layouts are mostly one column, stacked. On a laptop, you might have a sidebar and two columns.

Describe layouts by region: "A sticky header with the café name. A scrolling list of menu items. A cart bar fixed to the bottom of the screen."

Components

A componentComponentA reusable building block of a UI, such as a button, card or drawer, built once and used many times. is a reusable building block. You build a "menu item card" once and use it twenty times. The common ones have names everyone, including Sous, understands:

ComponentWhat it isIn QueueLess
ButtonSomething you tap to do an action"Add", "Checkout", "Pay ₹130"
InputA box you type intoName, phone number, "Any special requests?"
CardA box grouping related thingsOne menu item: name, price, photo, Add button
Modal (dialog)A box that pops over the page and needs an answer"Remove bun maska from your cart?"
Drawer (sheet)A panel that slides in from an edgeThe cart, sliding up from the bottom
BadgeA small label or count"3" on the cart icon; "Bestseller"
ToastA brief message that appears and fades"Masala chai added"

Using these exact names in prompts gets you far better results than "a box thing that pops up".

States

This is the part almost every AI-built app gets wrong. A screen isn't one picture. It's several, depending on what's going on. Every screen that shows data needs at least four statesUI statesThe different versions of a screen depending on what's happening: empty, loading, error and success.:

  • Empty: nothing here yet. "Your cart is empty. The masala chai is very good."
  • Loading: waiting for data. A spinner, or grey placeholder shapes called skeletons.
  • Error: something failed. Say what happened and what to do: "Couldn't load the menu. Check your connection and try again." Plus a Try again button.
  • Success: the happy path, with real content. Plus confirmations: "Order placed! Pick up at the counter in about 5 minutes."

Sous builds the success state beautifully, because that's what you described. Ask for the other three by name, or you won't get them.

🚦 Why states matter so much

Picture Rohit in the queue. His phone is on weak 4G. He taps "Menu" and sees… a blank white screen. Is it broken? Loading? Did he do something wrong?

He gives up and orders at the counter. A loading state would have kept him. An error state with "Try again" would have rescued him. The happy path is maybe a quarter of the design work.

Navigation

NavigationNavigationHow people move between screens: tabs, links, back buttons and menus. is how people move between screens: tabs at the bottom, a back arrow, a menu icon, links. Good navigation answers three questions at a glance: where am I, where can I go, how do I get back?

For QueueLess, Pixel's rule is simple: a customer should reach "Pay" in four taps or fewer from opening the app.

🎮 Play

Spot the Missing State

Real apps aren't just the happy path. Show me you can spot what's missing.

Find the screens missing an empty, loading or error state.

  • ▸ Each screen comes with a situation.
  • ▸ Pick which state the screen is missing.
  • ▸ A timer runs per screen.

The surfaces: where a UI can live

"Build me an app" can mean very different things. Here are the main surfacesSurfaceA place where a UI lives: a website, web app, mobile app, desktop app, watch or chat. a UI can live on, and when to pick each.

SurfaceWhat it isBuilt withPick it when
Website / landing pageMostly pages to read: info, marketing, a menuHTML, Next.js, Webflow, FramerYou need to explain, attract and be found on Google
Web app / SaaSAn app in the browser: log in, do things, save dataNext.js, ReactYou want something people use, on any device, with one codebase. Most products start here
PWAA web app that can be "installed" to the home screen and work a bit offlineA web app plus a manifest and service workerYou want app-like feel without app stores
Native mobileAn app from the App Store or Play StoreSwift (iPhone) or Kotlin (Android); or one codebase with React Native/Expo or FlutterYou need the camera, push notifications, offline use or deep phone features, and you have users who want it
Desktop appAn app you install on a laptopElectron or Tauri (web tech in a desktop shell)People live in it all day, or it needs local files
Watch / wearableGlanceable screens on a wristSwiftUI on watchOS; Jetpack Compose for Wear OSAlmost always a companion to a phone app: "Your chai is ready" on the wrist
Chat / agent UIYour product inside Slack, WhatsApp, or an AI assistantBots, APIs, MCP serversYour users already live in that chat, and the task is a quick ask-and-answer

A few notes on the less obvious ones:

  • A PWAPWA (progressive web app)A web app that can be added to a phone's home screen and open full-screen like an app, without an app store. (progressive web app) sits halfway between a website and an app. You visit it in the browser, tap "Add to Home Screen", and it opens full-screen with its own icon. For a café, that's often enough.
  • A native appNative appAn app installed from the App Store or Play Store, built for the phone platform (Swift, Kotlin) or with cross-platform tools like Expo or Flutter. is built specifically for one phone platform. Expo (built on React Native) and Flutter let one codebase run on both iPhone and Android, and AI tools handle Expo well. Store review, developer fees and update delays come with the territory.
  • Watch apps are tiny. A watch screen is about the size of a postage stamp. You show one fact and one or two buttons. Nobody browses a menu on their wrist.
  • Chat UIs are growing fast. Some products now live mainly inside an AI assistant, as a connector that does one job well.

Why a web app is the right first product

For QueueLess, and probably for your first product, the answer is a web app, built phone-first. Here's why:

  • One codebase, every device. It works on iPhones, Android phones, laptops and tablets the day you ship it.
  • No app store. You deploy in a minute with Vercel. No review, no waiting, no fees per download.
  • Instant updates. Fix a bug, push, and every customer has the fix on their next visit.
  • Zero install friction. Rohit scans a QR code at the counter and he's ordering. Asking a stranger to download an app loses most of them.
  • AI is great at it. Next.js, Tailwind and React are the most common patterns in Sous's training. Fewer mistakes, faster fixes.

Later, if customers ask for push notifications or a home-screen icon, you can make it a PWA. If thousands of regulars want a proper app, you can build one with Expo, reusing your server and database. You don't have to decide that today.

📰 Real-world story
A plain browser game that went viral

In February 2025, indie maker Pieter Levels built fly.pieter.com, a simple multiplayer flight simulator that runs in the browser, with AI's help in about three hours. No app store, no download, just a link. He reported it reached $1 million in annual revenue within 17 days, mostly from in-game ads, by his own account.

The graphics were blocky. The surface was "just" a web page. What mattered was a fun idea, shared loudly, that anyone could try in one tap.

Source: levels.io ↗

Design basics for non-designers

You don't need to become a designer. You need five basics, so you can tell Sous what's wrong with a screen and how to fix it.

1. Hierarchy

HierarchyVisual hierarchyArranging a screen so the most important things are the most noticeable, using size, weight, colour and position. means the most important thing is the most noticeable. On a menu, that's item names and prices, then the Add button. Not the logo. Not the sparkle icon.

Squint at your screen until it's blurry. What stands out? If it's not the thing that matters most, change size, weight or colour until it is.

2. Spacing

Cramped screens feel cheap; generous spacing feels calm and expensive. Use a consistent scale, such as 4, 8, 12, 16, 24, 32 pixels, rather than random gaps. Tailwind does this for you: p-2 is 8px, p-4 is 16px, p-6 is 24px.

Related things sit closer together. The item name and its price are close; two different menu items have more space between them.

3. Type scale

Pick a few text sizes and stick to them: one for headings, one for item names, one for body text, one for small print. Too many sizes look messy. On phones, body text should be at least 16px, so nobody has to pinch-zoom. Use one font family, two at most.

4. Colour and contrast

Use one main brand colour (Meera's deep chai orange), one or two neutrals, and colours with a meaning: green for success, red for errors. Use your brand colour for the main action, like Add and Pay, so people know where to tap.

ContrastContrastHow much text stands out from its background. Normal text should have a contrast ratio of at least 4.5:1 to be readable. is how much text stands out from its background. Pale grey on white looks stylish and is unreadable in sunlight. The accessibility guideline is a contrast ratio of at least 4.5:1 for normal text. Browser DevTools and free online checkers will tell you the ratio.

That's part of accessibilityAccessibilityMaking software usable by everyone, including people with low vision, colour blindness, limited movement or a screen reader.: making your app usable by everyone, including people with low vision, colour blindness, shaky hands or a screen reader. Big tap targets (about 44px), real labels on inputs, and not using colour alone to show meaning go a long way. Mrs. Kapoor, seventy-eight, a regular since 1998, will thank you.

5. Phone-first, responsive design

Responsive designResponsive designLayouts that adapt to the screen size, usually designed for phones first and then spread out for larger screens. means the layout adapts to the screen size. Design for the smallest screen first, then let it spread out on bigger ones. It's much easier than squeezing a laptop design onto a phone.

Most of Meera's customers will use QueueLess on a phone, in a queue, with one thumb. So: big buttons in the bottom half of the screen, where thumbs reach, and nothing important hidden behind hover effects, because phones can't hover.

Why AI apps all look the same

Sous learned from millions of websites, so when you say "make it look nice", it gives you the average of all of them: purple-to-blue gradients, rounded cards, a sparkle icon, grey text. Pixel calls it "the AI look". It's not ugly. It's just forgettable.

The fix is a design systemDesign systemA written set of design decisions (colours, fonts, spacing, components) that keeps every screen consistent.: a short set of decisions written down once. Your exact colours, fonts, spacing scale, corner radius and how buttons look. Then every prompt says "follow our design system", and every screen looks like it belongs to the same café. You'll build one properly in Chapter 12. For now, giving Sous three specific choices ("deep orange #C2410C, cream background, chunky rounded buttons") already beats "make it nice".

Pixel
Adjectives get you averages. Decisions get you a brand.

The golden rule of the dining room

This is the most important idea in the chapter, and one of the most important in the book.

Anything in the UI can be read and changed by the user.

When someone opens your web app, their browser downloads your page's code (the HTML, the CSS and the JavaScript) onto their device. It's theirs now. Every browser comes with DevToolsDevToolsDeveloper tools built into every browser that show a page's code and let you inspect and edit your own copy of it live., a built-in panel for developers that lets anyone see that code and edit it live, on their own screen.

The page in your browser is a copy on your device. You can change your copy, and the page believes you.

On a phone ordering screen, a cursor edits the price of masala chai from 40 to 0 rupees in browser developer tools and places the order. Meera is shocked; a stamp reads 'Trusted the browser'.

That means a customer can, on their own phone or laptop:

  • Read everything you sent: text, hidden elements, data, and any keys you put in the code
  • Change prices shown on the page
  • Reveal hidden buttons (an "Admin" button you only hid with CSS)
  • Flip flags like isAdmin = true or isPremium = true in the page's code
  • Change what the page sends to your server when they tap "Pay"

This isn't hacking in the movie sense. It's how browsers work, and it's been true since the 1990s. DevTools exist so developers can debug their own pages.

So the question isn't "can a customer change the price on their screen?" They always can. The question is: does your app believe them? If the page tells your server "one masala chai, ₹0" and your server says "OK!", that's a bug, and it's your bug.

⚠️ Vibe check: where AI gets this wrong
  • AI puts prices and totals in the browser. Sous will happily calculate the cart total in the page and send it to the server as "the amount to charge". The server must look up prices itself.
  • Hiding is not protecting. An "admin" button hidden with CSS, or a page with no link to it, is still reachable. Real protection happens on the server (Chapter 6).
  • Keys in front-end code are public. Anything Sous puts in a file that runs in the browser can be read by anyone. Secret keys belong on the server only (Chapter 4).
  • The AI look. Ask for specific colours, fonts and spacing, or you'll get the average of the internet.
  • Missing states. Ask for empty, loading and error states by name on every screen that loads data.
🎮 Play

Trust Nothing in the Browser

The browser is the customer's side of the counter. Let's see what that means for prices.

See why a price shown in the browser can't be trusted, then fix the checkout.

  • ▸ Look at the pretend shop's page and its checkout code.
  • ▸ Answer what a customer could change on their own device.
  • ▸ Choose where the price check belongs.

Building the dining room

Time to turn Pixel's napkin into real screens. You'll use claude.ai for thinking and sketching, and Claude Code in your queueless repo for building.

🛠️ Lab

Design and build the ordering screens

⏱ 75 min0/6
  1. Take screenshots of three ordering apps you like on your phone: a food delivery app, a coffee chain's app, anything with a menu and a cart. Open a new chat in your QueueLess project on claude.ai, attach the screenshots, and paste:

    💬
    Find the patterns in apps I like
    These are screenshots of three ordering apps I like. For each, describe the layout, the main components (buttons, cards, drawers, etc.) and how you get from the menu to paying.
    
    Then list the patterns all three share, and the one thing each does that the others don't.
    
    Finally, suggest which 3–4 patterns suit a small chai café whose customers order one-handed on a phone while standing in a queue.
    ✅ You should see: A breakdown of each app, a list of shared patterns (such as a sticky cart bar, big Add buttons, item photos, a bottom sheet for the cart) and a short recommendation.
  2. Draw the flow on paper: Menu → Item → Cart → Checkout. Four boxes, one per screen, with arrows. Inside each box, sketch roughly what's on it. Ten minutes, no rulers.

    Or ask Claude for a quick clickable mockup:

    💬
    Make a clickable mockup of the flow
    Make a clickable phone-sized mockup (as an artifact) of an ordering flow for Meera's Corner, a chai café: Menu → Item detail → Cart → Checkout.
    
    Use this real menu only: Masala chai ₹40, Cutting chai ₹25, Ginger chai ₹45, Bun maska ₹50, Veg sandwich ₹90.
    
    Design: deep chai orange (#C2410C) for main buttons, cream background, dark brown text, big rounded buttons in the bottom half of the screen. No gradients, no sparkle icons. Checkout can be fake; no real payments.
    ✅ You should see: A sketch or mockup you can tap through. Ask yourself: can Rohit get to Pay in four taps?
  3. In your terminal, go into the queueless folder, start npm run dev in one tab and claude in another. Commit first:

    git add -A
    git commit -m "Before menu and cart UI"
    

    Then ask Claude Code:

    💬
    Build the menu list and cart drawer
    In this Next.js app, build the ordering UI for Meera's Corner using shadcn/ui and Tailwind.
    
    1. Set up shadcn/ui if it isn't already, and add the Button, Card, Sheet and Badge components.
    2. Menu page: show the items from src/data/menu.ts as cards (name, price, an Add button). One column on phones.
    3. A cart bar fixed to the bottom showing item count and total, e.g. "2 items · ₹65 · View cart".
    4. Tapping it opens a Sheet (drawer) from the bottom listing cart items with + and – buttons and a Checkout button. Checkout can just show "Coming soon" for now.
    5. Keep the cart in React state for now (no database yet).
    
    Design: deep chai orange (#C2410C) for main buttons, cream background, dark brown text, 16px minimum body text, tap targets at least 44px.
    
    Show me your plan and the files you'll touch before writing code.

    Read the plan, approve it, and approve file changes as they come.

    ✅ You should see: At localhost:3000, a menu of five cards. Tapping Add updates the bottom bar. Tapping the bar slides up a cart drawer with + and – buttons.
    😵 Stuck?
    If the shadcn setup asks questions in the terminal, it's fine to accept the defaults. If something breaks, paste the whole error to Claude Code. If it all goes wrong, git restore . and try a smaller step.
  4. Commit what works, then ask for the missing states:

    💬
    Add every state to the cart and menu
    Add proper states to the menu and the cart drawer:
    - Empty cart: a friendly message ("Your cart is empty. The masala chai is very good.") and a button that closes the drawer.
    - Loading: skeleton cards while the menu loads. Simulate a 1.5 second delay for now so I can see it.
    - Error: if the menu fails to load, show "Couldn't load the menu. Check your connection and try again." with a Try again button. Add a temporary way for me to trigger it (a ?error=1 query parameter).
    - Success: a short toast when an item is added ("Masala chai added").
    
    Tell me how to see each state in the browser.
    ✅ You should see: You can see all four: an empty cart message, grey skeletons while loading, an error box at localhost:3000/?error=1, and a toast when adding.
  5. Commit and push to a branch, so Vercel makes a preview deployment:

    git checkout -b menu-ui
    git add -A
    git commit -m "Menu, cart drawer and states"
    git push -u origin menu-ui
    

    Open your project on vercel.com. Under Deployments, find the one for menu-ui and open its preview URL on your phone. Order a chai one-handed.

    ✅ You should see: The preview URL works on your phone. The cart bar sits within thumb reach, text is readable without zooming, and buttons are easy to hit. Note anything awkward and ask Claude Code to fix it.
    😵 Stuck?
    If the preview is behind a Vercel login, that's preview protection. Sign in with the same account on your phone, or check the project's deployment protection settings.
  6. Now let's see the golden rule for real, on your own app. On your laptop, open your localhost or preview page in Chrome or Edge.

    1. Right-click the price of Masala chai and choose Inspect. DevTools opens with that bit of HTML highlighted.
    2. Double-click the text ₹40 in the Elements panel, change it to ₹0, and press Enter.
    3. Look at the page.
    ✅ You should see: The page now shows Masala chai at ₹0. Nothing stopped you, and the page believes you. Refresh, and it's back to ₹40, because you only changed your own copy.

    Here's the uncomfortable bit. Right now, QueueLess calculates the cart total in the browser. If checkout trusted that total, a customer could pay whatever their page said. You're not taking payments yet, so nothing is at risk. Chapter 4 moves prices to the server, where customers can't touch them. Write that down as a to-do.

🧪 Same screen, two surfaces 15 min
  1. In claude.ai, ask: "Show me the QueueLess menu screen twice: once as a Next.js page with Tailwind, and once as an Expo (React Native) screen. Keep the design the same."
  2. Compare the code side by side. Notice div and button on the web versus View, Text and Pressable in Expo.
  3. Ask: "What would I need to ship the Expo version that I don't need for the web version?" (Hint: app store accounts, builds, review.)
  4. Decide for yourself why we're starting on the web.
💬
Escape the AI look
This screen looks like a generic AI-built app. Restyle it with these decisions only:
- Brand colour: deep chai orange #C2410C for main actions only
- Background: warm cream #FFF7ED; text: dark brown #431407
- Font: one family; headings bold, body 16px
- Corners: rounded-xl on cards and buttons
- No gradients, no sparkle or AI icons, no grey buttons

Check every text colour against its background meets a 4.5:1 contrast ratio and tell me any that don't.

What you've learned

  • A UI is the dining room: everything users see and touch. Every screen is layout, components, states and navigation.
  • Every screen that loads data needs empty, loading, error and success states. Ask for them by name.
  • UIs live on many surfaces: websites, web apps, PWAs, native mobile, desktop, watches and chat. Start with a phone-first web app.
  • Hierarchy, spacing, a type scale, contrast and phone-first layout make AI screens look intentional. A design system fixes the AI look.
  • Anything in the browser can be read and changed by the user. The browser shows; the server decides.
🎬 Scene🪔 Day 4 / 30

The ₹0 chai

Evening. The menu-and-cart preview has been on Meera's counter all afternoon on a little stand with a QR code, "for testing". Ananya, a college student and a regular, comes up to the counter grinning, holding out her phone.

Pixel
Ananya! You tried it? What did you think of the cart drawer?
Jo
Rohit ordered in three taps this morning. Three!

Ananya turns her phone around. On the screen: the QueueLess cart. 1 × Masala chai. Total: ₹0.

Meera Aunty
Zero?

Ananya shrugs. She's a computer science student. She opened DevTools on her own phone browser during a boring lecture, changed the number, and pressed checkout.

Sous
The practice checkout I added this afternoon accepted it, chef! It said "Order placed!" and sent the ticket to the kitchen tablet.
Jo
Why could she change the price?

Pixel looks at the ceiling. Dev Uncle, as if summoned, is already on the stairs. But it's Chef Ravi who leans out of the kitchen door, wiping his hands.

Chef Ravi
Because you let the dining room decide the bill. Customers order. The kitchen decides. Tomorrow, you come into my kitchen.
❓ Quiz

Checkpoint quiz

Question 1 of 6

Which four states should almost every data screen have?

🍽️
CHECKPOINT · CHAPTER 3

Badge: Front of House

Lab steps ticked
0
Games played
0 / 2
Quiz best
not yet
Next: Chapter 4 · Chef Ravi's Kitchen →
Sources

Figures are as reported by the linked sources (many are founder- or vendor-reported). Tools and prices change monthly.