{"id":"5c6b74a1-a3b2-45d7-a849-f3182fb64820","shortId":"8btv9f","kind":"skill","title":"web-interface-guidelines-review","tagline":"Review UI files against accessibility, UX, and performance rules, then output terse findings grouped by file. Use when: (1) Auditing frontend code quality, (2) Enforcing design-system rules in PRs, or (3) Generating actionable file:line compliance reports.","description":"# Web Interface Guidelines Review\n\nAudit frontend files for accessibility, interaction quality, performance, and content rules. Return concise findings in `file:line` format grouped by file, with no preamble.\n\n## When to use\n\n- Use case 1: When you need a fast compliance pass on UI components before merge\n- Use case 2: When a team wants consistent accessibility and interaction quality checks\n- Use case 3: When reviewers need terse, high-signal findings instead of long explanations\n\n## Required tools / APIs\n\n- `rg` (ripgrep) — fast code search across source files\n- `node` (optional) — structured scans and report generation\n- No external API required\n\nInstall options:\n\n```bash\n# Ubuntu/Debian\nsudo apt-get install -y ripgrep nodejs npm\n\n# macOS\nbrew install ripgrep node\n```\n\n## Skills\n\n### basic_usage\n\nRun a pattern-based compliance scan and emit grouped findings.\n\n```bash\n# 1) Choose files (example)\nFILES=\"src/**/*.{vue,js,jsx,html,css}\"\n\n# 2) Run targeted checks (examples)\nrg -n \"<button[^>]*>\\s*(<svg|<i)\" $FILES\nrg -n \"<img(?![^>]*\\balt=)\" -P $FILES\nrg -n \"transition\\s*:\\s*all\" -P $FILES\nrg -n \"outline-none|outline:\\s*none\" -P $FILES\nrg -n \"onPaste\\s*=\\s*\\{[^}]*preventDefault\" -P $FILES\nrg -n \"user-scalable\\s*=\\s*no|maximum-scale\\s*=\\s*1\" -P $FILES\n```\n\n**Node.js:**\n\n```javascript\nconst { execSync } = require('node:child_process');\n\nconst checks = [\n  { rule: 'icon button missing aria-label', cmd: \"rg -n \\\"<button[^>]*>\\\\s*(<svg|<i)\\\" src\" },\n  { rule: 'image missing alt', cmd: \"rg -n -P \\\"<img(?![^>]*\\\\balt=)\\\" src\" },\n  { rule: 'transition: all used', cmd: \"rg -n -P \\\"transition\\\\s*:\\\\s*all\\\" src\" },\n  { rule: 'outline removed without replacement', cmd: \"rg -n -P \\\"outline-none|outline:\\\\s*none\\\" src\" }\n];\n\nfunction runCheck({ rule, cmd }) {\n  try {\n    const out = execSync(cmd, { encoding: 'utf8' }).trim();\n    if (!out) return [];\n    return out.split('\\n').map((line) => {\n      const [file, lineNo] = line.split(':');\n      return `${file}:${lineNo} - ${rule}`;\n    });\n  } catch {\n    return [];\n  }\n}\n\nconst findings = checks.flatMap(runCheck);\nif (!findings.length) {\n  console.log('✓ pass');\n} else {\n  console.log(findings.join('\\n'));\n}\n```\n\n### robust_usage\n\nRun a broader review using grouped output, anti-pattern checks, and severity tags.\n\n```bash\n# Save report in required style (grouped by file)\nnode scripts/review-ui-guidelines.js \"src/**/*.{vue,js,jsx,html,css}\" > ui-guidelines-report.txt\ncat ui-guidelines-report.txt\n```\n\n**Node.js:**\n\n```javascript\nconst { execSync } = require('node:child_process');\n\nconst inputGlob = process.argv[2] || 'src/**/*.{vue,js,jsx,html,css}';\n\nconst checks = [\n  { id: 'a11y-icon-label', label: 'icon button missing aria-label', pattern: '<button[^>]*>\\\\s*(<svg|<i)' },\n  { id: 'a11y-input-label', label: 'input lacks label/aria-label', pattern: '<input(?![^>]*(aria-label|id=|name=))' },\n  { id: 'a11y-img-alt', label: 'image missing alt', pattern: '<img(?![^>]*\\\\balt=)' },\n  { id: 'focus-outline', label: 'outline removed without focus replacement', pattern: 'outline-none|outline:\\\\s*none' },\n  { id: 'anim-all', label: 'transition: all → list properties', pattern: 'transition\\\\s*:\\\\s*all' },\n  { id: 'paste-block', label: 'onPaste preventDefault anti-pattern', pattern: 'onPaste\\\\s*=\\\\s*\\\\{[^}]*preventDefault' },\n  { id: 'zoom-block', label: 'zoom disabled (user-scalable=no or maximum-scale=1)', pattern: 'user-scalable\\\\s*=\\\\s*no|maximum-scale\\\\s*=\\\\s*1' },\n  { id: 'click-div', label: 'click handler on div/span should be button', pattern: '<(div|span)[^>]*onClick=' }\n];\n\nfunction grep(pattern) {\n  try {\n    const cmd = `rg -n -P \"${pattern}\" ${inputGlob}`;\n    const out = execSync(cmd, { encoding: 'utf8' }).trim();\n    return out ? out.split('\\n') : [];\n  } catch {\n    return [];\n  }\n}\n\nconst grouped = new Map();\n\nfor (const check of checks) {\n  for (const hit of grep(check.pattern)) {\n    const first = hit.indexOf(':');\n    const second = hit.indexOf(':', first + 1);\n    if (first === -1 || second === -1) continue;\n\n    const file = hit.slice(0, first);\n    const line = hit.slice(first + 1, second);\n    const finding = `${file}:${line} - ${check.label}`;\n\n    if (!grouped.has(file)) grouped.set(file, []);\n    grouped.get(file).push(finding);\n  }\n}\n\nif (!grouped.size) {\n  console.log('✓ pass');\n  process.exit(0);\n}\n\nfor (const [file, items] of grouped.entries()) {\n  console.log(`## ${file}`);\n  console.log('');\n  for (const item of items) console.log(item);\n  console.log('');\n}\n```\n\n## Vue + Tailwind report view (optional)\n\nUse this lightweight UI when you want readable review output in-browser.\n\n```vue\n<template>\n  <a href=\"#main\" class=\"sr-only focus:not-sr-only focus:absolute focus:left-4 focus:top-4 focus:z-50 focus:rounded focus:bg-white focus:px-3 focus:py-2 focus:ring-2 focus:ring-slate-500\">Skip to Main Content</a>\n\n  <main id=\"main\" class=\"mx-auto max-w-4xl p-4 sm:p-6 text-slate-900\">\n    <h1 class=\"text-2xl font-semibold text-balance\">Web Interface Guidelines Report</h1>\n\n    <p aria-live=\"polite\" class=\"mt-2 text-sm text-slate-600\">\n      {{ loading ? 'Loading…' : `${groups.length} files checked` }}\n    </p>\n\n    <section v-if=\"!loading && groups.length === 0\" class=\"mt-6 rounded border border-emerald-200 bg-emerald-50 p-4\">\n      <p class=\"font-medium\">✓ pass</p>\n    </section>\n\n    <section v-for=\"group in groups\" :key=\"group.file\" class=\"mt-6 rounded border border-slate-200 bg-white p-4 shadow-sm\">\n      <h2 class=\"text-lg font-semibold text-wrap-balance\">{{ group.file }}</h2>\n      <ul class=\"mt-3 space-y-2\">\n        <li v-for=\"item in group.items\" :key=\"item\" class=\"min-w-0 break-words rounded bg-slate-50 px-3 py-2 font-mono text-sm tabular-nums\">\n          {{ item }}\n        </li>\n      </ul>\n    </section>\n  </main>\n</template>\n\n<script setup>\nimport { ref, onMounted } from 'vue';\n\nconst loading = ref(true);\nconst groups = ref([]);\n\nonMounted(async () => {\n  try {\n    const res = await fetch('/ui-guidelines-report.json');\n    groups.value = await res.json();\n  } finally {\n    loading.value = false;\n  }\n});\n</script>\n```\n\n## Output format\n\nUse this exact shape.\n\n```text\n## src/Button.vue\n\nsrc/Button.vue:42 - icon button missing aria-label\nsrc/Button.vue:18 - input lacks label\nsrc/Button.vue:55 - animation missing prefers-reduced-motion\nsrc/Button.vue:67 - transition: all → list properties\n\n## src/Modal.vue\n\nsrc/Modal.vue:12 - missing overscroll-behavior: contain\nsrc/Modal.vue:34 - \"...\" → \"…\"\n\n## src/Card.vue\n\n✓ pass\n```\n\nRules for output:\n- Group by file\n- Use `file:line - issue` format\n- Keep text terse, high signal\n- Skip explanation unless fix is non-obvious\n- No preamble\n\n## Agent prompt\n\n```text\nYou have a Web Interface Guidelines Review skill.\n\nWhen the user asks to review frontend files, run rule-based checks across the provided paths and return findings grouped by file.\n\nRequirements:\n1. Follow accessibility, focus, forms, animation, typography, content handling, images, performance, navigation/state, touch, layout, theming, i18n, hydration, hover, and copy rules.\n2. Flag anti-patterns explicitly.\n3. Output ONLY in this format:\n\n## path/to/file\n\npath/to/file:line - concise issue\n\nIf a file has no issues:\n\n## path/to/file\n\n✓ pass\n\nDo not force a framework or language. Prefer Vue + Tailwind examples when a UI example is needed. Avoid TypeScript unless the user explicitly requests it.\n```\n\n## Troubleshooting\n\n**No findings but issues exist:**\n- Symptom: Report shows `✓ pass` unexpectedly\n- Solution: Expand file glob, include template/style files, and add missing regex checks\n\n**Too many false positives:**\n- Symptom: Findings are noisy or duplicated\n- Solution: Narrow patterns, add context-aware checks, and suppress known-safe paths\n\n## See also\n\n- [../using-web-scraping/SKILL.md](../using-web-scraping/SKILL.md) — Extracting source data from web pages\n- [../city-tourism-website-builder/SKILL.md](../city-tourism-website-builder/SKILL.md) — Building polished static pages quickly\n\n---\n\n## Notes\n\n- Recommended path: `skills/web-interface-guidelines-review/SKILL.md`\n- Keep examples copy-paste runnable in clean environments\n- Prefer semantic HTML first; use ARIA to complement semantics","tags":["web","interface","guidelines","review","open","skills","besoeasy","agent-skills","ai-agents","claude-code","clawdbot","clawdbot-skill"],"capabilities":["skill","source-besoeasy","skill-web-interface-guidelines-review","topic-agent-skills","topic-ai-agents","topic-claude-code","topic-clawdbot","topic-clawdbot-skill","topic-llm-tools","topic-mcp-server","topic-openai","topic-openclaw","topic-vibe-coding","topic-vibecoding"],"categories":["open-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/besoeasy/open-skills/web-interface-guidelines-review","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add besoeasy/open-skills","source_repo":"https://github.com/besoeasy/open-skills","install_from":"skills.sh"}},"qualityScore":"0.505","qualityRationale":"deterministic score 0.51 from registry signals: · indexed on github topic:agent-skills · 111 github stars · SKILL.md body (8,189 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-02T12:55:05.395Z","embedding":null,"createdAt":"2026-04-18T22:11:00.289Z","updatedAt":"2026-05-02T12:55:05.395Z","lastSeenAt":"2026-05-02T12:55:05.395Z","tsv":"'-1':593,595 '/city-tourism-website-builder/skill.md':916,917 '/using-web-scraping/skill.md':908,909 '0':600,627 '1':24,78,174,242,514,527,590,606,788 '12':717 '18':697 '2':29,93,185,399,809 '3':38,106,815 '34':724 '42':689 '55':702 '67':710 'a11y':410,427,443 'a11y-icon-label':409 'a11y-img-alt':442 'a11y-input-label':426 'access':10,53,99,790 'across':127,777 'action':40 'add':878,895 'agent':753 'also':907 'alt':273,445,449 'anim':472,703,793 'anim-al':471 'anti':362,492,812 'anti-pattern':361,491,811 'api':121,139 'apt':147 'apt-get':146 'aria':260,418,437,694,941 'aria-label':259,417,436,693 'ask':767 'audit':25,49 'avoid':851 'awar':898 'balt':200,279,452 'base':166,775 'bash':143,173,368 'basic':160 'behavior':721 'block':487,502 'brew':155 'broader':356 'browser':662 'build':918 'button':192,257,265,415,421,539,691 'case':77,92,105 'cat':386 'catch':338,566 'check':103,188,254,364,407,574,576,676,776,881,899 'check.label':612 'check.pattern':582 'checks.flatmap':342 'child':251,394 'choos':175 'clean':934 'click':530,533 'click-div':529 'cmd':262,274,285,299,313,318,549,558 'code':27,125 'complement':943 'complianc':43,84,167 'compon':88 'concis':61,824 'consist':98 'console.log':346,349,624,634,636,642,644 'const':247,253,315,330,340,390,396,406,548,555,568,573,578,583,586,597,602,608,629,638 'contain':722 'content':58,667,795 'context':897 'context-awar':896 'continu':596 'copi':807,930 'copy-past':929 'css':184,384,405 'data':912 'design':32 'design-system':31 'disabl':505 'div':531,541 'div/span':536 'duplic':891 'els':348 'emit':170 'encod':319,559 'enforc':30 'environ':935 'exact':684 'exampl':177,189,844,848,928 'execsync':248,317,391,557 'exist':864 'expand':871 'explan':118,744 'explicit':814,856 'extern':138 'extract':910 'fals':884 'fast':83,124 'file':8,21,41,51,64,69,129,176,178,196,202,210,220,228,244,331,335,376,598,610,615,617,619,630,635,675,732,734,771,786,828,872,876 'find':18,62,114,172,341,609,621,783,861,887 'findings.join':350 'findings.length':345 'first':584,589,592,601,605,939 'fix':746 'flag':810 'focus':455,461,791 'focus-outlin':454 'follow':789 'forc':836 'form':792 'format':66,681,737,820 'framework':838 'frontend':26,50,770 'function':310,544 'generat':39,136 'get':148 'glob':873 'grep':545,581 'group':19,67,171,359,374,569,730,784 'group.file':678 'grouped.entries':633 'grouped.get':618 'grouped.has':614 'grouped.set':616 'grouped.size':623 'groups.length':674 'guidelin':4,47,670,761 'handl':796 'handler':534 'high':112,741 'high-sign':111 'hit':579 'hit.indexof':585,588 'hit.slice':599,604 'hover':805 'html':183,383,404,938 'hydrat':804 'i18n':803 'icon':256,411,414,690 'id':408,425,439,441,453,470,484,499,528 'imag':271,447,797 'img':199,278,444,451 'in-brows':660 'includ':874 'input':428,431,435,698 'inputglob':397,554 'instal':141,149,156 'instead':115 'interact':54,101 'interfac':3,46,669,760 'issu':736,825,831,863 'item':631,639,641,643,679 'javascript':246,389 'js':181,381,402 'jsx':182,382,403 'keep':738,927 'known':903 'known-saf':902 'label':261,412,413,419,429,430,438,446,457,474,488,503,532,695,700 'label/aria-label':433 'lack':432,699 'languag':840 'layout':801 'lightweight':652 'line':42,65,329,603,611,735,823 'line.split':333 'lineno':332,336 'list':477,713 'load':672,673 'long':117 'maco':154 'main':666 'mani':883 'map':328,571 'maximum':238,512,523 'maximum-scal':237,511,522 'merg':90 'miss':258,272,416,448,692,704,718,879 'motion':708 'n':191,198,204,212,222,230,264,276,287,301,327,351,551,565 'name':440 'narrow':893 'navigation/state':799 'need':81,109,850 'new':570 'node':130,158,250,377,393 'node.js':245,388 'nodej':152 'noisi':889 'non':749 'non-obvi':748 'none':215,218,305,308,466,469 'note':923 'npm':153 'obvious':750 'onclick':543 'onpast':223,489,495 'option':131,142,649 'out.split':326,564 'outlin':214,216,295,304,306,456,458,465,467 'outline-non':213,303,464 'output':16,360,659,680,729,816 'overscrol':720 'overscroll-behavior':719 'p':201,209,219,227,243,277,288,302,552 'page':915,921 'pass':85,347,625,677,726,833,868 'past':486,931 'paste-block':485 'path':780,905,925 'path/to/file':821,822,832 'pattern':165,363,420,434,450,463,479,493,494,515,540,546,553,813,894 'pattern-bas':164 'perform':13,56,798 'polish':919 'posit':885 'preambl':72,752 'prefer':706,841,936 'prefers-reduced-mot':705 'preventdefault':226,490,498 'process':252,395 'process.argv':398 'process.exit':626 'prompt':754 'properti':478,714 'provid':779 'prs':36 'push':620 'qualiti':28,55,102 'quick':922 'readabl':657 'recommend':924 'reduc':707 'regex':880 'remov':296,459 'replac':298,462 'report':44,135,370,647,671,866 'request':857 'requir':119,140,249,372,392,787 'return':60,324,325,334,339,562,567,782 'review':5,6,48,108,357,658,762,769 'rg':122,190,197,203,211,221,229,263,275,286,300,550 'ripgrep':123,151,157 'robust':352 'rule':14,34,59,255,270,281,294,312,337,727,774,808 'rule-bas':773 'run':162,186,354,772 'runcheck':311,343 'runnabl':932 'safe':904 'save':369 'scalabl':233,508,518 'scale':239,513,524 'scan':133,168 'scripts/review-ui-guidelines.js':378 'search':126 'second':587,594,607 'see':906 'semant':937,944 'sever':366 'shape':685 'show':867 'signal':113,742 'skill':159,763 'skill-web-interface-guidelines-review' 'skills/web-interface-guidelines-review/skill.md':926 'skip':664,743 'solut':870,892 'sourc':128,911 'source-besoeasy' 'span':542 'src':179,269,280,293,309,379,400 'src/button.vue':687,688,696,701,709 'src/card.vue':725 'src/modal.vue':715,716,723 'static':920 'structur':132 'style':373 'sudo':145 'suppress':901 'svg':194,267,423 'symptom':865,886 'system':33 'tag':367 'tailwind':646,843 'target':187 'team':96 'template/style':875 'ters':17,110,740 'text':686,739,755 'theme':802 'tool':120 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-code' 'topic-clawdbot' 'topic-clawdbot-skill' 'topic-llm-tools' 'topic-mcp-server' 'topic-openai' 'topic-openclaw' 'topic-vibe-coding' 'topic-vibecoding' 'touch':800 'transit':205,282,289,475,480,711 'tri':314,547 'trim':321,561 'troubleshoot':859 'typescript':852 'typographi':794 'ubuntu/debian':144 'ui':7,87,653,847 'ui-guidelines-report.txt':385,387 'unexpect':869 'unless':745,853 'usag':161,353 'use':22,75,76,91,104,284,358,650,682,733,940 'user':232,507,517,766,855 'user-scal':231,506,516 'utf8':320,560 'ux':11 'view':648 'vue':180,380,401,645,663,842 'want':97,656 'web':2,45,668,759,914 'web-interface-guidelines-review':1 'without':297,460 'y':150 'zoom':501,504 'zoom-block':500","prices":[{"id":"d2589b47-f8a6-4dd5-bab4-4b09360ea2e4","listingId":"5c6b74a1-a3b2-45d7-a849-f3182fb64820","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"besoeasy","category":"open-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T22:11:00.289Z"}],"sources":[{"listingId":"5c6b74a1-a3b2-45d7-a849-f3182fb64820","source":"github","sourceId":"besoeasy/open-skills/web-interface-guidelines-review","sourceUrl":"https://github.com/besoeasy/open-skills/tree/main/skills/web-interface-guidelines-review","isPrimary":false,"firstSeenAt":"2026-04-18T22:11:00.289Z","lastSeenAt":"2026-05-02T12:55:05.395Z"}],"details":{"listingId":"5c6b74a1-a3b2-45d7-a849-f3182fb64820","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"besoeasy","slug":"web-interface-guidelines-review","github":{"repo":"besoeasy/open-skills","stars":111,"topics":["agent-skills","ai","ai-agents","claude-code","clawdbot","clawdbot-skill","llm-tools","mcp-server","openai","openclaw","vibe-coding","vibecoding"],"license":null,"html_url":"https://github.com/besoeasy/open-skills","pushed_at":"2026-03-31T13:05:30Z","description":"Battle-tested skill library for AI agents. Save 98% of API costs with ready-to-use code for crypto, PDFs, search, web scraping & more. No trial-and-error, no expensive APIs.","skill_md_sha":"c23261adc9b6dafc8e5186b03a3668161183d8a2","skill_md_path":"skills/web-interface-guidelines-review/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/besoeasy/open-skills/tree/main/skills/web-interface-guidelines-review"},"layout":"multi","source":"github","category":"open-skills","frontmatter":{"name":"web-interface-guidelines-review","description":"Review UI files against accessibility, UX, and performance rules, then output terse findings grouped by file. Use when: (1) Auditing frontend code quality, (2) Enforcing design-system rules in PRs, or (3) Generating actionable file:line compliance reports."},"skills_sh_url":"https://skills.sh/besoeasy/open-skills/web-interface-guidelines-review"},"updatedAt":"2026-05-02T12:55:05.395Z"}}