Slopapalooza

What it is

The Screenshot-Driven Product Spec treats a visual reference as a complete requirement for an interactive product. AI can reproduce the layout while permissions, state changes, validation, and failure behavior remain undecided. The screenshot is useful input. The failure is accepting a convincing rendering as evidence that the product rules are settled.

The missing frame

Consider an illustrative invoice screen with a “Pay” button. The reference shows an unpaid invoice viewed by an authorized customer. It says nothing about a request that reaches the server but loses its response. Should the screen offer another payment, show a pending state, or retrieve the result of the first attempt?

Disabling the button during the request helps prevent accidental double clicks. It does not handle a reload or a second browser tab. The product and API need an agreed way to identify the same payment attempt and recover its status. Generating another spinner does not answer that question, even if the spinner is extremely on-brand.

Why it’s dangerous

An unspecified rule still becomes behavior when somebody implements it. The UI may label an uncertain payment “failed” and encourage a retry, or hide a button while leaving its server action open to an unauthorized caller. A visual comparison can pass in both cases.

Building a visual prototype first is a useful way to discover these questions. Keep simulated behavior visible as a prototype constraint, and resolve the consequential rules before connecting real actions. Existing components and API contracts may already answer most of them; copying their rules into a new specification creates another document to keep synchronized.

How to turn the picture into a specification

Separate the invoice’s business state, the payment attempt’s result, and what the browser currently knows. “Submitting” describes a UI interaction; “rejected” needs an authoritative result. A timeout leaves the browser uncertain even if payment succeeded. Retrieve the existing attempt’s status rather than silently creating a new one. Decide when an uncertain outcome needs support and when a new attempt is allowed. These rules must match the payment API’s retry and idempotency contract; the UI cannot invent an exactly-once guarantee.

Let AI draft questions from the reference and compare them with existing flows. Attach each consequential question to an existing contract or an owner who will decide it. A question list alone is not a specification: “handle errors” still leaves the agent choosing what the customer can do after a payment timeout.

The serious team fix

  1. Keep state examples beside the design. Include loading, empty, denied, failed, and uncertain outcomes where relevant. For the payment screen, specify the message and available action when status is unknown. Reuse shared components and conventions so every screen does not maintain a separate interpretation of “pending.”
  2. Check the flow across the service boundary. Component stories make states easy to inspect. Also exercise the actual status and permission behavior in a sandbox, including a lost response and a repeated attempt. A mocked “paid” response proves that the screen can render it, not that payment was handled correctly.
  3. Inspect interaction as well as appearance. Check keyboard access, focus after errors, labels, and announcements of status changes. Automated accessibility checks catch some problems; W3C’s evaluation guidance explains why tools alone cannot determine accessibility. Test the supported flow with appropriate assistive technology as well as comparing screenshots.

Related anti-patterns

Back to all anti-patterns