Design review for every pull request.

Agents open more pull requests than anyone can look at, and code review has reviewers where design has none: Impeccable is the design reviewer in the loop.

Join the closed beta waitlist
crewline.app/people
Crewline, the sample app: the People table of a workspace on a deep plum ground, with an apricot Invite member button.
crewline.app/activity
Crewline: the Activity feed, where the description says an invitation shows up.
crewline.app/people
Crewline: the Invite member dialog the pull request adds — an email field, a role, three permissions, and a Send invite button that is the only blue thing on the screen.
crewline.app/people
Crewline on a phone: the same invite dialog, full width.

Add CSV and PDF export to the report toolbar #418

Opencodex-agent wants to merge 1 commit into main from report-export

Invite member modal #1287

Opencodex-agent wants to merge 2 commits into main from invite-modal

Add a show settings page #2210

Opencodex-agent wants to merge 3 commits into main from show-settings

impeccablebotcommented

The invite is three questions on a card that looks like the app, and it works from the keyboard. Two things stop it: Send invite is the only blue thing in an app that acts in apricot, and it closes the card without a word, so an admin cannot tell the invitation went.

3/5 · Not yet: fixable before it ships
1 blocker · 1 on how it looks · 2 for your users · 1 in the craft · 3 sessions

Does it work for your users?

Nora, returning customer on a laptop: 5 steps in 34s, scored 6/10. “I pressed Send invite and the card closed. Nothing said it went, and the table did not change.”Got through, with friction
Quinn, operator on a keyboard: 4 steps in 21s, scored 8/10. “Tab landed in the email field, Escape closed the card, and focus came back to the button.”Got through
Ravi, new visitor on a phone: 3 steps in 18s, scored 8/10. “Invite member is where I expected, and the form is three questions.”Got through
P1

Send invite ends in silence
/people · Invite member

P2

Role and permissions ask the same question twice
/people · Invite member

Does it look right?

impeccable engine · reading your design system from the code

P2

Send invite is the only blue in the app
/people · Invite member · styles.css:388

Is it solid?

P3

The close button has no name
index.html:184

The Export menu answers the one question a person has at that toolbar, which file do I get, and it works from the keyboard. Nothing to fix.

5 of 5 5/5 · Ready
no blockers · nothing to fix · 2 sessions

Does it work for your users?

Sessions
Nora, returning customer: 3 steps, scored 9/10. “Export sits where I expected, next to Print, and the hint under PDF said formatted report before I clicked.”

Got through

nothing to fix

Quinn, operator on a phone: 4 steps, scored 8/10. “Arrowed to CSV, Enter, done. Escape put me back on the button.”

Got through

nothing to fix

The report toolbar with the Export menu open beside Print: CSV, rows as filtered; PDF, formatted report.

The report toolbar with the Export menu open beside Print: CSV, rows as filtered; PDF, formatted report.

Measured

MeasureThis changeTotalWhere
SLOP Tells in the chrome00
DRIFT Declarations off the tokens00
CRAFT Controls without a name00
WEIGHT Page weight0 KB31 KBno images
For agents
nothing to do
About this review

Reviewed 3 files at 2f0a9c1. 2 of 2 routes rendered at 1280 and 390 px; 2 sessions. The menu opens from its button, arrows move between the two items, Escape and Tab close it and hand focus back, a click outside closes it.

Ledgerline is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.

The invite is three questions on a card that looks like the app, and it works from the keyboard. Two things stop it: Send invite is the only blue thing in an app that acts in apricot, and it closes the card without a word, so an admin cannot tell the invitation went.

3 of 5 3/5 · Not yet: fixable before it ships
1 blocker · 1 on how it looks · 2 for your users · 1 in the craft · 3 sessions

Does it work for your users?

Sessions
Nora, returning customer on a laptop: 5 steps in 34s, scored 6/10. “I pressed Send invite and the card closed. Nothing said it went, and the table did not change.”

Got through, with friction

Sent the invite and could not tell.

Quinn, operator on a keyboard: 4 steps in 21s, scored 8/10. “Tab landed in the email field, Escape closed the card, and focus came back to the button.”

Got through

nothing to fix

Ravi, new visitor on a phone: 3 steps in 18s, scored 8/10. “Invite member is where I expected, and the form is three questions.”

Got through

nothing to fix

P1

Send invite ends in silence
/people · Invite member

The card closes and clears. No Invited row in the People table, nothing in Activity where the description says it shows up. As far as the admin can tell, the invitation did not go.

Fix Keep the card open until the email passes, then say what happened: an Invited row, or a line in Activity.

The foot of the dialog: Cancel, and a blue Send invite.
P2

Role and permissions ask the same question twice
/people · Invite member

The role decides what a person can do, and three checkboxes under it let the admin contradict it: a Member with the directory unchecked, a Workspace admin who cannot invite.

Fix Drop the checkboxes. Under the role, one line saying what it allows; edit permissions on the member’s page.

The Invite member dialog on the app’s plum ground: an email field, a role select, three permission tick boxes, Cancel and a blue Send invite.

Does it look right?

P2

Send invite is the only blue in the app
/people · Invite member · styles.css:388

The button hardcodes #3b82f6. Every other primary, the Invite member trigger included, takes --accent, the apricot this app acts in — and the app has no blue anywhere else. White on that blue is 3.7:1.

Fix Drop the colour rules and let .btn-primary style the button.

The apricot Invite member button on the People page.
The blue Send invite button at the foot of the dialog, beside a plain Cancel.

Is it solid?

P3

The close button has no name
index.html:184

A bare × with no aria-label: a screen reader announces “button” and nothing else.

Fix Give it aria-label="Close".

Measured

MeasureThis changeTotalWhere
SLOP Tells in the chrome00
DRIFT Declarations off the tokens33styles.css:304, :376, :383
DRIFT Shipped values against your design tokens11#3b82f6 where the accent is green
CRAFT Low-contrast text11Send invite, 3.7:1
CRAFT Controls without a name11the close button
CRAFT Functional text under 11px00
WEIGHT Page weight+4 KB47 KBno images
For agents
P2 · Send invite is the only blue in the app · /people · styles.css:388 · fix: drop the colour rules; let .btn-primary style it.
P1 · Send invite ends in silence · /people · modal.js:29 · fix: keep the card open until the email passes, then an Invited row or a line in Activity.
P2 · Role and permissions ask the same question twice · /people · index.html:196 · fix: drop the checkboxes; one line under the role saying what it allows.
P3 · The close button has no name · /people · index.html:184 · fix: aria-label="Close".
About this review

Reviewed 3 files at 8c41e0d. 2 of 2 routes rendered at 1280 and 390 px; 3 sessions. The dialog opens with focus in the email field, traps it, closes on Escape and returns focus to the button.

Crewline is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.

The page is the right shape and reads in one pass: a short form that says where each thing shows up, on the app’s own ground. Delete show wears the accent the app keeps for its primary action, and one click from it is 48 episodes gone. Two decisions go against the app: a sidebar of its own, and a section that is a heading over nothing.

3 of 5 3/5 · Not yet: fixable before it ships
1 blocker · 1 on how it looks · 3 for your users · 2 in the craft · 3 sessions

Does it work for your users?

Sessions
Ravi, new visitor: 3 steps, scored 2/10. “Connected services is a heading over nothing. I cannot tell if I have none or it is not built yet.”

Stuck

Stuck at Connected services: nothing to connect, nothing said.

Quinn, operator on a phone: 5 steps, scored 6/10. “Two rows of links above the form on my phone, none of which did anything, so I scrolled.”

Got through, with friction

Found the setting past two rows of dead links.

Nora, returning customer: 3 steps, scored 8/10. “Category is where I expected it, and Save changes sat right under the form.”

Got through

nothing to fix

P1

Delete show is one click from 48 episodes gone
/settings.html · Danger zone

One click is the whole flow: nothing between it and the deletion, and the button sits a few lines under Save changes.

Fix A confirmation that names the show and what goes with it, with Cancel as the default.

P2

The page invents its own navigation
/settings.html · sidebar

A sidebar of four section links while every other page navigates from the masthead, and on a phone it wraps into two rows between the heading and the first field.

Fix Cut the sidebar and its column. The section headings already do the job.

On a phone: Show details, Notifications, Connected services and Danger zone as two rows of links.
P2

Connected services is a heading over nothing
/settings.html · Connected services

An empty list under a heading. A host cannot tell whether they have none or the feature is not built yet — and the pull request body knows the answer.

Fix Write the empty state: the Spotify and Apple sync is coming, nothing to do now. If that cannot be said yet, leave the section out.

The Connected services card: a heading and nothing under it.

Does it look right?

P2

Delete show wears the accent, not the danger colour
/settings.html · Danger zone · styles.css:226

The same filled --accent orange as Save changes. The app declares --danger and no screen uses it, so the one destructive button on the page reads as its primary action.

Fix Give it --danger, outlined, and keep the filled accent for the action that is not destructive.

The Danger zone card: a sentence saying deletion removes all 48 episodes, and a filled orange Delete show button.

Is it solid?

P3

Two field names reach no control
settings.html:49

The Category label points at an id the select does not have, and Description is a heading above a textarea with no label. Both look labelled and neither is.

Fix Point the label at category, and turn the Description heading into <label for="show-description">.

The Category field: a label, a select showing Society & Culture, and a hint.
P3

Spacing in the new sections is off the app’s scale
styles.css:194

28 px gaps, 18 px section padding and a 10 px rhythm where the rest of the app moves in 12, 16 and 24.

Fix Replace the literals with the steps the stylesheet already names.

Measured

MeasureThis changeTotalWhere
SLOP Tells in the chrome00
DRIFT Declarations off the tokens99styles.css:194, :200, :226 …
DRIFT Shipped values against your design tokens11--accent on the destructive action
CRAFT Controls without a name22Category, Description
CRAFT Low-contrast text00
CRAFT Functional text under 11px00
WEIGHT Page weight+11 KB58 KBno images
For agents
P2 · Delete show wears the accent, not the danger colour · /settings.html · styles.css:226 · fix: --danger, outlined.
P1 · Delete show is one click from 48 episodes gone · /settings.html · settings.html:91 · fix: a confirmation that names the show, Cancel as the default.
P2 · The page invents its own navigation · /settings.html · settings.html:23 · fix: cut the sidebar and its column.
P2 · Connected services is a heading over nothing · /settings.html · settings.html:77 · fix: write the empty state, or leave the section out.
P3 · Two field names reach no control · /settings.html · settings.html:49 · fix: label for="category"; label the description.
P3 · Spacing off the app’s scale · /settings.html · styles.css:194 · fix: the named steps.
About this review

Reviewed 4 files at 5b2d91e. 3 of 3 routes rendered at 1280 and 390 px; 3 sessions.

Wavecast is a sample app we keep for this. The review is written by hand in the shape the product posts, from the findings the app’s reference review names; the captures are real renders, the visitors and the counts are an example.

styles.cssline 388
.modal-submit {- background: #3b82f6;- border-color: #3b82f6; }
impeccablebotleft a comment

Every other primary in the app takes the --accent token; this one hardcodes the blue.

Suggested change

- background: #3b82f6;- border-color: #3b82f6;+ background: var(--accent);+ border-color: var(--accent);
Commit suggestionAdd suggestion to batch
styles.cssline 194
.settings-section {- gap: 28px;- padding: 18px; }
impeccablebotleft a comment

The stylesheet already names these steps; the new sections are the only place that spells them out.

Suggested change

- gap: 28px;- padding: 18px;+ gap: var(--space-lg);+ padding: var(--space-md);
Commit suggestionAdd suggestion to batch

impeccable / design review · Ready · 5/5impeccable / design review · Not yet · 3/5impeccable / design review · Not yet · 3/5

See it on a pull request that is

ledgerline/app · 3 files changed, 2 sessionscrewline/web · 3 files changed, 3 sessionswavecast/dashboard · 4 files changed, 3 sessions

The pull requests are against sample apps we keep for this; each critique is the one that pull request gets.

Code review caught up with agentic development. Design review did not.

code review design review
Before. Fewer pull requests, and every one passed a person’s eye: a designer and a product manager saw the screen before it shipped.
code review design review
Now. Teams ship many times the pull requests they used to. Code review kept up — an AI reviewer on every one — and the design seat is empty, so slop on the screen compounds into the product.
code review design review
With Impeccable. The same loop, with the design reviewer back in it: one more check to gate on, one more comment to satisfy, and the fix is in the comment.

Join the closed beta.

For teams with a frontend and a preview to render. Leave your email, then answer 7 quick questions. The more we know about your setup, the sooner we can invite you, and the better your first review goes.

We keep your address and your answers, plus salted hashes of your network address and browser so one machine cannot fill the list. Never shared. Want off the list? Email privacy@renaissance-geek.ai and we’ll remove you.