Cursor is at its best when the change sits right next to the code it touches. For interface work that means three things: the actual component, a rule that only speaks when it's relevant, and a review of every state the screen can be in. A form that only looks right when everything goes well isn't finished.
Example task used in this guide: fix an "Add card" form that answers every problem with "Something went wrong" and wipes what the person typed.
Start with the real component
Open the form, the field components it uses and the code that sends the save request, and ask Cursor to explain how validation works today. You're looking for where errors are decided (in the browser, from the server, or both) and why the fields get cleared. Usually it's a reset that runs on every submit, not only on success.
Then name the real problem. In the "before" screen above, the person can't tell what went wrong or what to change, and fixing it means typing everything again. Every decision that follows should serve one goal: show the problem where it is, and keep their work.
Add one scoped project rule
Cursor keeps project rules as .mdc files in .cursor/rules. The frontmatter decides when a rule applies. With globs set to your form files, this rule is attached automatically when Cursor works on a form, and stays out of the way otherwise:
--- description: Form fields, validation and error messages globs: src/components/forms/**, src/app/**/checkout/** alwaysApply: false --- - Reuse the existing Field, Input and Button components. Don't create new ones. - Validate each field when the person leaves it, and again on submit. - Put an error next to the field it's about, in plain words that say how to fix it. - Never clear what the person typed after a failed submit. - Don't rely on color alone: errors have text, and the field is announced as invalid (aria-invalid, aria-describedby). - After a failed submit, move focus to the first field with a problem.
Keep rules short and checkable. "Make forms friendly" can't be verified; "never clear what the person typed after a failed submit" can. Don't count on a long rule being read on every request; scope it to where it matters.
Look up how others handle it
The hard part here is wording and placement: what does a good card error say, and where does it go? With UXKIN connected, Cursor can call find_ui_references with "card error" and get real flows, such as adding a card with a wrong number in Instagram or adding an invalid card in ASOS, with every screen linked.
Ask it to compare two of them on three points: where the message appears, what it says, and what stays filled in. Then have it say which decisions it's adopting. It should borrow the pattern, not the other app's wording or styling. Your components and tone of voice stay yours.
Review the states, not the mockup
Have Cursor run the form and go through each case the way a person would hit it:
- Card number too short: the error sits under that field and says how to fix it.
- Expired card: the expiry field is marked, nothing else changes.
- Declined by the bank: a message near the button explains it's not a typo and suggests another card.
- Network error: a Try again button that keeps every field as it was.
- Success: a clear confirmation, then the form closes or resets.
Do it once with the keyboard only: after a failed submit, focus should land on the first field with a problem, and a screen reader should announce the error. Check a phone width (390px) and a desktop width (1440px).
Set up UXKIN in Cursor
The quickest way is the setup prompt from the Agent SDK tab: paste it into Cursor's agent chat and it does the steps below itself. To do it by hand:
1. Install the no-ui-slop skill
npx skills add https://uxkin.com --skill no-ui-slop -g -a cursor -y
It installs to ~/.agents/skills/no-ui-slop, which Cursor loads in every project.
2. Connect the UXKIN MCP server
Add UXKIN to ~/.cursor/mcp.json (all your projects) or .cursor/mcp.json (one project). This version reads your token from a UXKIN_TOKEN environment variable, so the file is safe to share and commit:
{
"mcpServers": {
"uxkin": {
"url": "https://uxkin.com/mcp",
"headers": {
"Authorization": "Bearer ${env:UXKIN_TOKEN}"
}
}
}
}Set UXKIN_TOKEN to the token from your setup prompt, then restart Cursor. Cursor only sees variables that exist when it starts, and when opened from the Dock or Start menu it may not see ones set in your shell profile: if the token isn't picked up, start Cursor from a terminal with cursor .. If you'd rather not use a variable, you can paste the token in place of ${env:UXKIN_TOKEN}, but then never commit that file or show it in a screenshot.
3. Check it
Open Cursor's MCP settings (Customize in the sidebar) and make sure uxkin is enabled with find_ui_references and find_ui_materials listed. If it doesn't connect, the Output panel's "MCP Logs" view shows why. There's no need for a test search; the next UI task is the test.
A prompt you can use
Adapt it to your own form. It sets the goal, asks one reference question and lists every state to handle:
Fix the error handling in our "Add card" form. Today a failed save shows "Something went wrong", clears every field, and people give up. First, open the form and the Field/Input/Button components it uses, and tell me how validation and the save request work now. If UXKIN is connected, use find_ui_references for "card error" and pick two flows. For each, note: where the error message appears, what it says, and what stays filled in. Say which of those decisions you're adopting. Then: - Validate on leaving a field and on submit; show each error next to its field, saying how to fix it. - Keep everything the person typed after any failure. - Handle: card number too short, expired card, card declined by the bank, network error (with Try again), and success. - Move focus to the first problem after a failed submit, and mark invalid fields for screen readers. Check it at 390px and 1440px, and by keyboard only. Explain each change in one line.
Questions
Should I use Cursor project rules or AGENTS.md?
Either works. Cursor reads AGENTS.md as simple always-on instructions. Project rules in .cursor/rules are better for UI guidance, because a rule can apply only to the files it's about, like your form components, instead of every request.
Where does Cursor keep MCP settings?
In ~/.cursor/mcp.json for all your projects, or .cursor/mcp.json inside a project. Use the global file for UXKIN if you work alone. If you commit the project file, reference the token with ${env:UXKIN_TOKEN} instead of pasting it.
Why doesn't Cursor pick up my UXKIN_TOKEN variable?
Cursor only sees environment variables that exist when it starts. If you set UXKIN_TOKEN in a shell profile, start Cursor from that terminal or set the variable system-wide, then restart Cursor. Its Output panel has an "MCP Logs" view that shows connection errors.
Do I need UXKIN to fix a form like this?
No. The rule, the component and a review of every state do most of the work. References help when you're unsure how to word or place an error, and seeing how two real apps handle it settles that quickly.
Is the card form in this guide real?
No. The before and after screens are illustrations with made-up details. The flows the guide suggests looking up ("card error") are real journeys in the UXKIN library.
Sources and review
Checked against UXKIN's live tools on September 30, 2026. Client apps change their settings screens over time; follow your client's own documentation for the exact steps.
Put it to work
Create your account, choose a plan, then copy your setup prompt and paste it into Claude Code, Cursor, Codex or any MCP client. Every plan includes the complete DESIGN.md for every web pack.