Ship a Frontend Change
Activated Cloud✓ Officialactivated/ship-frontend-change
Free · MIT
About
Builds or changes user-interface code that fits the existing app: reuse its components, design tokens and data-fetching patterns, handle loading, empty, error and long-content states, keep it accessible by keyboard and screen reader and responsive down to phone width, then verify in a real browser at several widths with a clean console, plus type checks, tests and a production build. Use for UI features, layout fixes and component work in React, Vue, Svelte or plain HTML and CSS. Not for backend endpoints (use design-http-api).
Documentation
Ship a Frontend Change
Frontend work is judged by what people see and do, so it is only done when you have looked at it: in a browser, at desktop and phone widths, with the slow, empty and broken cases exercised, using only the keyboard for at least one pass. It should look like it was always part of the app: the same components, spacing, colours and patterns as the screens around it.
When to use
- "Add a settings page", "show the invoice status in the table", "fix the layout on mobile", "build this component from the design".
- UI bugs: overlapping elements, broken states, wrong copy, flicker, layout shift.
- Turning a design or screenshot into working UI.
What you need
- The request, plus any design file, screenshot or reference (look at images with
vision_analyze). - The repo with its dev server command and test, lint, type-check and build commands.
- Test data or a test account for the screens involved. Do not use real customer accounts without the owner's permission.
- The owner's preferences in
memory(some owners want to check UI themselves before anything is merged; follow that).
Method
Learn the house patterns before writing. Find out, from the code:
- framework, router and where pages live;
- styling system (CSS modules, Tailwind, styled components, plain CSS) and design tokens (colour, spacing, type variables);
- the component library or in-house components;
- state management and data fetching (React Query, SWR, loaders, stores);
- form handling, icons, translations.
Open two screens similar to the one you are building and copy their structure.
search_filesfor an existing component before creating one: a second Button or Modal is a defect.
List the states before coding. For each view or component, decide what it shows when: loading, empty, error (with a retry where it makes sense), success, partial data, very long text and very many items, no permission, offline or slow network, and while a form is submitting. The full checklist is in
references/ui-states-and-a11y.md. Missing states are the most common frontend bug.Build with the existing pieces. Use the design tokens, not raw hex colours or pixel values that differ from the system. Keep components small and focused; keep shared state where the codebase keeps it. Follow the app's data-fetching pattern, and handle errors from every request. Forms: labels for every input, validation messages next to the field, the submit button disabled while submitting, protection against double submission, and Enter submitting where users expect it.
Accessibility as you go, not after.
- Real elements:
<button>for actions,<a href>for navigation,<label>tied to inputs, headings in order, lists as lists, tables for tabular data. - Everything usable by keyboard: Tab order follows the visual order, focus is visible, dialogs trap focus and return it on close, Escape closes overlays.
- Text alternatives: meaningful
alton informative images, emptyalt=""on decorative ones, accessible names on icon-only buttons (aria-label). - Colour contrast at least 4.5:1 for normal text and 3:1 for large text (WCAG AA); never colour alone to convey meaning.
- Use ARIA only when no native element does the job, and then correctly.
- Respect
prefers-reduced-motionfor non-essential animation.
- Real elements:
Responsive by default. Check at roughly 375 px (phone), 768 px (tablet) and 1280 px or wider (desktop). No horizontal scrolling of the page, no text cut off, tap targets at least 24 by 24 CSS pixels (44 is better on touch), tables that scroll inside their container or reflow, images that scale.
Mind performance. Size images and lazy-load those below the fold, avoid layout shift by reserving space for images and async content, avoid unnecessary re-renders in hot lists, and check what a new dependency adds to the bundle before installing it (prefer what the app already has).
Run the checks. Type check, lint, unit or component tests (Testing Library queries by role and label), and a production build: the build often catches errors the dev server tolerates (server rendering, hydration mismatches, tree-shaking problems, environment variables).
Look at it in a real browser.
- Start the dev server in the background (
terminal(background=true)) and open the page withbrowser_navigate. - Inspect with
browser_snapshot(structure and text) andbrowser_vision(how it looks). - Walk the flow with
browser_clickandbrowser_type: the happy path, then each state from step 2 (force the empty and error states with test data or a failing local endpoint). - Check narrow widths with the project's end-to-end tool if it has one (for example a Playwright script with the viewport at 375 px) or the browser's responsive mode.
- Read the browser console and the dev server log: no new errors or warnings.
- Start the dev server in the background (
One keyboard-only pass. Tab through the new UI from the top of the page: can you reach and operate everything, see where focus is, open and close dialogs, submit the form?
Compare with the design or the neighbouring screens. Spacing, alignment, font sizes, colours, icon style and copy tone. Fix differences unless they are deliberate.
Capture evidence. Screenshots of the key states at desktop and phone width for the pull request or the owner. If the owner checks UI changes personally, hand over the URL and what to look at, and wait for their feedback instead of declaring it done.
Output
The code change, plus a note with: what changed for users, the states handled, screenshots (desktop and phone; key states), accessibility checks done, checks run (types, lint, tests, build) with results, and anything not verified (for example a browser you could not test). For example:
Invoices table now shows a status badge (Paid, Overdue, Draft) using the existing `Badge` component and status tokens.
States: loading skeleton (5 rows), empty ("No invoices yet" + Create button), error with Retry, 1,000 rows paginated.
Checked at 375, 768 and 1440 px: table scrolls inside its card on phones; no page-level horizontal scroll.
Keyboard: rows and Retry reachable by Tab, focus visible; badges have text, not colour alone.
Checks: tsc, eslint, vitest (12 new tests) and `npm run build` all exit 0; console clean.
Not verified: Safari (no macOS browser available).
Screenshots: desktop, phone, empty state, error state (attached).
Checks before you finish
- Loading, empty, error and long-content states exist and were seen in the browser.
- The page works at phone and desktop widths without horizontal scrolling.
- A keyboard-only pass works with visible focus; inputs have labels; icon buttons have names.
- Type check, lint, tests and a production build pass; the browser console shows no new errors.
- Existing components and tokens were reused; no near-duplicate components were added.
Pitfalls
- Only building the happy path. Real users hit empty lists, slow networks and failed requests on day one.
- Div soup. Clickable
<div>s are invisible to keyboards and screen readers. Use buttons and links. - Hard-coded colours and sizes. They drift from the design system and break dark mode or theming.
- Testing only at your own width. Most layout bugs live at 375 px.
- Declaring done from the code. Look at it. Then look at it on a phone width.
- A new dependency for a small job. Bundle size and maintenance grow; check what the app already uses.
- Changing shared components casually. A tweak to a shared Button changes every screen. Search for usages and check a few.
Versions
Listed from the source repository.
Reviews
No reviews yet. Be the first.
