A ticket arrived with three apparently small issues in a tournament-creation dialog: a file upload that failed on mobile, a name field that cleared on submit, and stale date-placeholder behavior. I started by fixing inputs. The more useful answer came later, when a review questioned whether this task belonged in a dialog at all.
The production app is an old ASP-classic application. Modal dialogs were a reasonable choice when the app was built, and a load-bearing assumption by the time I inherited it. The Create Event dialog was one of hundreds of those patterns layered in over the years, each one reasonable at the time it was added, each one adding constraints the next builder had to work around. By the time I sat down with that ticket, the dialog had accumulated fields across multiple tournament types and had become a surface where fixing one thing reliably broke another.
the dialog was the wrong container
During the implementation work, a design reviewer joined and looked at the current modal. One product question changed the direction of the day.
The question was: why is this a dialog at all?
Tournament creation involved uploads, dates, names, staffing, and a mobile-readable flow. Dialogs can work well for focused tasks, but this particular flow had accumulated enough state, recovery needs, and responsive layout pressure that the modal no longer supported the task clearly. The special cases were a signal to reconsider the container, not proof that every dialog was a mistake.
The team routed the create-event task to a dedicated full-page form and retired the dialog path. The page gave the flow room for its inputs, validation, recovery states, and responsive layout. The important change was not the route syntax; it was making the task surface match the work the user actually needed to complete.
what the design review actually killed
The design review made several concrete decisions, each resolving an issue I had initially treated as separate.
The review used language that matched how users described their role, moved the upload action to a clearer place in the task flow, improved visual hierarchy, and restructured the form around user intent rather than a compact field list. It also retired the dialog. That decision was not obvious during implementation because the work had been framed as input-level bugs rather than a task-flow problem.
the fixes that needed a real page
Once the form was a page, several things that had been hard became straightforward.
The competition-name field had been clearing on submit because of how the dialog’s state was wired. On the page form, the value is preserved through the action cycle, and that fix came from changing the container, not from patching the field.
The image upload had a temporary-file lifecycle issue: the handoff location did not survive the expected submission sequence. Moving to a page made the states and failure handling easier to inspect, but the fix still required an explicit, secure upload lifecycle with validation, cleanup, and access controls.
Mobile layout had been wrapping inputs into columns that made the form unreadable on anything narrower than 800px. The page handled wrapping correctly because it was not constrained by dialog width.
Date placeholders were showing a format string instead of hint text on several browsers. That is a one-line fix once the input is visible and testable in isolation, but on the dialog it had been masked by the surrounding chrome. Input sizing and label alignment got a cleanup pass. Nothing individually significant, but the cumulative effect is a form that reads as intentional rather than accumulated.
AI assistance helped implement several bounded fixes once the broken behavior and constraints were clear. It did not independently broaden this particular ticket into a product-level container review, because that was not part of the task context. The design review supplied that missing frame.
where the session artifacts go
One operational side-lesson from the day. Screenshots, plans, and session artifacts had been landing in ad-hoc locations around the repo, some in tracked directories, some not. By the end of the session I had defined a named constant pointing at a scratch location outside the tracked tree. Future sessions write their temp output there.
Small convention. Sessions on an old codebase accumulate a lot of intermediate state, and without a named home for it, that state becomes noise you clean by hand or leave to pollute the repo history.
what the agent can and can’t do
The bounded implementation work was useful once its constraints were understood. The missing step was a product-level review of the user task, container, and recovery flow.
An AI assistant working on a dialog will usually improve the dialog unless the prompt or review process explicitly asks whether the container remains appropriate. It can help compare options when given the relevant user evidence and constraints, but it should not be the sole authority for a product decision with accessibility, workflow, and business consequences.
In this case, a design review brought the user’s vocabulary and task flow into the conversation. Those product decisions became visible because someone evaluated the frame as well as the code.
AI assistance accelerates implementation. It does not remove the need for a collaborator to challenge the frame, validate the experience, and decide whether the task surface is still right.
Related
- AI Will Happily Produce the Wrong Mockup: a component-level case where broader layout review changed the diagnosis
- The Real Fix Was Starting Over With a Smaller Blast Radius: another case where redefining the scope made subsequent implementation safer to review