fe-guardrails
Skill8 starsChanged 12 days agoMITView on GitHub
Use before writing or reviewing React or Next.js code that fetches data, renders pickers, selects, or tables, submits forms, or shows errors, and when building or wiring a screen ("build màn", "wire API vào màn", "nối API").
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 9 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈9
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 14
Only when no route exists, get the design from the design source (e.g.
- Distinctive: line 17
Do not "improve" existing UI without permission.
- Distinctive: line 22
Every async UI has a loading state (spinner, skeleton, disabled while pending) and an empty-state placeholder.
- Distinctive: line 44
Use the project's single error-parsing helper.
- Very specific: line 46
Do not close a dialog on validation errors.
- Distinctive: line 48
Keep existing client-side validation conditions exactly.
- Distinctive: line 50
Add a structural test that scans forms and fails when a new form neither uses the shared inline-error path nor is allowlisted with a reason.
- Distinctive: line 54
Prefer the exact copy from the design or spec.
- Distinctive: line 56
Use the user's words, not system terms: "Notifications", not "Webhook config".
- Distinctive: line 60
Avoid these AI tells in copy and layout:
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
fe-guardrails
Before building a screen
- Search the repo first. Many screens already exist (often on mock data with a "swap for the real API later" comment).
lsthe routes and grep the module name before concluding a screen or design is missing; the job is often to wire the API into an existing screen, not build a new one. - Only when no route exists, get the design from the design source (e.g. Figma MCP); if it is unavailable, ask instead of inventing a layout.
- Match the design exactly. Deviate only where the spec requires it, and record each deviation and why. Do not "improve" existing UI without permission.
- Shared components first. Any repeated element (input, field, card, dialog, table, badge) lives in the shared UI folder; pages only compose.
Loading, empty, and error states
- Every async UI has a loading state (spinner, skeleton, disabled while pending) and an empty-state placeholder.
- Never
query.data ?? []in a picker/select/table without anisErrorbranch. It collapses 200-empty, 403, and 500 into the same empty list with an enabled control, and the user never learns why. A read error stays on screen (inline alert or error section), not in a toast. - A query with
enabled: falseis not pending; do not render "Loading..." forever. - Disable submit while pending; a double click must not create two rows.
Form errors: exactly three groups
- Message about one field -> inline under that field,
aria-invalidon the control, stays until the user edits that field. Includes client-side gates and backend rejections whose key maps to a field rendered on screen. - Message not about any rendered field -> one error toast (no key, unknown key, 403/404/409 without a field, 500, network). Split mixed rejections: field parts inline, the rest in the toast; never show the same sentence in both, never drop one.
- Action result (Created/Updated/Deleted successfully) -> toast, never inline.
Rules:
- Map backend keys to field ids only from evidence (contracts, schemas, service code); never guess, never map to a conditionally rendered field. Unmappable messages go to the toast.
- The data layer must keep the error body.
throw new Error(messageOf(body))flattens it before the form can see the keys, and every inline wiring above becomes dead code. Throw a typed error that carriesstatusandbody. - Use the project's single error-parsing helper; never write a second parser or humanizer.
- Show the backend's message verbatim; write your own only when the backend sends none.
- Do not close a dialog on validation errors; never swallow a rejection with an empty
.catch(). - Multi-step wizards navigate to the step of the first error; long forms scroll the first error into view.
- Keep existing client-side validation conditions exactly; changing what is enforced is a spec change, so ask.
<Alert>/banners remain for non-submit states (load errors, missing permission, static guidance); toasts disappear and cannot hold persistent state.- Add a structural test that scans forms and fails when a new form neither uses the shared inline-error path nor is allowlisted with a reason.
Copy
- Prefer the exact copy from the design or spec; the rules below apply only to copy you write yourself.
- Sentence case, plain English, no raw schema text ("Country must be 100 characters or fewer", not "String must contain at most 100 character(s)").
- Use the user's words, not system terms: "Notifications", not "Webhook config".
- An action keeps one name through the whole flow: a Publish button leads to a "Publish post?" dialog and a "Published" toast, never Submit, Save, or Done.
- An error you write states what happened and what to do next, and never apologizes ("Couldn't save the invoice. Check your connection and try again.", not "Oops, something went wrong").
- An empty state names the next action and offers it ("No clients yet" plus an "Add client" button), not just "No data".
- Avoid these AI tells in copy and layout:
- em dashes and "Word - fragment" labels;
- slop words (seamlessly, effortlessly, unlock, empower, elevate, streamline) and filler taglines that sell instead of explain;
- meta strings joined by middle dots ("A · B · C");
- an arrow appended to link or button text ("View all →");
- all-caps labels and eyebrows.
In this repository27 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- releaseSkill
- ask-or-decideSkill
- axiSkill
- betterstack-logsSkill
- bug-triageSkill
- chrome-devtools-axiSkill
- e2e-verifySkill
- environmentsSkill
- feature-buildSkill
- feature-statusSkill
- flow-traceSkill
- fresh-reviewSkill
- gnhfSkill
- harness-mapSkill
- jira-bug-hunterSkill
- knowledge-placementSkill
- logging-standardSkill
- project-initSkill
- root-causeSkill
- security-passSkill
- server-touchSkill
- stowSkill
- verify-loopSkill
- visionSkill
- worktree-flowSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

