product-ui · git:20261027.0084070 · 2026-10-27 · sha256 f4528a9e733b549d
product-ui git:20261027.0084070A
Immutable. This exact content never changes and is served at /api/v1/blob/f4528a9e733b549d.
--- name: product-ui description: Make product screens look designed, not templated - dashboards, a map or canvas with side panels, data views, detail pages, forms and flows, lists, mobile screens. Use whenever you build or change an app screen, a view or a component in web/ (the landing hero and the visual direction itself are design-taste-frontend). Covers layout recipes, hierarchy, craft, the 3-second judge test and the design-lint gate. --- # Product UI · screens that look designed `design-taste-frontend` is for landings, portfolios and the visual direction: it says so on line 1. App screens are this skill. Why (Chilangatón, a 7-hour sprint): the first UI was a column of white boxes with gray borders, raw `stone-*`/`emerald-*` classes, every label `text-lg font-semibold`, and each view with its own badge and toggle. It was redone from scratch 3 hours in, and the team nearly lost on it. ## 0. Before the first line 1. Read `web/DESIGN.md` and open the locked screenshot in `web/public/design-lock/`. Your screen must look like the same product as that image. 2. Build from the UI kit (`web/src/lib/ui`, `web/src/lib/map`). A piece is missing? Ask its owner (`uak msg <design task> --kind request "component · variant · why"`). Never a local copy: copies drift. 3. Name the screen's one job and its hero (the map, the number, the route, the form) in one line of the PR. ## 1. Accessibility is a floor, not a style AA contrast, 16–18 px body, 44–48 px targets, visible focus, plain language and the reduced-motion path are mandatory. They never mean gray, flat or a government-form look. A social-impact or public-sector brief is still a product judged in 3 seconds on a projector. Use GOV.UK or USWDS only when the human asks for them. ## 2. Pick one layout recipe per screen | Screen | Recipe | |---|---| | Map or canvas + controls | The hero is full-bleed: no border, no card around it. One panel of 360–420 px at 1280 wide, ONE surface (solid or `glass`). Sections are separated by 24–32 px of space or a hairline, never a box each. Legend big, on the map. | | Dashboard | One hero metric (display font, 48–72 px) and 2–4 supporting stats in a row, then one primary chart. Never a grid of 9 equal cards. | | Detail / profile | A header band with the identity (name, mark, status chip, the primary action), then 2/3 main content and 1/3 facts. | | Flow / form | One step or one group at a time, with a progress indicator. Labels above full-width inputs, the primary action sticky at the bottom. | | List / results | Rows, not cards, past 6 items. Each row: a leading visual (icon, thumbnail or number), the title, meta in secondary text, a trailing value or action. | | Empty, loading, error | Designed like the screen: skeletons shaped like the content, an empty state with one sentence and one action, an error that says the fix. | ## 3. Hierarchy in five rules 1. **Three text levels per screen:** display (headline or hero number), body, secondary. Not six sizes of semibold. 2. **Size, weight and space carry hierarchy, not boxes.** One level of container at most: a card never sits in a card, and a panel's sections are not cards. 3. **One primary action per screen** in the brand accent; the rest secondary or ghost. 4. **Color has a job:** accent = action or brand moment; semantic colors = data states; neutrals = everything else. Only tokens: raw palette classes and hex in feature code fail `design-lint`. 5. **The most important number is the biggest thing on the screen:** tabular figures, unit, label and source. ## 4. Craft that separates designed from templated - Spacing from the token scale (4/8 grid). Use 3–4 steps and the same padding in every panel. - One radius family (for example 12 / 20 / 28). Soft layered shadows; borders only as 1 px low-contrast hairlines. - The display font for headings (tight tracking), the body font for the rest: the pair in `DESIGN.md`. - One icon set (Phosphor), one size and one stroke. No emoji as icons. - Navigation with presence: brand mark, a pill or segmented control for views, depth (a surface or blur). A white bar with a gray border and text links reads "admin template". - Motion with a reason: the hero enters, actions answer, state changes animate in 150–300 ms. Respect `prefers-reduced-motion`. - Real content from the fixtures: real names, places and numbers. Never "Lorem", "Item 1" or "Sin dato" walls. ## 5. The 3-second judge test, before every UI PR Screenshot the screen at 1280×720 (`webapp-testing`), look at it for 3 seconds, then answer: 1. What is this screen and what do I do here? 2. Is the hero the biggest and most colorful thing? 3. Could it pass for a Linear, Stripe or Airbnb-level product, or does it look like an admin template, a government form or default Tailwind? The second answer is a P1: fix it before review. 4. Put it next to one other screen of the product: same product? Then run `bash .uak/bin/design-lint`, and the `design-critic` subagent. ## 6. Seen in real events: each one cost a redo | Seen | Do instead | |---|---| | A side panel as a stack of white boxes with gray borders | One surface; sections by space or hairlines | | `text-lg font-semibold` on every label | Three text levels | | `stone-*` / `gray-*` plus one hand-typed orange | Tokens | | Each view with its own badge, button or toggle | The UI kit's components | | Tiny legend and labels on the map | A big legend with a labeled scale, on the map | | A header that is a white bar with links | Brand mark, pill navigation, depth | ## 7. The gate `bash .uak/bin/design-lint` fails on raw palette classes, hex colors and local copies of UI kit components in `web/src` (outside the UI kit and the stylesheets). A deliberate exception carries `design-lint: ok` and the reason on the same line, for example a map paint color read once from a token. The stack's smoke and `design-critic` run it.