{"course":{"slug":"building-apps-with-ai","title":"Building Apps with AI","url":"https://addaly.com/learn/building-apps-with-ai","level":"beginner","track":"build"},"lesson":{"slug":"describing-what-you-want","title":"Describing what you want","url":"https://addaly.com/learn/building-apps-with-ai/describing-what-you-want","position":10,"of":87,"minutes":8,"answer":"Describe what must be true and what happens when it fails; the happy path writes itself.","keyIdea":"Describe what must be true and what happens when it fails; the happy path writes itself."},"body":{"format":"markdown","text":"## The model cannot read your mind, and it will not say so\n\nAsk for \"a booking app for my salon\" and you will get a booking app. It will have appointments, times, maybe a calendar. It will also have invented answers to about forty questions you never asked, because it had to pick something: whether two people can book the same slot, what happens at closing time, whether a customer can cancel, what a phone number looks like.\n\nThose invented answers are the bugs you will spend next week chasing. The prompt is where you prevent them.\n\n## A specification has four parts\n\nWhen you describe a feature, cover these:\n\n**Things**: what exists, and what each one holds. \"A booking has a customer name, a phone number, a stylist, a start time and a duration in minutes.\"\n\n**Actions**: who does what. \"A customer creates a booking. A stylist cancels one. Nobody edits a booking once it has started.\"\n\n**Rules**: the constraints that make it yours. \"Two bookings cannot overlap for the same stylist. Bookings only between 09:00 and 19:00. Maximum 30 days ahead.\"\n\n**Failures**: this is the one people skip, and it is worth more than the other three combined. \"If the slot was taken while they were filling the form, show the message 'That time just went. Here are the next three openings.' and do not lose what they typed.\"\n\nMost AI-written bugs live in the failure paths, because nobody described them, so the model wrote the happy path and left the rest silent.\n\n## Adjectives are not requirements\n\n```\nBad:  Build it production-ready, secure and scalable.\nGood: Only the logged-in user can see their own bookings.\n      Check that on the server, not in the browser.\n      A page must load in under two seconds on a phone.\n```\n\n\"Make it secure\" produces the appearance of security: a comment saying `// validate input`, a variable called `sanitized`. Say what must be true and where it must be checked, and you get something you can verify.\n\n> Figure: The four parts of a specification. Layers, top to bottom: Things: what exists and what each one holds (name, phone, stylist, start time, duration in minutes); Actions: who does what (a customer creates, a stylist cancels, nobody edits); Rules: the constraints that make it yours (no overlap for one stylist, 09:00 to 19:00, 30 days ahead); Failures: what happens when a rule is broken (the message, and not losing what they typed). The first three are what people write. The fourth is where almost every AI-written bug lives, because nobody described it and the model wrote the happy path in silence.\n\n## Small steps beat long prompts\n\nThere is a widespread belief that the trick is writing one enormous, perfect prompt. It is not. A 900-word prompt produces 900 words of code you have not read, in files you did not know existed, and when something is wrong you cannot tell which part.\n\nBuild in slices you can check in under two minutes:\n\n1. \"Make a page at /book that shows a form: name, phone, stylist dropdown, date, time. No saving yet. Just the form.\"\n2. Open it. Does it look right on your phone?\n3. \"Now save a submitted form to the database. Show the saved booking on screen afterwards.\"\n4. Submit one. Look in the database.\n5. \"Now reject a booking that overlaps an existing one for the same stylist, with this message.\"\n6. Try to make a double booking on purpose.\n\nEach step is small enough that when it breaks you know exactly what broke it.\n\n## Decide the stack once, then repeat it\n\nIf you never state your tools, the model picks fresh each time, and by Thursday you have three ways of talking to the database. Write your stack down once and paste it into every session, or put it in the file your tool reads automatically: `.cursorrules`, `CLAUDE.md`, `AGENTS.md`, depending on the tool.\n\n```\nNext.js with the app router. TypeScript. Postgres via Drizzle.\nTailwind for styling. No new dependencies without asking me first.\nEvery database query goes in lib/queries.ts.\n```\n\nThat last line matters more than it looks. Without it, database calls end up scattered across twenty files and nobody, including you, can answer the question \"where does this data come from?\"\n\n## Show, do not only tell\n\nThe strongest thing you can hand a model is an example of what you already have. \"Add a cancel button that matches the edit button in components/BookingRow.tsx\" gets you consistency for free. Screenshots work too: for layout, a screenshot with two arrows drawn on it beats three paragraphs of description.\n\n## One question to ask before you send\n\nRead your prompt and ask: if a competent stranger built exactly this and it was wrong, what would they have had to guess?\n\nAnswer that, and send."},"check":{"question":"Two people ask for the same feature: a form where users join a waiting list with their email. One gets code that works for months, the other gets code that breaks within a week. Which difference in the request most likely explains it?","options":[{"text":"The first person named the exact library and version to use for form handling.","correct":false,"tempting":"Confuses precision about tools with precision about behavior: the library choice rarely determines whether the feature is correct."},{"text":"The first person said what should happen when the email is blank, malformed, or already on the list.","correct":true},{"text":"The first person wrote a much longer and more detailed request, giving the model more to work with.","correct":false,"tempting":"Treats length as a proxy for clarity, when long prompts often add restatement rather than new constraints."},{"text":"The first person specified that the code should be production-ready, secure and well tested.","correct":false,"tempting":"Reads adjectives as requirements, when they generate the appearance of quality rather than a checkable condition."}]},"prev":{"slug":"autonomy-and-where-to-keep-your-hand","title":"Autonomy, and where to keep your hand","url":"https://addaly.com/learn/building-apps-with-ai/autonomy-and-where-to-keep-your-hand"},"next":{"slug":"the-data-model-before-the-screens","title":"The data model comes before the screens","url":"https://addaly.com/learn/building-apps-with-ai/the-data-model-before-the-screens"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'Describing what you want', in Building Apps with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-apps-with-ai/describing-what-you-want (Accessed: 31 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"Describing what you want","courseTitle":"Building Apps with AI","module":{"index":2,"slug":"saying-what-you-want","title":"Saying what you want, precisely enough"},"answer":null,"keyIdea":"Describe what must be true and what happens when it fails; the happy path writes itself.","hero":{"kind":"figure","figure":{"t":"figure","label":"Figure 2.1","figure":{"type":"stack","title":"The four parts of a specification","layers":[{"label":"Things: what exists and what each one holds","detail":"name, phone, stylist, start time, duration in minutes"},{"label":"Actions: who does what","detail":"a customer creates, a stylist cancels, nobody edits"},{"label":"Rules: the constraints that make it yours","detail":"no overlap for one stylist, 09:00 to 19:00, 30 days ahead"},{"label":"Failures: what happens when a rule is broken","detail":"the message, and not losing what they typed"}],"caption":"The first three are what people write. The fourth is where almost every AI-written bug lives, because nobody described it and the model wrote the happy path in silence."},"alt":"Figure: The four parts of a specification. Layers, top to bottom: Things: what exists and what each one holds (name, phone, stylist, start time, duration in minutes); Actions: who does what (a customer creates, a stylist cancels, nobody edits); Rules: the constraints that make it yours (no overlap for one stylist, 09:00 to 19:00, 30 days ahead); Failures: what happens when a rule is broken (the message, and not losing what they typed). The first three are what people write. The fourth is where almost every AI-written bug lives, because nobody described it and the model wrote the happy path in silence."}},"blocks":[{"t":"h2","id":"the-model-cannot-read-your-mind-and-it-will-not-say-so","runs":[{"text":"The model cannot read your mind, and it will not say so"}]},{"t":"p","runs":[{"text":"Ask for “a booking app for my salon” and you will get a booking app. It will have appointments, times, maybe a calendar. It will also have invented answers to about forty questions you never asked, because it had to pick something: whether two people can book the same slot, what happens at closing time, whether a customer can cancel, what a phone number looks like."}]},{"t":"p","runs":[{"text":"Those invented answers are the bugs you will spend next week chasing. The prompt is where you prevent them."}]},{"t":"h2","id":"a-specification-has-four-parts","runs":[{"text":"A specification has four parts"}]},{"t":"p","runs":[{"text":"When you describe a feature, cover these:"}]},{"t":"p","runs":[{"text":"Things","b":true},{"text":": what exists, and what each one holds. “A booking has a customer name, a phone number, a stylist, a start time and a duration in minutes.”"}]},{"t":"p","runs":[{"text":"Actions","b":true},{"text":": who does what. “A customer creates a booking. A stylist cancels one. Nobody edits a booking once it has started.”"}]},{"t":"p","runs":[{"text":"Rules","b":true},{"text":": the constraints that make it yours. “Two bookings cannot overlap for the same stylist. Bookings only between 09:00 and 19:00. Maximum 30 days ahead.”"}]},{"t":"p","runs":[{"text":"Failures","b":true},{"text":": this is the one people skip, and it is worth more than the other three combined. “If the slot was taken while they were filling the form, show the message ‘That time just went. Here are the next three openings.’ and do not lose what they typed.”"}]},{"t":"p","runs":[{"text":"Most AI-written bugs live in the failure paths, because nobody described them, so the model wrote the happy path and left the rest silent."}]},{"t":"h2","id":"adjectives-are-not-requirements","runs":[{"text":"Adjectives are not requirements"}]},{"t":"code","lang":"","label":"Text","text":"Bad:  Build it production-ready, secure and scalable.\nGood: Only the logged-in user can see their own bookings.\n      Check that on the server, not in the browser.\n      A page must load in under two seconds on a phone."},{"t":"p","runs":[{"text":"“Make it secure” produces the appearance of security: a comment saying "},{"text":"// validate input","code":true},{"text":", a variable called "},{"text":"sanitized","code":true},{"text":". Say what must be true and where it must be checked, and you get something you can verify."}]},{"t":"h2","id":"small-steps-beat-long-prompts","runs":[{"text":"Small steps beat long prompts"}]},{"t":"p","runs":[{"text":"There is a widespread belief that the trick is writing one enormous, perfect prompt. It is not. A 900-word prompt produces 900 words of code you have not read, in files you did not know existed, and when something is wrong you cannot tell which part."}]},{"t":"p","runs":[{"text":"Build in slices you can check in under two minutes:"}]},{"t":"ol","start":1,"items":[[{"text":"“Make a page at /book that shows a form: name, phone, stylist dropdown, date, time. No saving yet. Just the form.”"}],[{"text":"Open it. Does it look right on your phone?"}],[{"text":"“Now save a submitted form to the database. Show the saved booking on screen afterwards.”"}],[{"text":"Submit one. Look in the database."}],[{"text":"“Now reject a booking that overlaps an existing one for the same stylist, with this message.”"}],[{"text":"Try to make a double booking on purpose."}]]},{"t":"p","runs":[{"text":"Each step is small enough that when it breaks you know exactly what broke it."}]},{"t":"h2","id":"decide-the-stack-once-then-repeat-it","runs":[{"text":"Decide the stack once, then repeat it"}]},{"t":"p","runs":[{"text":"If you never state your tools, the model picks fresh each time, and by Thursday you have three ways of talking to the database. Write your stack down once and paste it into every session, or put it in the file your tool reads automatically: "},{"text":".cursorrules","code":true},{"text":", "},{"text":"CLAUDE.md","code":true},{"text":", "},{"text":"AGENTS.md","code":true},{"text":", depending on the tool."}]},{"t":"code","lang":"","label":"Text","text":"Next.js with the app router. TypeScript. Postgres via Drizzle.\nTailwind for styling. No new dependencies without asking me first.\nEvery database query goes in lib/queries.ts."},{"t":"p","runs":[{"text":"That last line matters more than it looks. Without it, database calls end up scattered across twenty files and nobody, including you, can answer the question “where does this data come from?”"}]},{"t":"h2","id":"show-do-not-only-tell","runs":[{"text":"Show, do not only tell"}]},{"t":"p","runs":[{"text":"The strongest thing you can hand a model is an example of what you already have. “Add a cancel button that matches the edit button in components/BookingRow.tsx” gets you consistency for free. Screenshots work too: for layout, a screenshot with two arrows drawn on it beats three paragraphs of description."}]},{"t":"h2","id":"one-question-to-ask-before-you-send","runs":[{"text":"One question to ask before you send"}]},{"t":"p","runs":[{"text":"Read your prompt and ask: if a competent stranger built exactly this and it was wrong, what would they have had to guess?"}]},{"t":"p","runs":[{"text":"Answer that, and send."}]}],"check":{"question":[{"text":"Two people ask for the same feature: a form where users join a waiting list with their email. One gets code that works for months, the other gets code that breaks within a week. Which difference in the request most likely explains it?"}],"options":[{"text":[{"text":"The first person named the exact library and version to use for form handling."}],"correct":false,"tempting":[{"text":"Confuses precision about tools with precision about behavior: the library choice rarely determines whether the feature is correct."}]},{"text":[{"text":"The first person said what should happen when the email is blank, malformed, or already on the list."}],"correct":true,"tempting":null},{"text":[{"text":"The first person wrote a much longer and more detailed request, giving the model more to work with."}],"correct":false,"tempting":[{"text":"Treats length as a proxy for clarity, when long prompts often add restatement rather than new constraints."}]},{"text":[{"text":"The first person specified that the code should be production-ready, secure and well tested."}],"correct":false,"tempting":[{"text":"Reads adjectives as requirements, when they generate the appearance of quality rather than a checkable condition."}]}],"order":[3,2,0,1],"why":null},"prev":{"slug":"autonomy-and-where-to-keep-your-hand","title":"Autonomy, and where to keep your hand","minutes":8},"next":{"slug":"the-data-model-before-the-screens","title":"The data model comes before the screens","minutes":9}}}