What separates a prompt that works
Most advice about AI prompts is about wording. For agentic coding it is mostly about structure, and specifically about constraints.
Consider two ways of asking for the same thing.
Add a contact form to the site.
You will get a contact form. It may use a pattern that exists nowhere else in the codebase, validate only on the client, use a placeholder as a label, and hard-code an email address. None of that is the model being careless — you did not say otherwise, and every one of those choices is defensible in isolation.
Now the same request with the decisions made in advance:
Build a contact form. Fields: name (optional), email (required), message (required). Before writing anything, look at how forms are already built in this codebase and follow that pattern. Requirements: - Every control has a visible, programmatically associated label. A placeholder is not a label. - Correct input types and autocomplete attributes - Client-side validation for speed, server-side for truth - Errors in text, next to the field, saying how to fix the problem - Submit button disabled and labelled during submission - Keyboard operable throughout - Works without JavaScript if the platform allows it Tell me what happens to the data after submission, and confirm nothing sensitive is logged.
The second is longer, but almost none of the extra length is description. It is constraint — decisions moved from implicit to explicit. That is the entire technique.
This matters more with an agentic tool than with chat, because the agent will act on its assumptions rather than showing them to you first. The constraints are how you get a vote.
The six parts
Prompts that consistently produce usable output tend to contain the same six things. Not every prompt needs all six; the more consequential the task, the more of them you want.
| Part | What it does | What goes wrong without it |
|---|---|---|
| Context | What this project is and what already exists | Code that ignores your conventions |
| Objective | The specific outcome, not the general area | A plausible answer to a different question |
| Constraints | What must and must not happen | Reasonable-looking choices you did not want |
| Process | The order of work, and where to stop | A twelve-file diff you cannot review |
| Validation | How to prove it worked | "Done" meaning "I stopped writing" |
| Deliverables | What you want back and in what form | A wall of prose where you wanted a table |
The two that people most often leave out are Process and Validation, and they are the two that matter most. Process is what stops a task from becoming an unreviewable diff. Validation is what stops the model from being the sole judge of whether it succeeded.
Four additions that improve almost any prompt
Before the examples, four short instructions that work on nearly everything and cost one line each.
| Add this | Effect |
|---|---|
| "Cite the file and line for every finding." | Eliminates most plausible-sounding invention, because a fabricated claim has nowhere to point |
| "Tell me what you could not verify." | Surfaces blind spots that otherwise arrive as confident assertions |
| "Do not change anything yet — show me the plan first." | Prevents unwanted edits; pairs with plan mode |
| "If you are uncertain, say so rather than guessing." | Genuinely reduces confident errors on version-specific facts |
The first one is the highest-leverage sentence in this article. An audit that cites nothing is a list of things that sound like problems.
Repository discovery
Map an unfamiliar codebase
When: the first session in any repository you did not write, or have not touched in months.
Analyse this repository. Do not modify anything. Map: structure and the convention behind it; stack with versions read from the manifest and lockfile, not inferred from directory names; entry points for run, build, test and deploy; where data comes from; expected environment variables; the conventions actually in force; and what tests exist and whether they currently pass. Then tell me the three things I most need to understand before making a change, anything that looks unusual and whether it seems deliberate, and anything you are uncertain about. Cite file paths for every claim.
Why it works: "do not modify anything" makes the first session safe. "Read the manifest and lockfile" blocks a specific and common failure — inferring the stack from folder names. "Cite file paths" makes the whole thing checkable.
Verify: spot-check two or three cited paths. If any is wrong, the rest of the report is suspect and you should say so and re-run.
Find where the documentation lies
When: inheriting a project, before you trust its README.
Compare this project's documentation against what the code actually does. Check the README, any docs directory, and code comments. Look for: commands that no longer work — actually run them where it is safe; renamed or removed configuration options; described behaviour that has changed; documented files that no longer exist; and environment variables read by the code but missing from .env.example. List every discrepancy with both sources cited.
Why it works: "actually run them where it is safe" converts a reading exercise into a test. The gap between documentation and code is reliably where the bugs are.
Verify: run one of the commands it reported as broken and confirm it is.
Blast radius of a change
When: before touching anything shared.
I am considering changing [FILE or FUNCTION]. Find everything that depends on it, directly or indirectly: imports, call sites, tests, configuration references, and anything that depends on its current behaviour rather than just its signature. Tell me what would break, what would break silently, and what I should check that static analysis would not catch. Do not change anything.
Why it works: "what would break silently" is the part that matters. Anything a compiler catches you would have found anyway.
Verify: check the dynamic cases yourself — string-based lookups, config references, anything reached by route rather than import.
Planning and architecture
Plan before code
When: any change large enough that you would not want to read the diff cold.
Create an implementation plan for [FEATURE]. Break it into steps that are each independently reviewable and independently revertible. For each: what changes, which files, what "done" means, and how to verify it. Order by dependency — nothing before what it depends on. Also give me the risks, what could go wrong at each step, and the rollback. If any part of this is larger than it appears, say so now rather than halfway through. Do not implement anything. I want the plan first.
Why it works: "independently revertible" forces genuinely small steps. "If any part is larger than it appears" invites the model to flag scope it would otherwise quietly absorb.
Verify: check that no step depends on a later one, and that every step has a real verification rather than "confirm it works".
Compare approaches honestly
When: a decision that will be expensive to reverse.
I need to [GOAL]. Give me three genuinely different approaches. For each: how it works, what it costs, what it makes easy, what it makes hard, and what it forecloses. Then recommend one, and be explicit about what you are trading away to get it. Do not give me three variations of the same idea. If there is genuinely only one reasonable approach, say so and explain why the others fail.
Why it works: asking for the cost is the whole trick. Models default to advocacy; "what are you trading away" produces engineering.
Verify: if the three options are minor variants of each other, push back — the question was not answered.
Decide whether to build it at all
When: before planning a feature nobody has validated.
I am considering building [FEATURE]. Before planning it, help me decide whether to. Ask me: what problem it solves, who has that problem, how they solve it now, and what happens if we do not build it. Then tell me honestly: does this seem worth building? What is the simplest version that would tell us whether it is? What would you build instead? Push back if the answer is that this is not worth building. That is more useful to me than a plan.
Why it works: explicitly licensing a negative answer. Without that line you will get a plan, because you asked for one.
Verify: nothing to verify — but notice whether it actually pushed back. If everything gets approved, the permission was not read.
Frontend development
Build a component that matches the codebase
Build a [COMPONENT] component. Requirements: [WHAT IT DOES] Before writing anything, check whether something similar already exists in this codebase and follow its pattern. Regardless of the requirements above: - Semantic HTML — the element that carries the meaning, never a clickable div - Keyboard operable with a visible focus state - Every value from the design tokens; hard-code nothing that exists as a token - Handle the loading, empty, and error states - Responsive from 320px up - No new dependency without telling me what it costs and why the platform cannot do it Show me the plan before you write the code.
Why it works: "check whether something similar already exists" prevents the single most common form of AI-generated tech debt — a fourth implementation of something the codebase already has three of.
Verify: search for near-duplicates yourself. Tab through the component. Check that no literal colour or spacing value appears in the diff.
Make it work at 320px
Make [COMPONENT or PAGE] work correctly from 320px to wide desktop. Check at 320, 375, 390, 430, 768, 1024, and 1440. Requirements: no horizontal overflow at any width; text readable without zooming; tap targets at least 24x24 CSS px with adequate spacing; content reflows rather than shrinking; nothing depends on hover; no fixed pixel heights on anything containing text. Work mobile-first. Tell me what you changed and what compromises you made.
Why it works: naming the exact widths turns a vague instruction into a checklist. "What compromises you made" surfaces the trade-offs instead of hiding them.
Verify: measure it. In a browser console, document.documentElement.scrollWidth against clientWidth at 320px tells you the truth in one line. A common cause of failure here is that grid and flex children default to min-width: auto, so anything with intrinsically wide content cannot shrink — no linter reports it.
Add the states everyone forgets
Add loading, empty, and error states to [AREA]. For each: what the user sees, what they can do next, and how it is announced to assistive technology. Errors should explain what went wrong and how to fix it — no apologies, no vagueness. Empty states should tell the user how to get out of the empty state. Never leave a user staring at a blank region with no explanation.
Why it works: these three states are most of the difference between a demo and a product, and they are almost never in the original request.
Verify: force each state — throttle the network, empty the data, break the endpoint.
Backend and data
Create an endpoint that is not a liability
Create an endpoint for [PURPOSE]. Requirements: - Validate input against a schema at the boundary - Authorise on the server — check both authentication and whether this user may act on this specific resource - Correct status codes; a 200 with an error body is a bug - Consistent error shape, matching the rest of this API - Paginate if it returns a list, with a maximum page size - Never return more data than the caller needs — check what the response actually exposes - Parameterise every database query - No sensitive data in logs Follow the patterns already in this codebase. Show me the plan first.
Why it works: "whether this user may act on this specific resource" is the distinction between authentication and authorisation, and skipping it produces the most common serious vulnerability in web applications.
Verify: change an ID in the request and confirm you get a 403, not someone else's data.
Write a migration that cannot lose data
Write a migration to [CHANGE]. Rules: - Additive first. Never add and remove in one step. If this changes an existing column, split it: add, backfill in batches, switch reads, then drop in a later release. - Include a tested down migration - Assume it runs against a live system — no long table locks - Batch any backfill, with a pause between batches - Tell me the expected duration against realistic data volumes If this migration would lose data, stop and tell me before writing it.
Why it works: the additive-first rule prevents most production database incidents on its own. The final line is a circuit breaker.
Verify: run the down migration. An untested rollback is not a rollback.
Debugging
Find the cause, not a plausible fix
I am getting this error: [PASTE THE FULL ERROR AND STACK TRACE] It happens when: [WHEN] Find the cause before proposing a fix. Read the relevant code. Trace the path that produces this. Tell me what is actually happening, not what usually causes errors that look like this. If you cannot determine the cause from what you can see, tell me what information you need rather than guessing. Then propose a fix and explain why it addresses the cause rather than the symptom.
Why it works: "not what usually causes errors that look like this" blocks pattern-matching to a common cause that happens not to be yours. That single clause saves a lot of wasted fixes.
Verify: ask it to explain why the error stopped. If the explanation is vague, the fix probably masked a symptom.
It works locally and fails in production
[BEHAVIOUR] works locally and fails in production. Systematically compare the two environments: runtime and dependency versions; which environment variables are set and which are missing; whether production is actually running the same build; configuration differences; data differences, since production has real data; timing, since production is slower and race conditions surface there; and case sensitivity, since many local filesystems are case-insensitive and production is not. Tell me the most likely cause and how to confirm it before changing anything.
Why it works: it enumerates the actual difference space. The case-sensitivity item alone explains a surprising share of these.
Verify: confirm the hypothesis before deploying a fix built on it.
Reproduce it reliably
I cannot reliably reproduce [PROBLEM]. Help me build a reproduction. Based on the code, what conditions would produce this? What inputs, what state, what timing, what sequence? Give me the smallest set of steps most likely to trigger it, ordered by likelihood. If it depends on data, tell me what shape of data. If it depends on timing, tell me how to force the timing. Once we can reproduce it reliably, we can fix it. Until then we are guessing.
Why it works: it targets the actual blocker. Intermittent bugs are not hard to fix; they are hard to observe.
Verify: the reproduction should fail before the fix and pass after. If it does not fail beforehand, it is not a reproduction.
Refactoring
Refactor without changing behaviour
Refactor [FILE or FUNCTION] for clarity. Constraints: - Behaviour must be identical. Anything that changes behaviour is out of scope. - Do not change the public interface - Do not add features - Do not "improve" anything I did not ask about Before you start, tell me what tests currently cover this. If there are none, write them first so we can prove behaviour is unchanged. Show me the diff and explain what each change improves.
Why it works: "do not improve anything I did not ask about" is doing real work. Unrequested improvements widen the diff and make the review harder for no benefit.
Verify: tests pass before and after, and the diff contains nothing outside the stated scope.
Find dead code without deleting working code
Find dead code in this project: unused exports, unreferenced files, unreachable branches, commented-out blocks, feature flags for features that fully shipped, unused CSS, unused dependencies, and orphaned assets. For each, tell me how confident you are that it is genuinely unused and what would confirm it. Be careful with dynamic imports, string-based references, anything referenced from configuration, and anything reachable only from a route. Do not delete anything yet — false positives here delete working code. Give me the list with confidence levels.
Why it works: naming the false-positive sources is the difference between a useful list and an outage.
Verify: grep for each candidate by name before removing it.
SEO
Technical SEO audit with evidence
Perform a technical SEO audit of this project. Check: indexability (robots.txt, noindex, blocked resources); canonicalisation (self-referencing canonicals, www vs apex, trailing slashes); status codes and redirect chains; sitemap contents; metadata uniqueness; heading hierarchy; structured data validity; internal linking; and rendering without JavaScript. For every finding: the evidence — file and line, or the actual response. Rank by real impact. Do not report a missing nice-to-have as critical. Tell me what you could not check and why. Do not invent search volumes, difficulty scores, traffic estimates, or ranking positions. If you have not measured it, say "not measured".
Why it works: the last paragraph is essential. Ask an AI for SEO analysis without it and you will get confident, entirely fictional search volumes.
Verify: fetch two or three of the URLs it reports on and confirm the status codes and canonicals independently.
Check the sitemap by sampling it
Check this site's sitemap. Confirm it returns 200 with the correct content type and is valid XML. Then sample at least ten URLs from it and fetch each one. For each, report the actual status code and whether it is canonical and indexable. Flag any URL that redirects, returns anything other than 200, carries noindex, or is not canonical. Each of those is a finding. Also: are important pages missing? Is it generated automatically, or was it written by hand and now stale?
Why it works: "sample and fetch" turns an assumption into a measurement. Most sitemap problems are invisible until someone actually requests the URLs.
Verify: the sampled URLs and their status codes should be in the output. If they are not, it did not fetch them.
Accessibility
Keyboard review
Review this project for keyboard accessibility. Check: is every interactive element reachable by Tab? Is the tab order logical? Is there a visible focus indicator everywhere, on every background? Is outline:none used anywhere without a stronger replacement? Are there positive tabindex values? Can focus always leave anything it can enter? Does Escape close dialogs and menus? Is there a skip link, and does it actually move focus rather than just the scroll position? Look specifically for clickable divs and spans — an element with a click handler that is not a button or a link is not keyboard accessible. Also check whether a sticky header would hide the focused element as someone tabs down the page. Tell me which of these you verified in a browser and which you inferred from markup.
Why it works: the last line is the important one. Much of this cannot be determined from source, and being told which half is inference is what makes the report usable.
Verify: do the keyboard pass yourself. It takes ten minutes and it is the highest-yield accessibility test there is.
Measure contrast rather than asserting it
Check colour contrast throughout this project. For every foreground and background pair that carries text or meaning, compute the actual ratio and report it in a table. Required: 4.5:1 normal text, 3:1 large text and interactive component boundaries. Also check focus indicators against every background they appear on, and whether colour is ever the only means of conveying information — error states, required fields, links within body text, status indicators. Compute the ratios. Do not assert compliance without the numbers.
Why it works: "do not assert compliance without the numbers" prevents the most common failure, which is a confident "meets AA" with nothing behind it.
Verify: the real check is computed against the rendered backdrop, not the declared one. Inherited and composited backgrounds are where this goes wrong — and where a CSS specificity conflict can make text the same colour as the surface behind it while the source looks perfectly correct.
Security
Scan for secrets in all four places
Scan this repository for exposed credentials. Check: the working tree; tracked files that should never be committed; the full git history, all branches and tags — a secret removed in a later commit is still in history and still compromised; deleted files in history; commit messages; the build output and client bundles, because anything in a client bundle is public; source maps; CI/CD configuration; test fixtures and seed data. Be over-inclusive. A false positive costs me thirty seconds; a missed key costs an incident. Do not print any discovered secret in full — show enough to identify it and redact the rest. For each finding tell me where to rotate it. Rotation comes first: removing a secret from the repository does not un-expose it.
Why it works: most secret scans check the working tree only. History and build output are where the real ones hide.
Verify: rotate anything found, immediately, before cleaning anything up.
Authorisation review
Review authorisation in this application. For every endpoint and every data access: 1. Is authorisation checked on the server? 2. Is ownership verified — does this user have the right to this specific record, not just to this type of record? 3. Could a user access another user's data by changing an ID in a URL, a form field, or a JSON body? Trace it and tell me. 4. Could a normal user reach an admin function by requesting its URL? 5. Is anything enforced only in the UI? A hidden button is not access control. For each finding: the exact request that would exploit it, and the fix.
Why it works: asking for "the exact request that would exploit it" separates real findings from theoretical ones.
Verify: make that request. If it returns data, the finding is real.
Performance
Baseline before optimising
Establish a performance baseline for this project. Build the production bundle and measure, reporting real numbers: bundle sizes by chunk for JS and CSS; total image weight and the largest individual images; font payload; third-party bytes and the origins contacted; request count; build duration. Then identify the LCP element on each key template, and every render-blocking resource. State how you measured and under what conditions. Do not estimate a number and present it as measured. Do not optimise anything yet.
Why it works: "do not optimise anything yet" is the point. Without a baseline you cannot tell whether the next hour helped.
Verify: the numbers should be specific. Round numbers across the board suggest estimation.
Audit third-party scripts
Audit every third-party script on this site. For each: what it is, what it costs in bytes and requests, which origins it contacts, whether it blocks rendering, whether it loads on every page or only where needed, and what business value it delivers. Flag anything loading on every page for a feature used on one page, anything from a service no longer in use, and anything that could be deferred. For each candidate for removal, state exactly what functionality is lost. Do not remove anything that drives revenue to improve a score — give me the trade-off; the decision is mine.
Why it works: the last sentence keeps a performance exercise from quietly deleting the analytics or the payment widget.
Verify: check the network panel before and after. Confirm the removed script's functionality is genuinely gone or genuinely unused.
Testing
Tests that would actually catch the bug
Add tests for [AREA]. Test behaviour through the public interface, not implementation details — a test that breaks on every refactor is a liability. Cover the happy path, invalid input, empty input, boundary values, and the error paths. Do not write a test that passes without asserting anything. Do not weaken an assertion to make something pass — if a test fails, tell me whether the code or the test is wrong. Tell me what is still untested and why.
Why it works: the two "do not" lines block the two ways generated tests fail — asserting nothing, and being weakened until they pass.
Verify: break the code deliberately and confirm the test fails. A test that passes against broken code is worse than no test.
Git and deployment
Review a diff before merging
Review these changes: [DIFF or "the current uncommitted changes"] In this order: 1. Does it do what it claims? 2. Does it break anything that currently works? 3. Is it secure — input validated, output encoded, authorisation checked, no secrets, nothing new logged that should not be? 4. Is it accessible — semantics, labels, keyboard, contrast? 5. Does it follow the conventions already in this codebase? 6. Is it tested? 7. Will it be understandable in six months? Skip anything a linter or formatter would settle. If there is nothing wrong, say so plainly. Do not manufacture findings to appear thorough — a review that always finds something teaches me to ignore it.
Why it works: the ordering matters — correctness before style. The last paragraph prevents review inflation, which is what makes reviews get ignored.
Verify: run it in a fresh session. A session reviewing its own work will defend it.
Deployment readiness
Assess whether this project is ready to deploy to production. Check: does it build from a clean checkout? Do tests pass — report the actual result. Is there a secret anywhere in source, config, client bundles, or git history? Are all environment variables documented and set in the target? Is there a rollback procedure, and has anyone read it? Is monitoring in place before traffic rather than after? For each: pass, fail, or not verified. "Not verified" is a legitimate answer and more useful than an unearned pass. Give me a clear go or no-go with the blockers named in the first sentence. Do not hedge.
Why it works: making "not verified" an explicitly allowed answer is what stops the checklist becoming a formality of unearned ticks.
Verify: anything marked "not verified" is your remaining risk. Decide about each one consciously.
Turning prompts into slash commands
Copying prompts from an article into a terminal gets old fast. Save the ones you use as slash commands and they become part of the tool.
mkdir -p .claude/commands
cat > .claude/commands/audit-seo.md <<'CMD'
Perform a technical SEO audit of this project. Check indexability,
canonicalisation, metadata uniqueness, heading hierarchy, structured
data, sitemap contents, and internal linking.
For every finding give evidence — the file and line, or the actual
response. Rank by impact. Tell me what you could not check.
CMD
Then in any session in that project: /audit-seo.
Put project-specific commands in .claude/commands/ so they travel with the repository and your team gets them. Put personal ones in ~/.claude/commands/ to have them everywhere.
Doing this for your five most-used prompts is the single change that most alters how the whole workflow feels — the friction of "which prompt was that again" disappears, and you stop skipping steps because they were tedious to type.
Prompt patterns that waste your time
Asking for everything at once
"Build the whole site" produces a diff nobody reviews. The failure is not the model's output quality; it is that you cannot check it. Stage the work.
Describing the solution instead of the problem
"Add a Redis cache here" forecloses the possibility that the query needs an index. Describe the symptom and the constraint, and ask for approaches.
Leaving conventions implicit
Every unstated convention is a coin flip. This is what CLAUDE.md is for — say it once, in a file, instead of in every prompt.
Accepting "done" without evidence
"Tests pass" is a claim. Ask for the output.
Politeness instead of constraints
"Please be careful with the database" does nothing. "Never write a migration that drops a column without asking first" does.
Re-explaining the project every session
If you are typing the same context repeatedly, it belongs in a file. That is the signal.
Auditing in the session that wrote the code
It will defend its own work. Fresh session, every time.
Where to go next
These prompts are individual tools. The complete website workflow shows where each one fits in a full build, from definition through to post-launch monitoring. For the persistent context that stops you repeating constraints in every prompt, see creating a production CLAUDE.md. Platform-specific applications are in the Shopify guide and the SEO guide.
Sources and further reading
- Claude Code: common workflows — plan mode, subagents, worktrees, headless mode
- Claude Code: memory and CLAUDE.md
- W3C: WCAG 2.2 — the criteria referenced in the accessibility prompts
- OWASP Top Ten — the risk categories behind the security prompts