AI disclosure: The first draft of this article and its code example were generated with AI. The salon below is a fictional example, not a completed client project.
“Build a modern website for a beauty salon with a booking form.”
That sounds like a reasonable prompt. But it leaves an important question unanswered: what should the form actually do?
Scroll to a contact section? Send an appointment request? Reserve an available time slot?
Those are different implementations. A screenshot cannot tell you which one you have.
For an AI-assisted website project, I would start with acceptance criteria: observable conditions that tell you whether the result does what you asked.
Here is a workflow for turning a vague website request into a buildable brief and a test plan.
1. Define one complete user journey
For this example, the business is a fictional salon called Glow Studio. The first version needs one journey:
Read about a service → request an appointment → receive a submission confirmation.
An appointment request is not a confirmed booking. The salon still needs to agree on a time with the customer.
That distinction determines the copy, the interface, and the backend work. The button should say “Request an appointment,” not promise an instantly confirmed reservation.
Keep accounts, payments, live availability, and loyalty programs outside this first version.
2. Write the acceptance criteria before the prompt
Instead of “make it responsive and functional,” write conditions you can check:
| Requirement | How to check it |
|---|---|
| The primary CTA leads to the request form. | Activate it from the hero and navigation. |
| Missing required information prevents submission. | Submit an empty form and inspect the feedback. |
| A successful request reaches the configured destination. | Submit test data and locate the corresponding record. |
| A failed request does not display a success message. | Simulate a network failure and check the interface. |
| The layout works at the chosen test widths. | Inspect at 360, 390, 768, and 1280 CSS pixels. |
These widths are example checkpoints, not proof that every device is covered.
Notice that most of the criteria describe behavior, not appearance. “Premium design” is open to interpretation. “An empty required field prevents submission” is much easier to evaluate.
3. Turn the brief into a constrained generation prompt
Here is an example prompt:
Build a responsive, single-page website for Glow Studio,
a fictional beauty salon.
Audience:
Local customers researching services and requesting appointments.
Primary journey:
Read about a service, request an appointment, and receive a
confirmation that the request was submitted. Do not present
an appointment request as a confirmed reservation.
Sections:
Hero, services, about, FAQ, and appointment request form.
Primary CTA:
"Request an appointment". Every primary CTA should lead to
the form section with the ID "appointment".
Form fields:
Name, email, and preferred service. Require all three.
Use visible labels associated with the controls.
Form behavior:
Validate input, indicate submission progress, and display
separate success and error states. Preserve entered values
when submission fails.
Integration boundary:
Do not invent a working backend. If a submission destination
has not been configured, label the form "Demo only: requests
are not sent". Do not show a fake success confirmation.
Content:
Do not invent reviews, awards, addresses, or customer numbers.
Clearly label missing business information as placeholder content.
Layout:
Use a restrained visual style and readable typography.
Avoid horizontal page scrolling at the selected test widths.
Provide visible keyboard focus styles.
Out of scope:
Payments, accounts, live appointment availability, and a dashboard.
The integration boundary matters as much as the visual instructions. It separates a useful prototype from a misleading demonstration.
A prompt is still a specification, not evidence that the generated implementation satisfies it.
4. Verify the form, not just its appearance
Start with the markup. A basic email field can use native HTML features:
<label for="email">Email address</label>
<input
id="email"
name="email"
type="email"
autocomplete="email"
required
/>
The matching for and id associate the label with its input. See MDN’s label documentation.
The required and type="email" attributes provide browser-side constraints. They do not prove that an address exists, and they do not replace server-side validation. See MDN’s constraint validation guide.
Next, trace a test request through the complete system. Check the browser response, then locate the submitted data in the destination you configured. A visible “Success” message alone is not that evidence.
Test failure separately. Keep the user’s input, explain what went wrong, and provide a way to try again. For accessible feedback, consult W3C’s guidance on form notifications.
Finally, navigate the form with a keyboard. Can you reach the controls, see where focus is, and understand the result without relying only on color?
5. Investigate mobile overflow with a small diagnostic
When a page scrolls sideways unexpectedly, it helps to identify elements extending beyond the viewport.
After the page has loaded, open your own project’s preview at the problem width and run this in the browser console:
(() => {
const viewport = document.documentElement.clientWidth;
const candidates = [...document.querySelectorAll("body *")]
.map((element) => ({
element,
rect: element.getBoundingClientRect(),
}))
.filter(({ rect }) =>
rect.width > 0 &&
rect.height > 0 &&
(rect.left < -1 || rect.right > viewport + 1)
)
.map(({ element, rect }) => ({
element,
left: Math.round(rect.left),
right: Math.round(rect.right),
viewport,
}));
console.table(candidates);
return candidates;
})();
getBoundingClientRect() reports element bounds relative to the viewport. In standards mode, the root element’s clientWidth provides the viewport width excluding its scrollbar.
Treat the output as candidates for inspection, not an automatic list of bugs. Intentional off-canvas menus and clipped decorative elements can appear. The snippet does not inspect iframe contents or shadow roots and is not a complete responsive-layout audit.
Do not immediately hide all horizontal overflow. First check whether a fixed width, long text, or an oversized child is causing the problem.
6. Request a targeted fix and rerun the check
A useful follow-up prompt should resemble a small bug report rather than another creative brief.
For example:
At a viewport width of 390 CSS pixels, the service cards
extend beyond the right edge of the page.
Adjust the service-card layout so every card fits inside
the viewport at this width.
Preserve the existing copy, colors, section order, and form
behavior. Do not redesign unrelated sections.
After the change, repeat the failing check and the primary user journey. The goal is not to trust the model’s explanation of the fix. It is to observe the corrected behavior.
The definition of done belongs outside the model
For this example, the site is not ready for real enquiries until the form destination is connected, placeholder content is replaced, and the user journey works on the published page.
Before accepting real traffic, repeat the checks outside the builder’s editor. Use your own test contact details and verify where the request arrives.
The workflow is:
Brief → acceptance criteria → generation → verification → targeted fixes.
AI can propose the implementation. Deciding whether it works still requires an observable result.
Author affiliation: I’m a co-founder of Lork. Our team shares practical website-building guides on the Lork blog.
Top comments (0)