Code review ui
Portable engineering policies for coding agents — git, testing, logging, and language conventions written once and referenced everywhere
npx -y skills add andr-ca/agentharness --skill code-review-uiAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 25 days oldThe repository was created 25 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when reviewing frontend, UI, or component code. Covers accessibility (WCAG AA), state management, bundle size, keyboard navigation, hydration, and rendering performance. Load instead of the general code-review skill for UI-focused reviews.
SKILL.md
5.0 KB, as published. Nobody here has run it
Code Review — UI / Frontend Layer
Focus on accessibility, performance, and correctness at the rendering boundary.
Accessibility (WCAG AA)
- Missing
alttext on images — every<img>needs analtattribute. Decorative images usealt="". Neveralt="image"oralt="photo". - Interactive element is not keyboard-accessible — a
<div onClick>or<span onClick>is not focusable by default. Use<button>or addrole/tabIndexand keyboard event handlers. - Color contrast — text must meet 4.5:1 contrast ratio (3:1 for large text). Check with a contrast analyzer before approving color changes.
- Missing form labels — every
<input>needs a visible<label>oraria-label. Placeholder text is not a substitute. - Inaccessible error messages — form validation errors must be associated with the input (
aria-describedby) and announced to screen readers. - Focus management after state change — modals, dialogs, and popups must move focus to the new content on open and restore it on close.
- Missing ARIA role on custom widget — a custom dropdown, slider, or menu must declare its ARIA role and maintain ARIA state (
aria-expanded,aria-selected, etc.).
State Management
- Server state stored in client state — data fetched from an API stored in
useState/useReducer/Vuex instead of a server state cache (React Query, SWR, Apollo). Leads to stale reads and manual invalidation bugs. - Derived state stored explicitly —
const [fullName, setFullName] = useState(...)whenfullName = firstName + lastNameis derivable. Store the minimum, compute the rest. - State updated without immutability — mutating a React/Vue state object directly (
state.items.push(...)) instead of returning a new reference. Breaks change detection. - Global state for local data — adding to a global store (Redux, Zustand, Pinia) something only one component uses. Use
useState/ component-local state first. - Missing loading / error states — async data fetch with no handling of the pending or error case. The UI silently shows nothing or crashes.
Rendering & Performance
- Missing key on list items — rendering a list without a stable, unique
keyprop. React/Vue useskeyfor reconciliation; missing or array-index keys cause incorrect re-renders. - Unnecessary re-renders — a component re-renders on every parent update because a prop (often an inline object or callback) is recreated each render. Stabilize with
useMemo/useCallback/memo. - Blocking the main thread — expensive computation in a render method or event handler without
requestIdleCallback, a Web Worker, oruseDeferredValue. - Waterfall data fetching — child components that each fetch their own data serially. Hoist fetches to a parent or use parallel queries.
- Layout thrashing — reading and writing DOM properties (e.g.,
element.offsetHeight) in a loop causes repeated reflows. Batch reads before writes.
Bundle Size
- Unguarded heavy import —
import * as moment from 'moment'(300 kB) when only one function is needed. Use a lighter alternative (date-fns) or a named import. - Missing code splitting — a rarely-used heavy route imported eagerly. Use
React.lazy/ dynamicimport()for route-level or feature-flag-gated code. - Polyfill included unconditionally — polyfills for features that target browsers already support. Check
browserslistconfig. - Duplicate dependency — two packages that provide the same thing (e.g.,
lodashandlodash-es, or bothaxiosandfetchwrappers). Pick one.
Hydration & SSR
- Hydration mismatch — rendering different content on the server vs. client (using
window,Date.now(), or random values during SSR). Wrap inuseEffector a client-only boundary. - Missing Suspense boundary — a lazy-loaded component or async data source with no
<Suspense>fallback. Crashes or shows nothing during loading. - Client-only APIs accessed in SSR —
localStorage,document,windowaccessed outside a lifecycle hook oruseEffect. Will throw during server rendering.
See Also
.claude/skills/code-review/SKILL.md— general review checklist for all layers.claude/skills/react-best-practices/SKILL.md— React-specific patterns and hooks rules.claude/skills/accessibility/SKILL.md— detailed WCAG 2.2 accessibility guidance