Discovery 0/3
Before any pixels. Validate the need, set the bar, name the states.
-
Manual
Before you design anything, confirm the component fills a real gap that more than one screen will reuse. Open a tracked issue and run a quick team critique first.
Fix Write an issue saying what the gap is and who needs it. Hold a 15-minute critique before you start high-fidelity work.
-
Manual
Pick WCAG 2.2 Level A and AA as your bar, not AAA, and put it in writing so everyone is aiming at the same achievable target.
Fix Add the line 'Target: WCAG 2.2 AA' to the project README or the design brief.
-
Manual
List the states each view can show, empty, sparse, dense, loading, error, and success, so you design them on purpose instead of bolting them on later.
Fix For every data-driven view, sketch all six states before you sign off the happy path.
Design 0/13
In the design tool. Contrast, targets, scales, palette, hierarchy.
-
Automated
Give body text a contrast of at least 4.5:1 against its background. Large text, 24px regular or 18.5px bold and up, can sit at 3:1. Do not round up: 4.499:1 still fails. Disabled, decorative, and logo text are exempt.
Fix Drop each text and background pair into the WebAIM contrast checker. Darken the text or lighten the surface until it passes, then save both as tokens.
-
Advisory
Give control edges and states, the borders on inputs, buttons, checkboxes, toggles, and focus rings, plus any icon or chart line you need to read, at least 3:1 against what sits next to them. This is a separate rule from text contrast.
Fix Check every border, focus ring, and meaningful icon against its background. Push the token darker or lighter until each clears 3:1.
-
Manual
Never use colour as the only signal for meaning, an action, or which thing is which. Back every coloured cue with text, an icon, an underline, or a shape. Underline links, mark error fields with text, and label chart series.
Fix Add a tick or warning icon next to status colours, underline links, and label or pattern each chart series.
-
Advisory
Make every pointer target at least 24 by 24 CSS px, or space them so a 24px circle on each one does not touch a neighbour. On mobile follow the platform: 44pt on iOS, 48dp on Android. The 44px square is the higher AAA goal, not the AA floor.
Fix Grow the hit area with padding, not margin. Links inside a sentence are exempt.
-
Advisory
Pull every type size from one defined scale, either a ratio near 1.25 or the Material 3 type roles. Pick from the scale instead of typing in one-off sizes.
Fix Set the scale up as tokens, then swap any stray font-size for the nearest scale token.
-
Advisory
Pull all spacing from one scale, like 4, 8, 16, 24, 32, 48, 64, or an 8dp grid with a 4dp sub-grid. Keep no two steps closer than about 25 percent. Start with lots of whitespace and take it away, do not pile it on.
Fix Swap any odd margin or padding for a scale token. Put less space between related items than between unrelated groups.
-
Advisory
Build a wide neutral scale of 8 to 10 shades, add 1 or 2 brand colours, and reserve danger, warning, and success, with optional accents for hierarchy or charts. One colour only is a rough guide, not a law. Aim for roughly a 60-30-10 split.
Fix Author the whole neutral, brand, and semantic set as tokens. Strip out accidental one-off colours but keep the accents you meant.
-
Manual
Show what matters most with size, weight, and contrast, and quiet the secondary stuff, rather than leaning on labels. Give the main action the strongest visual weight on the screen.
Fix Dim secondary text and chrome, and let one primary action stand out per view.
-
Advisory
Use one icon family with consistent names and sizes from the type scale: 16, 20, or 24. Give any icon that carries meaning at least 3:1 contrast so it reads.
Fix Pick one icon set, bind the sizes to tokens, and check meaningful icons clear 3:1 against their background.
-
Advisory
Design each state of a component up front: default, hover, focus, active, disabled, loading, and error. Cover the awkward combinations too, like disabled plus error, so nothing gets retrofitted later.
Fix Lay out a state grid for each component and draw every cell, including the messy overlaps, before sign-off.
-
Advisory
Build the spec from existing tokens only, write down every interaction state and the focus order, and clear WCAG 2.2 AA contrast. Run an expert review at full fidelity before you sign it off.
Fix Map each value in the spec to a named token, then mark hover, focus, active, disabled, and tab order before handoff.
-
Manual
Write button, error, label, and heading copy in one documented voice, in plain language. Use the same word for the same action everywhere so users are not guessing.
Fix Read the copy against the voice guide and unify any wording that drifted, so one action always reads the same way.
-
Automated
Run a token linter that checks format, colour space and gamut, naming, duplicate values, and required types and modes, plus a minimum contrast and minimum font size on token pairs.
Fix Run the linter in CI against the token source and fail the build on any error.
Build 0/36
In code. Semantics, focus, states, motion, tokens.
-
Advisory
Every control you can reach by keyboard shows a clear focus ring while it is focused. Never strip the outline without a just-as-visible replacement.
Fix Add a high-contrast :focus-visible outline with a small offset to every control, then tab through the page to confirm.
-
Manual
When you tab to something, a sticky header, footer, or overlay must not cover it. The focused item has to stay in view.
Fix Add scroll-padding-top the same height as your sticky header so the focused item is never tucked underneath it.
-
Manual
You can reach and use every feature with the keyboard alone, and focus never gets stuck. Tab order follows the visual layout.
Fix Unplug the mouse and finish every flow with Tab, Enter, Space, and arrows. Fix anything you cannot reach or escape.
-
Automated
Tie every input to a visible label so it never disappears. Group related inputs, and link error messages to the field they belong to.
Fix Put a real label above each input and connect it. Move any placeholder hint into the label or helper text instead.
-
Advisory
When an input is wrong, name the field and say what went wrong in plain text, not just a red colour or icon. Suggest the fix when you can.
Fix Show a short text message with a warning icon right below the input, and tell the person how to fix it.
-
Manual
On submit, show an error summary above the heading, send focus to it, and link each item to its field. Word it the same as the field message.
Fix Render the summary when validation fails, move focus to it, link each line to its field, and match the wording.
-
Automated
Give content images a short, meaningful alt. Mark purely decorative images as empty so screen readers skip them. Describe charts and maps in longer text.
Fix Write alt that says what the image means, use empty alt for decoration, and add a longer description for complex visuals.
-
Advisory
Use one h1 per page and step heading levels in order, never skipping. Use real heading tags for section titles, not text that just looks big.
Fix Check the heading outline and fix any skipped level. Wrap regions in nav and main so the structure is clear.
-
Advisory
Make every button and link text say its action, like 'Save API key', not 'Continue'. Use a link to go somewhere and a button to do something.
Fix Rename vague controls to spell out the action, and flag any link that opens a new tab.
-
Automated
Give an icon-only button an aria-label so screen readers can name it. Hide decorative icons with aria-hidden, and start the label with any visible text.
Fix Add aria-label to every icon-only button, set aria-hidden on purely decorative icons, and lead the label with the visible text.
-
Automated
Set the page language on the html tag, give the page a real unique title, and let people pinch to zoom. Never block zoom.
Fix Add lang to the html tag, write a real title, and remove user-scalable=no from the viewport tag.
-
Automated
Set text inputs to at least 16px so Safari on iPhone does not zoom in when tapped. Make the tappable area match the visible control. Never block zoom.
Fix Set input font-size to 16px or more, and remove any maximum-scale or user-scalable lock from the viewport tag.
-
Advisory
Set body text to at least 16px, keep lines around 70 characters wide, and use a line-height near 1.5 for body and tighter for headings.
Fix Set body line-height to 1.5, cap line length near 70 characters, and tighten heading leading as the size grows.
-
Advisory
Use only a few weights that suit your typeface, a safe set is 400, 600, and 700. Keep semibold 600, and skip anything below 400 for UI text.
Fix Bind a small weight set to tokens. Drop weights below 400 for UI text, but keep semibold.
-
Advisory
Set body copy to align at the start with a ragged right edge. Skip full justification on screen, it leaves rivers of white space and is harder to scan.
Fix Remove text-align:justify from body copy. Use start, not a hard left, so right-to-left languages mirror.
-
Automated
When one rounded box sits inside another, make the inner radius the outer radius minus the gap, and never let it go below zero. Inner corners stay smaller than the outer.
Fix Work out the inner radius as outer minus padding, clamped at zero. Group your radii into sm, md, and lg tokens.
-
Advisory
Make shadows feel like real depth: stack a soft wide shadow with a tighter close one, and blur about twice the offset. In dark UIs, lift surfaces lighter instead.
Fix Swap harsh single shadows for two-layer soft ones as tokens, and use a few set depth levels, not random values.
-
Advisory
Design how each control looks at rest, on hover, on focus, when pressed, and when disabled. Bump the contrast a little on hover, focus, and active.
Fix Add a clear hover and focus to every control. For disabled, prefer aria-disabled so it stays focusable, and keep it readable.
-
Automated
Card padding steps down at phone width instead of holding the desktop inset, and a section's primary call to action spans the full width so it is an easy thumb target. Match the tiers: content cards 16 then 24, the big feature cards down to the standard tier, section CTAs full-width below 768px.
Fix Author card padding as a compact base with an @media(min-width:768px) bump (or a clamp floored at the compact or standard tier), and add the section CTA to the components.css mobile full-width allowlist. The mobile-consistency gate enforces both.
-
Advisory
Pick by how long it takes: under 1 second show nothing, 1 to 10 seconds a spinner or skeleton, over 10 seconds a percent progress bar. Skeletons must mirror the real layout.
Fix Match the pattern to the wait, build skeletons that look like the real content, and gate any shimmer behind reduced motion.
-
Automated
Animate only the properties you name, never transition:all, and move transform and opacity rather than width or height. Keep small moves quick and large ones a touch slower.
Fix Replace transition:all with the exact properties, and shift any size or position change onto transform.
-
Advisory
When someone asks for reduced motion, give them a calmer version. Keep looping animation under 5 seconds or let people pause it, and never auto-play flashing content.
Fix Add a prefers-reduced-motion block and give every auto-moving region a pause control.
-
Advisory
Keep z-index values in named tokens with wide gaps of about 100, ordered base, dropdown, sticky, modal, tooltip, toast. Single-digit steps leave no room and start stacking fights.
Fix Define z-index tokens, like dropdown 1000 up to toast 1500, and replace every raw z-index with one.
-
Advisory
Set images to object-fit: cover and give them a width and height or an aspect ratio, so they never squish and the browser can hold the space.
Fix Add object-fit: cover plus an explicit width and height, or an aspect-ratio, to every content image.
-
Advisory
Give data tables header cells with a scope and a caption that names the table. When a column sorts, announce it with aria-sort.
Fix Use th with scope for headers, add a caption, and set aria-sort on the column that is currently sorted.
-
Advisory
Use font-display: swap so text appears right away while custom fonts load, instead of leaving people staring at blank space. Lean on system fonts where you can.
Fix Add font-display: swap to your @font-face rules, and use the system font stack where a custom font is not essential.
-
Advisory
When the language reads right to left, like Arabic or Hebrew, the layout should flip to match. Use logical CSS so it mirrors on its own.
Fix Use margin-inline and text-align: start instead of hard left or right, so the layout mirrors when dir is rtl.
-
Advisory
Translated text can run about 30 percent longer than English, so leave room for it. Test long strings and check nothing overflows or gets cut off.
Fix Drop in a long pseudo-translated string and confirm buttons, labels, and headings still fit without clipping or overflow.
-
Manual
Show dates, numbers, and currency the way the user's region expects, not one hard-coded format. The same value reads differently around the world.
Fix Format with the user locale, for example Intl.DateTimeFormat and Intl.NumberFormat, instead of hand-building the string.
-
Manual
For carousels, comboboxes, tooltips, and menus, follow the ARIA Authoring Practices: the right keys move focus, focus is managed, and Escape closes them.
Fix Match each custom widget to its APG pattern for keyboard, focus, and roles, then test it with a keyboard and screen reader.
-
Manual
While a dialog is open, keep focus inside it and make the page behind it inert. When it closes, send focus back to whatever opened it, and close on Escape.
Fix Hold focus within the open dialog, mark the background inert, close on Escape, and move focus back to the trigger on close.
-
Advisory
Your UI still has to work when Windows High Contrast or forced-colors mode is on. Do not rely on backgrounds or borders that vanish in those modes.
Fix Test in forced-colors mode and add a forced-colors media block so borders, icons, and states stay visible.
-
Advisory
Each component should say when to use it and when not to. A link goes somewhere and a button does something, so do not swap them.
Fix Add a short when-to-use and when-not-to note to each component's docs, and check links and buttons are used for the right job.
-
Automated
Build it to match the spec exactly, using your tokens, with responsive behaviour, translation support, and docs. Send it through a reviewed pull request, never straight to main.
Fix Ship every component change as a PR that includes tokens, responsive states, and updated docs, with no direct pushes to main.
-
Automated
Run Stylelint as an error in your build to block raw hex colours and !important, limit units, and require your token naming. That makes using tokens the only easy path.
Fix Add Stylelint at error severity to CI and fail the build on raw colours and anything that breaks the token naming.
-
Automated
Set Style Dictionary to treat warnings as errors so a broken reference or a clashing value or name stops the build, instead of quietly shipping wrong output.
Fix Set the build logger to error and add a check that fails if the committed CSS no longer matches the token source.
QA 0/11
Before sign-off. Automated gates, then the manual and assistive-tech pass machines cannot do.
-
Automated
Run axe-core in your build and stop the build on any real violation: weak contrast, unnamed links or buttons, missing image alt, missing labels, no page title, no lang. Log the needs-review hits as warnings, not fails.
Fix Add axe in a headless browser to your build and fail it on any violation. Keep needs-review hits as warnings you read by hand.
-
Automated
Run Lighthouse in your build and require a top accessibility score for the checks it can measure automatically. Use error to stop the build and warn for softer budgets.
Fix Add Lighthouse CI with an accessibility check against your live or staged build, and fail when the score drops.
-
Automated
Run a browser test that fails if anything spills past the screen width at each breakpoint. Check that tap targets are big enough wherever you can measure them in the page.
Fix Loop over elements at 375, 768 and 1440px in Playwright and fail the build on any overflow past the viewport.
-
Advisory
At 320px wide (the same as 1280px zoomed to 400 percent) the page reflows with no sideways scrolling and nothing lost. Also check it reads fine at 200 percent text zoom and in high-contrast and inverted modes.
Fix Zoom to 400 percent and to 200 percent text, then fix anything that forces sideways scrolling or gets clipped.
-
Manual
Run the page with a screen reader and the keyboard, and judge what no tool can: is the alt text useful, is focus order sensible, does the spacing and type feel right, is the copy clear. A scanner alone never proves you meet WCAG.
Fix Run your core flows with VoiceOver and the keyboard, and fix what the automated gate cannot see.
-
Advisory
Keep every word, action and element meaning the same thing across the whole product, and follow the platform's normal conventions so people are not surprised.
Fix Audit your labels and components across screens and unify anything that has drifted out of sync.
-
Advisory
Run screenshot comparisons to flag unexpected visual changes, but treat them as a heads-up only. Pin the test machine, tune the diff threshold and hide moving content, or you get false alarms.
Fix Capture your baselines on a fixed setup and review each diff as a prompt to look, not a hard build failure.
-
Advisory
View the screen through protanopia, deuteranopia and tritanopia filters. Status and data colours must still be tellable apart for people who cannot see certain hues.
Fix Run Color Oracle over each view and add a label, icon or pattern wherever two colours blur into one.
-
Advisory
Turn on Windows High Contrast mode (or emulate forced-colors in the browser) and confirm every control, border and icon stays visible and usable when the system swaps your colours out.
Fix Switch on forced-colors and fix anything that vanishes; lean on system colour keywords and borders, not background images.
-
Automated
Keep largest content paint under 2.5 seconds, interaction delay under 200 milliseconds, and layout shift under 0.1. Set those three as budgets in Lighthouse so a regression fails the build.
Fix Add Lighthouse CI budgets for LCP, INP and CLS, and fail the build when any of the three slips past its limit.
-
Manual
Before sign-off, read every bit of text for plain language and one steady voice. A scanner cannot judge tone, so a person has to do this pass.
Fix Read the screen aloud, cut jargon and filler, and make the wording sound like one person wrote it all.
Pre-ship 0/5
The gate before merge or release. Required checks, visual regression, a definition of done.
-
Automated
Make the accessibility and visual checks required on every pull request, and run a designer-led QA pass against a shared definition of done before you call it stable.
Fix Mark the gates as required branch checks. Write down your definition of done and review each change against it.
-
Automated
Set automated limits on contrast and on speed (how fast the page first paints, how heavy your files are) so a slow or low-contrast regression fails the build instead of slipping through.
Fix Add Lighthouse CI checks for the categories and budgets you care about. Fail the build when a budget is blown.
-
Manual
Treat your design-system components as a starting point, not proof the page is accessible. Test the real assembled page with a screen reader and keyboard against WCAG 2.2 AA before you release.
Fix Book a screen-reader and keyboard pass on the finished page, not just the components on their own.
-
Advisory
Write down which browsers and devices you support, then actually test on each one before release. Do not assume it works everywhere because it works on your machine.
Fix List your supported browsers and devices in the README, then open the key flows on each and fix what breaks.
-
Advisory
Your layout works whether the screen is upright or sideways. Do not lock it to one orientation, and make sure nothing breaks or cuts off when someone rotates their phone or tablet.
Fix Rotate a phone and tablet through both orientations and fix anything that clips or breaks. Only lock orientation when the content truly needs it.
Post-launch 0/7
After release. Keep docs, design files, and the checklist itself in lockstep.
-
Manual
When you ship a change, announce it and update the docs and design files in the same commit. Keep your definition of done current, and fix it whenever a bug slips through.
Fix Every time you ship, edit the doc, the design file, and the checklist together. Never let one lag behind.
-
Manual
After editing naming rules in the design-system skill or CLAUDE.md, re-test in a new Claude conversation (the edit session gives a false pass). The skill-sync gate also blocks token/scale drift in those files.
Fix Open a brand-new Claude Code session after any skill or CLAUDE.md edit and verify the skill behaves as expected before merging.
-
Manual
After launch, keep checking the live product for quality slips, and watch whether people adopt it: are bug reports dropping, are installs going up.
Fix Track how often bugs escape and how many teams use each component. Feed what you learn back into the next round of planning.
-
Advisory
Put the checklist or tool on GitHub with contributor docs and a code of conduct, so anyone can fork it, fix mistakes, and add to it.
Fix Make the source public, invite issues and pull requests, and give it a version number.
-
Manual
Number every release major.minor.patch so people know at a glance if an update is safe: bump major for breaking changes, minor for new features, patch for fixes.
Fix Tag releases as major.minor.patch. Raise the major number any time you break how something already works.
-
Manual
Write a changelog for every release that lists what changed. When a change breaks existing work, spell out the exact steps to move over.
Fix Keep a changelog grouped by added, changed, and fixed. For any breaking change, write the migration steps right there.
-
Manual
When you retire a component or token, announce it with a removal date and a clear path to the replacement. Give people time, and never just delete it.
Fix Mark the old thing as deprecated, name its replacement, and set a removal date. Remove it only after that date passes.