agentleFS
VercelKnown publishervercel-labs/web-interface-guidelines/AGENTS.md

web-interface-guidelines

AGENTS.md970 starsChanged 40 days agoMITView on GitHub

Concise rules for building accessible, fast, delightful UIs. Use MUST/SHOULD/NEVER to guide decisions.

  • Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.

    Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.

The file

Show its rules and text

We split this AGENTS.md into the rules it gives an agent

108 rules. About 1 is common, 50 are distinctive, and 57 are very specific to this project.

  • ≈1

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈50

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 57

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    MUST: Full keyboard support per WAI-ARIA APG

    line 7
  2. Very specific:

    MUST: Visible, unobscured focus rings (:focus-visible.

    line 8
  3. Distinctive:

    MUST: Manage focus (trap, move, return) per APG patterns

    line 9
  4. Very specific:

    NEVER: outline: none without visible focus replacement

    line 10
  5. Distinctive:

    MUST: Hit target ≥24px (mobile ≥44px).

    line 14
  6. Very specific:

    MUST: Mobile <input> font-size ≥16px to prevent iOS zoom

    line 15
  7. Very specific:

    NEVER: Disable browser zoom (user-scalable=no, maximum-scale=1)

    line 16
  8. Very specific:

    MUST: touch-action: manipulation to prevent double-tap zoom

    line 17
  9. Very specific:

    SHOULD: Set -webkit-tap-highlight-color to match design

    line 18
  10. Distinctive:

    MUST: Hydration-safe inputs (no lost focus/value)

    line 22
  11. Very specific:

    NEVER: Block paste in <input>/<textarea>

    line 23
  12. Distinctive:

    MUST: Loading buttons show spinner and keep original label

    line 24
  13. Very specific:

    MUST: Enter submits focused input.

    line 25
  14. Distinctive:

    MUST: Keep submit enabled until request starts.

    line 26
  15. Distinctive:

    MUST: Accept free text, validate after—don't block typing

    line 27
  16. Distinctive:

    MUST: Allow incomplete form submission to surface validation

    line 28
  17. Distinctive:

    MUST: Errors inline next to fields.

    line 29
  18. Very specific:

    MUST: autocomplete + meaningful name.

    line 30
  19. Very specific:

    SHOULD: Disable spellcheck for emails/codes/usernames

    line 31
  20. Very specific:

    SHOULD: Placeholders end with … and show example pattern

    line 32
  21. Distinctive:

    MUST: Warn on unsaved changes before navigation

    line 33
  22. Common:

    MUST: Compatible with password managers & 2FA.

    line 34
  23. Distinctive:

    MUST: Trim values to handle text expansion trailing spaces

    line 35
  24. Distinctive:

    MUST: No dead zones on checkboxes/radios.

    line 36
  25. Very specific:

    MUST: URL reflects state (deep-link filters/tabs/pagination/expanded panels)

    line 40
  26. Distinctive:

    MUST: Back/Forward restores scroll position

    line 41
  27. Very specific:

    MUST: Links use <a>/<Link> for navigation (support Cmd/Ctrl/middle-click)

    line 42
  28. Very specific:

    NEVER: Use <div onClick> for navigation

    line 43
  29. Distinctive:

    SHOULD: Optimistic UI; reconcile on response.

    line 47
  30. Distinctive:

    MUST: Confirm destructive actions or provide Undo window

    line 48
  31. Very specific:

    MUST: Use polite aria-live for toasts/inline validation

    line 49
  32. Very specific:

    SHOULD: Ellipsis (…) for options opening follow-ups ("Rename…") and loading states ("Loading…")

    line 50
  33. Distinctive:

    MUST: Generous targets, clear affordances.

    line 54
  34. Distinctive:

    MUST: Delay first tooltip.

    line 55
  35. Very specific:

    MUST: overscroll-behavior: contain in modals/drawers

    line 56
  36. Very specific:

    SHOULD: When suppressing page rubber-band bounce, set overscroll-behavior: none on <html> inside @media (pointer: fine).

    line 57
  37. Very specific:

    MUST: During drag, disable text selection and set inert on dragged elements

    line 58
  38. Very specific:

    MUST: Drag/swipe/pinch/path gestures have a tap/click and keyboard alternative unless essential

    line 59
  39. Distinctive:

    MUST: If it looks clickable, it must be clickable

    line 60
  40. Distinctive:

    SHOULD: Autofocus on desktop with single primary input.

    line 64
  41. Very specific:

    MUST: Honor prefers-reduced-motion (provide reduced variant or disable)

    line 68
  42. Distinctive:

    SHOULD: Prefer CSS > Web Animations API > JS libraries

    line 69
  43. Very specific:

    MUST: Animate compositor-friendly props (transform, opacity) only

    line 70
  44. Very specific:

    NEVER: Animate layout props (top, left, width, height)

    line 71
  45. Very specific:

    NEVER: transition: all—list properties explicitly

    line 72
  46. Distinctive:

    SHOULD: Animate only to clarify cause/effect or add deliberate delight

    line 73
  47. Very specific:

    SHOULD: Choose easing to match the change (size/distance/trigger)

    line 74
  48. Distinctive:

    MUST: Animations interruptible and input-driven.

    line 75
  49. Distinctive:

    MUST: Autoplay motion >5s alongside other content has pause, stop, or hide controls

    line 76
  50. Very specific:

    MUST: Correct transform-origin (motion starts where it "physically" should)

    line 77
  51. Very specific:

    MUST: SVG transforms on <g> wrapper with transform-box: fill-box

    line 78
  52. Distinctive:

    SHOULD: Optical alignment.

    line 82
  53. Very specific:

    MUST: Deliberate alignment to grid/baseline/edges—no accidental placement

    line 83
  54. Very specific:

    SHOULD: Balance icon/text lockups (weight/size/spacing/color)

    line 84
  55. Distinctive:

    MUST: Verify mobile, laptop, ultra-wide (simulate ultra-wide at 50% zoom)

    line 85
  56. Very specific:

    MUST: Respect safe areas (env(safe-area-inset-*))

    line 86
  57. Distinctive:

    MUST: Avoid unwanted scrollbars.

    line 87
  58. Distinctive:

    SHOULD: Flex/grid over JS measurement for layout

    line 88
  59. Distinctive:

    SHOULD: Inline help first.

    line 92
  60. Distinctive:

    MUST: Skeletons mirror final content to avoid layout shift

    line 93
  61. Very specific:

    MUST: <title> matches current context

    line 94
  62. Distinctive:

    MUST: No dead ends; always offer next step/recovery

    line 95
  63. Very specific:

    MUST: Design empty/sparse/dense/error states

    line 96
  64. Very specific:

    SHOULD: Curly quotes (“ ”).

    line 97
  65. Very specific:

    MUST: font-variant-numeric: tabular-nums for number comparisons

    line 98
  66. Distinctive:

    MUST: Redundant status cues (not color-only).

    line 99
  67. Distinctive:

    MUST: Accessible names exist even when visuals omit labels

    line 100
  68. Very specific:

    MUST: Use … character (not ...)

    line 101
  69. Very specific:

    MUST: scroll-margin-top on headings.

    line 102
  70. Very specific:

    MUST: Resilient to user-generated content (short/avg/very long)

    line 103
  71. Very specific:

    MUST: Locale-aware dates/times/numbers (Intl.DateTimeFormat, Intl.NumberFormat)

    line 104
  72. Very specific:

    SHOULD: translate="no" on brand names, code tokens, & identifiers to prevent garbled auto-translation

    line 105
  73. Very specific:

    MUST: Accurate aria-label.

    line 106
  74. Very specific:

    MUST: Icon-only buttons have descriptive aria-label

    line 107
  75. Very specific:

    MUST: Prefer native semantics (button, a, label, table) before ARIA

    line 108
  76. Very specific:

    MUST: Media has captions/transcripts/descriptions as applicable.

    line 109
  77. Very specific:

    MUST: Non-breaking spaces: 10&nbsp;MB, ⌘&nbsp;K, brand names

    line 110
  78. Very specific:

    MUST: Text containers handle long content (truncate, line-clamp-*, break-words)

    line 114
  79. Very specific:

    MUST: Flex children need min-w-0 to allow truncation

    line 115
  80. Distinctive:

    MUST: Handle empty states—no broken UI for empty strings/arrays

    line 116
  81. Distinctive:

    SHOULD: Test iOS Low Power Mode and macOS Safari

    line 120
  82. Distinctive:

    MUST: Measure reliably (disable extensions that skew runtime)

    line 121
  83. Distinctive:

    MUST: Track and minimize re-renders (React DevTools/React Scan)

    line 122
  84. Distinctive:

    MUST: Profile with CPU/network throttling

    line 123
  85. Distinctive:

    MUST: Batch layout reads/writes.

    line 124
  86. Very specific:

    MUST: Mutations (POST/PATCH/DELETE) target <500ms

    line 125
  87. Distinctive:

    SHOULD: Prefer uncontrolled inputs.

    line 126
  88. Distinctive:

    MUST: Virtualize large lists (>50 items)

    line 127
  89. Distinctive:

    MUST: Preload above-fold images.

    line 128
  90. Distinctive:

    MUST: Prevent CLS (explicit image dimensions)

    line 129
  91. Very specific:

    SHOULD: <link rel="preconnect"> for CDN domains

    line 130
  92. Very specific:

    SHOULD: Critical fonts: <link rel="preload" as="font"> with font-display: swap

    line 131
  93. Very specific:

    SHOULD: <video autoplay muted loop playsinline> over animated GIF.

    line 132
  94. Very specific:

    SHOULD: Short non-essential loops include a Safari H.264 MP4 <picture> source, prefers-reduced-motion media condition, and still fallback

    line 133
  95. Very specific:

    MUST: color-scheme: dark on <html> for dark themes

    line 137
  96. Very specific:

    SHOULD: <meta name="theme-color"> matches page background

    line 138
  97. Very specific:

    MUST: Native <select>: explicit background-color and color (Windows fix)

    line 139
  98. Very specific:

    MUST: Inputs with value need onChange (or use defaultValue)

    line 143
  99. Distinctive:

    SHOULD: Guard date/time rendering against hydration mismatch

    line 144
  100. Distinctive:

    SHOULD: Layered shadows (ambient + direct)

    line 148
  101. Distinctive:

    SHOULD: Crisp edges via semi-transparent borders + shadows

    line 149
  102. Distinctive:

    SHOULD: Nested radii: child ≤ parent.

    line 150
  103. Very specific:

    SHOULD: Hue consistency: tint borders/shadows/text toward bg hue

    line 151
  104. Distinctive:

    MUST: Accessible charts (color-blind-friendly palettes)

    line 152
  105. Distinctive:

    MUST: Meet contrast—prefer APCA over WCAG 2

    line 153
  106. Very specific:

    MUST: Increase contrast on :hover/:active/:focus

    line 154
  107. Distinctive:

    SHOULD: Match browser UI to bg

    line 155
  108. Distinctive:

    SHOULD: Avoid dark color gradient banding (use background images when needed)

    line 156

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md 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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

Concise rules for building accessible, fast, delightful UIs. Use MUST/SHOULD/NEVER to guide decisions.

Interactions

Keyboard

  • MUST: Full keyboard support per WAI-ARIA APG
  • MUST: Visible, unobscured focus rings (:focus-visible; group with :focus-within); sticky/fixed elements never cover focus
  • MUST: Manage focus (trap, move, return) per APG patterns
  • NEVER: outline: none without visible focus replacement

Targets & Input

  • MUST: Hit target ≥24px (mobile ≥44px); if visual <24px, expand hit area
  • MUST: Mobile <input> font-size ≥16px to prevent iOS zoom
  • NEVER: Disable browser zoom (user-scalable=no, maximum-scale=1)
  • MUST: touch-action: manipulation to prevent double-tap zoom
  • SHOULD: Set -webkit-tap-highlight-color to match design

Forms

  • MUST: Hydration-safe inputs (no lost focus/value)
  • NEVER: Block paste in <input>/<textarea>
  • MUST: Loading buttons show spinner and keep original label
  • MUST: Enter submits focused input; in <textarea>, ⌘/Ctrl+Enter submits
  • MUST: Keep submit enabled until request starts; then disable with spinner
  • MUST: Accept free text, validate after—don't block typing
  • MUST: Allow incomplete form submission to surface validation
  • MUST: Errors inline next to fields; on submit, focus first error
  • MUST: autocomplete + meaningful name; correct type and inputmode
  • SHOULD: Disable spellcheck for emails/codes/usernames
  • SHOULD: Placeholders end with … and show example pattern
  • MUST: Warn on unsaved changes before navigation
  • MUST: Compatible with password managers & 2FA; allow pasting codes
  • MUST: Trim values to handle text expansion trailing spaces
  • MUST: No dead zones on checkboxes/radios; label+control share one hit target

State & Navigation

  • MUST: URL reflects state (deep-link filters/tabs/pagination/expanded panels)
  • MUST: Back/Forward restores scroll position
  • MUST: Links use <a>/<Link> for navigation (support Cmd/Ctrl/middle-click)
  • NEVER: Use <div onClick> for navigation

Feedback

  • SHOULD: Optimistic UI; reconcile on response; on failure rollback or offer Undo
  • MUST: Confirm destructive actions or provide Undo window
  • MUST: Use polite aria-live for toasts/inline validation
  • SHOULD: Ellipsis (…) for options opening follow-ups ("Rename…") and loading states ("Loading…")

Touch & Drag

  • MUST: Generous targets, clear affordances; avoid finicky interactions
  • MUST: Delay first tooltip; subsequent peers instant
  • MUST: overscroll-behavior: contain in modals/drawers
  • SHOULD: When suppressing page rubber-band bounce, set overscroll-behavior: none on <html> inside @media (pointer: fine); keep coarse-pointer page defaults for pull-to-refresh. Test hybrid touch devices: pointer describes the primary input, and none also disables scroll chaining and native swipe navigation
  • MUST: During drag, disable text selection and set inert on dragged elements
  • MUST: Drag/swipe/pinch/path gestures have a tap/click and keyboard alternative unless essential
  • MUST: If it looks clickable, it must be clickable

Autofocus

  • SHOULD: Autofocus on desktop with single primary input; rarely on mobile

Animation

  • MUST: Honor prefers-reduced-motion (provide reduced variant or disable)
  • SHOULD: Prefer CSS > Web Animations API > JS libraries
  • MUST: Animate compositor-friendly props (transform, opacity) only
  • NEVER: Animate layout props (top, left, width, height)
  • NEVER: transition: all—list properties explicitly
  • SHOULD: Animate only to clarify cause/effect or add deliberate delight
  • SHOULD: Choose easing to match the change (size/distance/trigger)
  • MUST: Animations interruptible and input-driven; autoplay only for muted, non-essential loops
  • MUST: Autoplay motion >5s alongside other content has pause, stop, or hide controls
  • MUST: Correct transform-origin (motion starts where it "physically" should)
  • MUST: SVG transforms on <g> wrapper with transform-box: fill-box

Layout

  • SHOULD: Optical alignment; adjust ±1px when perception beats geometry
  • MUST: Deliberate alignment to grid/baseline/edges—no accidental placement
  • SHOULD: Balance icon/text lockups (weight/size/spacing/color)
  • MUST: Verify mobile, laptop, ultra-wide (simulate ultra-wide at 50% zoom)
  • MUST: Respect safe areas (env(safe-area-inset-*))
  • MUST: Avoid unwanted scrollbars; fix overflows
  • SHOULD: Flex/grid over JS measurement for layout

Content & Accessibility

  • SHOULD: Inline help first; tooltips last resort
  • MUST: Skeletons mirror final content to avoid layout shift
  • MUST: <title> matches current context
  • MUST: No dead ends; always offer next step/recovery
  • MUST: Design empty/sparse/dense/error states
  • SHOULD: Curly quotes (“ ”); avoid widows/orphans (text-wrap: balance)
  • MUST: font-variant-numeric: tabular-nums for number comparisons
  • MUST: Redundant status cues (not color-only); icons have text labels
  • MUST: Accessible names exist even when visuals omit labels
  • MUST: Use … character (not ...)
  • MUST: scroll-margin-top on headings; "Skip to content" link; hierarchical <h1>–<h6>
  • MUST: Resilient to user-generated content (short/avg/very long)
  • MUST: Locale-aware dates/times/numbers (Intl.DateTimeFormat, Intl.NumberFormat)
  • SHOULD: translate="no" on brand names, code tokens, & identifiers to prevent garbled auto-translation
  • MUST: Accurate aria-label; decorative elements aria-hidden
  • MUST: Icon-only buttons have descriptive aria-label
  • MUST: Prefer native semantics (button, a, label, table) before ARIA
  • MUST: Media has captions/transcripts/descriptions as applicable; controls are keyboard-operable; decorative media hidden from assistive tech
  • MUST: Non-breaking spaces: 10&nbsp;MB, ⌘&nbsp;K, brand names

Content Handling

  • MUST: Text containers handle long content (truncate, line-clamp-*, break-words)
  • MUST: Flex children need min-w-0 to allow truncation
  • MUST: Handle empty states—no broken UI for empty strings/arrays

Performance

  • SHOULD: Test iOS Low Power Mode and macOS Safari
  • MUST: Measure reliably (disable extensions that skew runtime)
  • MUST: Track and minimize re-renders (React DevTools/React Scan)
  • MUST: Profile with CPU/network throttling
  • MUST: Batch layout reads/writes; avoid reflows/repaints
  • MUST: Mutations (POST/PATCH/DELETE) target <500ms
  • SHOULD: Prefer uncontrolled inputs; controlled inputs cheap per keystroke
  • MUST: Virtualize large lists (>50 items)
  • MUST: Preload above-fold images; lazy-load the rest
  • MUST: Prevent CLS (explicit image dimensions)
  • SHOULD: <link rel="preconnect"> for CDN domains
  • SHOULD: Critical fonts: <link rel="preload" as="font"> with font-display: swap
  • SHOULD: <video autoplay muted loop playsinline> over animated GIF; provide still/reduced-motion alternative
  • SHOULD: Short non-essential loops include a Safari H.264 MP4 <picture> source, prefers-reduced-motion media condition, and still fallback

Dark Mode & Theming

  • MUST: color-scheme: dark on <html> for dark themes
  • SHOULD: <meta name="theme-color"> matches page background
  • MUST: Native <select>: explicit background-color and color (Windows fix)

Hydration

  • MUST: Inputs with value need onChange (or use defaultValue)
  • SHOULD: Guard date/time rendering against hydration mismatch

Design

  • SHOULD: Layered shadows (ambient + direct)
  • SHOULD: Crisp edges via semi-transparent borders + shadows
  • SHOULD: Nested radii: child ≤ parent; concentric
  • SHOULD: Hue consistency: tint borders/shadows/text toward bg hue
  • MUST: Accessible charts (color-blind-friendly palettes)
  • MUST: Meet contrast—prefer APCA over WCAG 2
  • MUST: Increase contrast on :hover/:active/:focus
  • SHOULD: Match browser UI to bg
  • SHOULD: Avoid dark color gradient banding (use background images when needed)

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

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.