| name | ux-audit |
| description | Run a UX/UI audit on a web project. Scans for hardcoded CSS values, accessibility violations, design token inconsistencies, and component patterns. Outputs to Figma (canvas API), reveal.js slide deck, or scrollable HTML. Publish to Vercel/Netlify/Surge. Defaults to @rolemodel/optics but configurable for any design system. |
UX/UI Audit Skill
Run structured UX/UI audits on web projects in two sessions:
- Discovery & Review — Scan the codebase, identify findings, and walk through them interactively with the team. This is an internal conversation — collaborative, iterative, and thorough.
- Client Report — After design work is complete (Figma mockups, prototypes), come back to generate the polished client-facing deliverable with real screenshots, video walkthroughs, and interactive embeds.
Output to reveal.js (component-based slide deck), Figma (direct canvas write), or scrollable HTML. Publish to Vercel, Netlify, or Surge. Generate DTCG token JSON only when the audit explicitly needs importable token artifacts.
Workflow Overview
┌─────────────────────────────────────────────────┐
│ SESSION 1: Discovery & Review │
│ │
│ Phase 1: Codebase scan + tech stack detection │
│ Phase 2: Design token mapping │
│ Phase 3: Heuristic audit (10 sections) │
│ Phase 4: Interactive review ← YOU ARE HERE │
│ Walk each finding with the team. │
│ Confirm, reject, reprioritize. │
│ Output: reviewed-findings.json │
│ │
│ ⏸ PAUSE — Design work happens here │
│ Figma mockups, prototypes, redesigns │
│ │
│ SESSION 2: Client Report │
│ │
│ Phase 5: Report generation (reveal/figma/html) │
│ Pull screenshots from Figma designs │
│ Add video walkthrough + interactive │
│ embed if available │
│ Phase 6: Figma deliverables + optional tokens │
│ Phase 7: Publish to web │
└─────────────────────────────────────────────────┘
Prerequisites
Run the setup script from the repo root — it checks everything and tells you what's missing:
./scripts/setup.sh
What's needed:
| Dependency | Required? | Purpose |
|---|
| Claude Code CLI | Yes | Runtime for the skill |
| Node.js 18+ | Yes | Token generation scripts (.mjs) |
| Figma plugin | Recommended | Screenshots, canvas writes, design inspection |
ripgrep (rg) | Optional | Powers scan-hardcoded-values.sh |
GitHub CLI (gh) | Optional | Project search from GitHub in run-audit-agent.sh |
Figma skills used by this audit:
| Skill | When used | Purpose |
|---|
figma-use | Every use_figma call (mandatory) | Loads Plugin API context; skipping it causes hard-to-debug failures |
figma-generate-design | Phase 5–6 (Figma format) | Section-by-section canvas assembly using design system tokens |
figma-create-new-file | Phase 6 (template duplication) | Creates the project-specific audit file from the template |
Without the Figma plugin, the skill still works — it skips Figma-dependent features and uses reveal.js or HTML output instead.
Invocation
Most users only need two commands — one for each session:
| Command | What it does |
|---|
/ux-audit | Session 1: Scans the codebase, maps tokens, runs the heuristic audit, then walks you through each finding interactively. Ends with a reviewed findings file and instructions for the design phase. |
/ux-audit report | Session 2: After design work is done, generates the client-facing report with screenshots, video, and embeds. Offers to publish when complete. |
That's it. Phases run automatically within each session — the user never needs to think about phase numbers.
Advanced: Individual Phase Commands
For power users, CI, or re-running a specific step:
/ux-audit scan
/ux-audit tokens
/ux-audit audit
/ux-audit review
/ux-audit report
/ux-audit figma
/ux-audit publish
Shell Scripts
./scripts/run-audit-agent.sh
./scripts/run-audit-agent.sh ~/Development/my-app --client --reveal
./scripts/publish-report.sh
Audience Mode
Every audit runs in one of two modes. If not specified, ask the user.
/ux-audit --internal — Internal/Technical mode: direct language, developer-focused, names specific code issues, uses severity labels (Critical/High/Medium/Pattern)
/ux-audit --client — Client-facing mode: Uses the "Then / Now / Next" narrative arc from references/team-guide.md. Diplomatic language, frames findings as improvement opportunities, acknowledges existing quality, never paints the project as "bad" or "poorly built." Findings are organized by 4 thematic lenses (Experience Gaps, Visual & Brand Coherence, Modernization Moments, Strategic Opportunities) — NOT by severity. The report should feel like "a magazine, not a bug report."
The mode can also be set in .ux-audit.json via "audience": "internal" or "audience": "client".
Output Format
Three output formats are available. Set via CLI flag or "format" in .ux-audit.json:
| Format | Flag | Description | Best For |
|---|
| reveal | --reveal | Self-contained reveal.js slide deck (HTML + inlined CSS + CDN JS). Arrow keys, swipe, or click to navigate. | Web sharing, presentations, PDF export |
| figma | --figma | Direct write to Figma canvas via Plugin API. Uses the Figma template as the visual structure. | Editable design deliverables, client collaboration |
| html | --html | Scrollable single-page HTML with companion CSS. | Internal reviews, print |
reveal and figma are only valid with --client mode
- Default format is
"reveal" for client mode, "html" for internal mode
reveal format supports PDF export via ?print-pdf query parameter (see reveal.js PDF docs)
figma format requires the Figma Desktop MCP server (b20fbcc1) connected
- All formats support web publishing via
./scripts/publish-report.sh (Vercel, Netlify, or Surge)
See references/tone-guide.md for detailed language rules for each mode.
See references/team-guide.md for the complete client audit philosophy and deliverable structure.
See references/paged-document-handoff.md for the handoff from reviewed findings into a branded paged-document artifact.
See references/figma-workflow.md for the Figma canvas workflow.
Required References
Read these files before beginning any audit phase:
Additional Arguments
Arguments after the phase name are passed as context. For example:
/ux-audit scan app/javascript/stylesheets — scan only that directory
/ux-audit figma gnJ9S1Bf1o8cWIxKpCy1Ec — push to a specific Figma file
Configuration
Look for .ux-audit.json in the project root. If it does not exist, ask the user these questions and create it:
- Audience —
"internal" (developer team) or "client" (external stakeholder). Default: "client".
- Output format —
"reveal" (slide deck), "figma" (canvas write), or "html" (scrollable). Default: "reveal" for client, "html" for internal.
- Target design system — default:
@rolemodel/optics. Accept any CSS framework name.
- Brand primary color — accept hex (#F7BD04), HSL (hsl(46, 97%, 49%)), or "use default"
- Brand font family — default from project's existing CSS
- Portfolio URL — URL to the company portfolio page (for cover image + client logo scraping). Example:
https://rolemodelsoftware.com/portfolio
- Case study URL — URL to the project's case study page (for narrative context). Optional.
- Figma file key — target file, or "create new", or "skip"
- Publish provider —
"vercel" (default), "netlify", or "surge"
- Output directory — default:
dev-tools/ux-audit-output
Config schema:
{
"audience": "client",
"format": "reveal",
"designSystem": {
"name": "optics",
"package": "@rolemodel/optics",
"version": "2.3.0",
"tokenPrefix": "--op-"
},
"brand": {
"name": "ProjectName",
"primaryHue": 46,
"primarySaturation": 97,
"primaryLightness": 49,
"neutralHue": 226,
"neutralSaturation": 5,
"fontFamily": "DM Sans",
"caseStudyUrl": null,
"portfolioUrl": null
},
"figma": {
"fileKey": null,
"templateKey": "iyfRvWyTHSbNYtpBcjuvGg",
"outputMode": "newFile"
},
"publish": {
"provider": "vercel",
"projectName": null
},
"outputDir": "dev-tools/ux-audit-output",
"appUrl": "http://localhost:3000"
}
The audience field accepts "internal" or "client". This controls:
- Report template selection (technical vs client-facing)
- Report structure (severity-based vs Then/Now/Next with 4 thematic lenses)
- Finding language and tone (direct vs diplomatic, "what we observed" + "what this means for users")
- Executive summary framing (stats-driven vs narrative paragraph + callout)
The format field accepts "reveal" (default for client), "figma", or "html":
"reveal" — Component-based HTML slide deck built from the bundled revealjs-template/ assets. Shareable via URL, PDF-exportable via ?print-pdf. Only valid with audience: "client".
"figma" — Direct write to Figma canvas via the Plugin API. Uses the template at figma.templateKey as the visual structure. The agent duplicates the template, then populates it section-by-section. Only valid with audience: "client". Requires Figma Desktop MCP.
"html" — Scrollable single-page HTML with companion CSS file. Works for both audience modes.
The brand.portfolioUrl field (e.g., "https://rolemodelsoftware.com/portfolio") is used to web-scrape the cover image and client logo. The scraper looks for data-framer-background-image-wrapper elements on Framer-built portfolio pages to find the project card with the hero background and logo overlay.
The figma section controls Figma output:
fileKey — Target Figma file for output (or null for new file)
templateKey — Figma template file key (default: "iyfRvWyTHSbNYtpBcjuvGg")
outputMode — "newFile" (duplicate template) or "existingFile" (write to fileKey)
The publish section controls static deployment:
provider — "vercel" (default), "netlify", or "surge"
projectName — override the deployed project name (default: {brand.name}-assessment slugified). This becomes the Vercel subdomain, e.g. rapidair-assessment.vercel.app — keep it clean and client-facing, no internal tool names.
When designSystem.name is "optics", use the Optics MCP tools (mcp__optics__*) for token lookups, component mapping, and contrast checking. For any other design system, fall back to Grep/Read-based analysis.
Token artifact rule
Phase 2 always maps observed values to the target design system because that helps the audit explain drift, contrast risk, and remediation effort. Do not assume new token files are needed. DTCG token JSON generation is conditional and should only run when at least one of these is true:
- the user explicitly asks for Figma Variables import files;
.ux-audit.json has "tokens": { "generate": true };
- the target design system does not already exist in the destination Figma file and the team needs a portable token artifact;
- the audit deliverable includes a formal token migration package, not just a report.
Skip token JSON generation when the product already has an adequate design system and the audit only needs mapping tables, remediation notes, screenshots, or a client report. When skipping, say: Token JSON skipped — mapping documented in report; no importable token artifact requested.
Figma MCP Usage Limits
Figma MCP tool calls are rate-limited by plan — not billed per request, but hard-capped daily. Exceeding the limit locks you out for the rest of the day. Plan accordingly.
| Plan + Seat Type | Daily Limit | Per-Minute |
|---|
| Enterprise (Full/Dev) | 600 calls/day | unlimited |
| Pro/Organization (Full/Dev) | 200 calls/day | 15–20/min |
| Starter or View/Collab | 6 calls/month | — |
Estimated usage per audit phase:
| Operation | Estimated Calls | Notes |
|---|
Read design context (get_design_context) | 3–8 | Depends on number of screens inspected |
Get screenshots (get_screenshot) | 3–10 | One per finding with a mockup |
Get metadata (get_metadata) | 1–3 | Structure overview |
Search design system (search_design_system) | 2–5 | Component/variable discovery |
Write to canvas (use_figma) | 10–30 | Section-by-section population |
| Full audit (read + write) | ~20–55 calls | ~25% of Pro daily limit |
| Read-only audit (no Figma output) | ~8–15 calls | Screenshots + context only |
Exempt from rate limits: generate_figma_design (HTML capture), add_code_connect_map, whoami.
Before running Figma phases, the agent should:
- Estimate the number of calls needed based on finding count
- Warn the user: "This audit will use approximately N of your 200 daily Figma MCP calls. Proceed?"
- If the user is on a Starter/View plan (6/month), warn strongly and suggest using the reveal.js HTML format instead
To minimize usage:
- Use
format: "reveal" (HTML) for the report — zero Figma write calls
- Pull screenshots in batch (
get_screenshot for multiple nodes in sequence)
- Only use
format: "figma" when the client specifically needs an editable Figma deliverable
Phase 1: Tech Stack Detection + Codebase Scan
Goal: Identify the project's tech stack and scan for all hardcoded values.
Pre-flight: Locate the Project
If the current working directory doesn't look like a project (no Gemfile, package.json, or source files), ask the user:
"I don't see a project here. What's the project name?"
Then attempt to find it:
-
Search locally — check common paths:
ls -d ~/Development/{name} ~/projects/{name} ~/code/{name} 2>/dev/null
-
Search GitHub — if not found locally, search the org:
gh repo list RoleModel --limit 100 --json name,url | jq '.[] | select(.name | test("name"; "i"))'
If found, offer to clone it:
Found "RoleModel/{name}" on GitHub. Clone it to ~/Development/{name}? (yes/no)
Clone with:
gh repo clone RoleModel/{name} ~/Development/{name}
-
If nothing found — ask the user for the full path or repo URL.
Once the project directory is confirmed, cd into it and proceed.
Steps
-
Detect tech stack by checking for:
Gemfile → Rails (check version in Gemfile.lock)
package.json → check for react, vue, svelte, next, nuxt, angular
.scss files → SCSS preprocessor
tailwind.config.* → Tailwind CSS
@rolemodel/optics in package.json → Optics already present
- Determine templating:
.slim, .erb, .haml, .tsx, .jsx, .vue
-
Find all stylesheet files using Glob:
**/*.scss, **/*.css, **/*.less (excluding node_modules, vendor)
- Also check JSX/TSX for inline styles:
**/*.jsx, **/*.tsx
-
Scan for hardcoded values using Grep on each stylesheet file. Reference references/audit-checklist.md for the complete list of patterns. Key patterns:
- Hex colors:
#[0-9a-fA-F]{3,8}
- Pixel values in spacing properties:
(padding|margin|gap|top|right|bottom|left).*\d+px
- Hardcoded font-size:
font-size:\s*\d
- Literal box-shadow:
box-shadow: not followed by var(
- Literal border-radius:
border-radius: not followed by var(
- Exclude values in comments (
// and /* */ lines)
-
Detect existing token systems:
- CSS custom properties:
--[a-z] declarations in :root or html
- SCSS variables:
\$[a-z] declarations
- Count which files USE tokens vs hardcode values
-
Fetch cover image, client logo, and case study context:
Image sourcing uses two URLs from config — brand.portfolioUrl for the card images and brand.caseStudyUrl for narrative context.
Cover image + client logo (from brand.portfolioUrl):
The portfolio page (e.g., https://rolemodelsoftware.com/portfolio) contains project cards — each with a background image and overlaid client logo. These are inside data-framer-background-image-wrapper elements on Framer-built sites.
curl -sL "{portfolioUrl}" | grep -oP 'data-framer-background-image-wrapper[^<]*<img[^>]+src="[^"]+"' | grep -oP 'src="\K[^"]+'
To find the correct project card:
- Search the page for the project name (case-insensitive) — it may be in an
alt attribute, nearby text, or link href
- The card's
data-framer-background-image-wrapper <img> gives you the hero background image
- Look for a second image inside the same card container — this is typically the client logo (often an SVG or white-on-dark logo)
- If the portfolio uses pagination ("Load More"), the project may not be in the initial HTML — note this for the user
Store as:
HERO_IMAGE_URL → {{HERO_IMAGE_URL}} template placeholder (cover slide background)
CLIENT_LOGO_URL → {{CLIENT_LOGO_URL}} template placeholder (cover slide logo)
If nothing found or fetch fails, keep the cover on the dark token fallback (--dark).
Hero image from case study page (fallback if portfolio scrape fails):
curl -sL "{caseStudyUrl}" | grep -oP 'data-framer-background-image-wrapper[^<]*<img[^>]+src="\K[^"]+' | head -5
Pick the image that visually represents the project (product photography or hero scene, not the company logo or abstract blur).
Case study narrative context — used to write the report:
Use WebFetch on the caseStudyUrl with this prompt: "Extract: (1) the problem or business need the software solved, (2) key features or capabilities built, (3) any outcomes, metrics, or impact statements, (4) quotes or notable language used to describe the product. Return as structured bullet points."
Store this as CASE_STUDY_CONTEXT. Use it in Phase 4 to:
- "Then" section: ground the strengths in the original business purpose. Instead of "the app has autosave", write "autosave was built to support long design sessions in the field — and it works." Use the case study's language about what was accomplished and why.
- Executive Summary narrative: reference real outcomes or impact language from the case study rather than generic framing.
- "Now" framing: frame current gaps as evolved expectations, not failures. "When this was built, X — today users expect Y."
- Never fabricate outcomes — only use what the case study explicitly states. If the case study is vague, use it for tone and domain context only.
-
Report summary to user:
Phase 1 Complete: Codebase Scan
Tech stack: [framework] + [frontend lib], [preprocessor]
Files scanned: N stylesheet files
Hardcoded hex colors: N across M files
Hardcoded pixel values: N across M files
Hardcoded font sizes: N
Existing CSS vars: N
Existing SCSS vars: N
Design system in use: [name or "none"]
Store all findings in memory for subsequent phases.
Phase 2: Design Token Mapping
Goal: Map every existing token and hardcoded value to the target design system.
Steps
-
Collect unique values from Phase 1 scan:
- Deduplicate hex colors
- Deduplicate spacing/size values
- Deduplicate font-size values
- Deduplicate shadow definitions
- Deduplicate border-radius values
-
Map to target design system:
If Optics (use MCP tools):
- For each unique color: call
mcp__optics__suggest_token_migration with the hex value
- For foreground/background pairs in CSS: call
mcp__optics__check_contrast
- For spacing: compare against
mcp__optics__search_tokens category "spacing"
- For border-radius: compare against
mcp__optics__search_tokens category "border"
- For shadows: compare against
mcp__optics__search_tokens category "shadow"
- For typography: compare against
mcp__optics__search_tokens category "typography"
- Use
mcp__optics__list_components to identify mappable components
If NOT Optics (grep-based):
- Read the target system's CSS/token files from node_modules or docs
- Build mapping table manually by comparing values
- Use WebSearch if needed to find documentation
-
Classify each mapping:
- Exact: Values match exactly
- Close: Values within reasonable tolerance (e.g., 2px spacing, 5% color)
- Miss: No good equivalent in target system
- WCAG Fail: Current value has a contrast issue
-
Report summary:
Phase 2 Complete: Token Mapping
Colors mapped: N/M (X exact, Y close, Z miss)
Spacing mapped: N/M
Border radius: N/M
Typography: N/M
Shadows: N/M
Components mappable: N of M
WCAG contrast failures: N
Phase 3: Heuristic Audit
Goal: Walk the product through the 10 UX sections from references/day-1-audit-checklist.html and produce classified findings for each. Combine observable heuristic evaluation (via appUrl or provided screenshots) with static code analysis patterns.
Apply the 21 Laws of UX from references/laws-of-ux.md throughout this phase. Use the Review Checklist to identify which laws are relevant to each section, and cite specific laws when documenting findings.
Run all 10 sections. For each section, produce a list of findings classified by severity using references/severity-model.md.
Section 1: First Impressions & Visual Coherence
Walk the app at appUrl (or use screenshots if provided). Check:
- Does the product make a strong first impression? Is the purpose clear in the first 30 seconds?
- Is the visual language consistent? Check button styles, typography, color usage, spacing, and iconography across multiple screens.
- Does the brand come through clearly?
- Is there visual hierarchy on key screens — can you tell what's most important at a glance?
- Is the color system doing meaningful work (semantic usage) or are colors arbitrary?
- Does the typography scale feel intentional? Are heading levels distinct?
Code scan support: count unique hex colors and font-size values from Phase 1 to quantify inconsistency.
Section 2: Navigation & Wayfinding
- Is the navigation structure predictable (follows conventions users know)?
- Do users always know where they are? Active states, breadcrumbs, page titles?
- Are navigation labels clear, plain-language, jargon-free?
- Is navigation depth appropriate (≤3 clicks to most things)?
- Does navigation work on mobile?
- Are there dead ends — screens with no clear path forward or back?
Code scan support: grep for display: none inside media queries (content being hidden vs adapting).
Section 3: Cognitive Load & Complexity
- Are screens trying to do too much? Flag pages with overwhelming options or decisions.
- Is information chunked effectively — related items grouped, easy to scan?
- Are forms as simple as possible? Extra fields, illogical order?
- Does the UI use meaningful defaults to reduce decisions?
- Is the language plain and direct, or does it require interpretation?
- Are there progress indicators for multi-step processes?
Section 4: Key Flows & Task Completion
Identify the top 2–3 core user tasks before evaluating this section. Walk each flow end to end.
- Is the entry point obvious?
- Are calls to action clear and appropriately sized?
- Does the flow match the user's mental model of the task?
- Are there unnecessary interruptions or confirmation steps?
- Are error states handled gracefully — clear, human, actionable?
- Does the product handle edge cases (empty states, long content, slow connections)?
- What is the peak moment and ending of each flow — are they positive?
Section 5: Feedback & System Communication
- Does the product acknowledge user actions (buttons, form submissions)?
- Are loading states handled with visual feedback?
- Are success and error states distinct and immediately clear?
- Is undo/back behavior predictable?
- Are notifications and alerts used appropriately (not over-interrupting)?
Code scan support: grep for loading spinner patterns; grep for success/error toast/flash component usage.
Section 6: Consistency & Standards
- Do similar elements behave the same way throughout?
- Does the product follow platform conventions (web, iOS, Android)?
- Is the component set stable, or are there one-off UI elements?
- Are interactive elements visually distinguishable from static ones?
Code scan support: Phase 1 hardcoded value counts per file indicate where visual drift is concentrated.
Section 7: Accessibility
Static code analysis — grep the codebase for each of the following:
Focus management:
outline:\s*(none|0) without corresponding :focus-visible replacement
- Missing skip-nav link (
[href="#main"] or similar)
- Missing
<main> landmark
ARIA issues:
role="menu" on <nav> elements (incorrect — should be navigation)
- Buttons/toggles missing
aria-expanded
- Icon-only buttons missing
aria-label
<img without alt attribute
<iframe without title attribute
- Modals without
role="dialog" and aria-modal="true"
Semantic HTML:
<a> wrapping <button> (or vice versa)
<div> with click handlers but no role="button" or tabindex
user-scalable=no or maximum-scale=1 in viewport meta
Color contrast:
- For each foreground/background pair identified in Phase 1, check WCAG AA ratio
- If Optics: use
mcp__optics__check_contrast
- Flag anything below 4.5:1 (normal text) or 3:1 (large text)
Form accessibility:
<input> without associated <label> or aria-label
<select> placeholder options not disabled
- Missing
aria-required on required fields
- No inline validation (submit-only)
Also note observable accessibility gaps from the product walkthrough: tap target sizes, motion, color-only status indicators.
Section 8: Mobile & Responsive Behavior
- Does the layout adapt gracefully across breakpoints (mobile, tablet, desktop)?
- Are touch targets appropriately sized (minimum 44×44px)?
- Is any content hidden on mobile that's visible on desktop?
- Does the navigation pattern work on mobile? Is it thumb-friendly?
- Do forms work on mobile keyboards (correct input types, numeric for phone)?
Code scan support: grep for @media queries and display: none patterns within them.
Section 9: Performance Perception
Observable only — not a technical perf audit:
- Does the product feel fast? Note any perceived slowness during loading, transitions, interactions.
- Are images and media obviously oversized?
- Are transitions and animations additive or distracting?
Section 10: Strategic & Forward-Looking Notes
Step back from individual findings:
- What is the product's single strongest moment? What should be protected and built on?
- Where is the product most constrained by past decisions?
- What 1–2 changes would have the highest user impact with moderate effort?
- Is there a meaningful modernization opportunity (design system, accessibility overhaul, mobile-first)?
- What does "next" look like for this product?
Phase 3 Output
Report summary to user:
Phase 3 Complete: Heuristic Audit
Section 1 – First Impressions: N findings
Section 2 – Navigation: N findings
Section 3 – Cognitive Load: N findings
Section 4 – Key Flows: N findings
Section 5 – Feedback: N findings
Section 6 – Consistency: N findings
Section 7 – Accessibility: N findings (M WCAG violations)
Section 8 – Mobile: N findings
Section 9 – Performance: N findings
Section 10 – Strategic: N findings
Total: N findings (C critical, H high, M medium, P patterns)
Classify each finding using references/severity-model.md.
Phase 4: Interactive Review
Goal: Walk through every finding with the team member running the audit. Confirm, reject, refine, and prioritize before any design work begins. This is the most important phase — it ensures the report is grounded in shared understanding, not just automated analysis.
This phase is interactive. Do not skip it. Do not batch-approve findings. Present each one and wait for input.
How It Works
For each finding from Phase 3, present it to the user and ask:
-
Present the finding clearly:
── Finding 3 of 17 ─────────────────────────────
Section: Navigation & Wayfinding
Severity: High
"Active nav state is missing — users can't tell where they are."
Evidence: No .active or aria-current class on nav links.
Files: app/views/layouts/_nav.html.slim:12-28
─────────────────────────────────────────────────
-
Ask for confirmation:
- "Do you agree with this finding? (yes / no / modify)"
- If no → mark as rejected, ask why (store the reason), move on
- If modify → ask what should change (wording, severity, scope), update the finding
- If yes → proceed to prioritization
-
Ask for prioritization (for confirmed findings):
- "Should this be in the client report? (yes / maybe / internal-only)"
yes → included in the client deliverable
maybe → flagged for discussion, not in v1 of the report
internal-only → stays in internal notes, not shown to client
-
Ask for design direction (for client-facing findings):
- "Any thoughts on the redesign direction? Or should we propose something?"
- Capture notes like "use a floating panel instead" or "they've mentioned wanting tabs"
- These notes inform the design work that happens between sessions
-
Ask for grouping preference:
- "Which lens does this fit? (experience / visual / modernization / strategic)"
- Default to the auto-classified lens, but let the reviewer override
Review Output
After all findings are reviewed, write {outputDir}/reviewed-findings.json:
{
"reviewedAt": "2026-03-25T10:00:00Z",
"reviewer": "Dallas",
"totalFindings": 17,
"confirmed": 12,
"rejected": 3,
"modified": 2,
"findings": [
{
"id": "nav-active-state",
"section": "Navigation & Wayfinding",
"severity": "high",
"title": "Active nav state is missing",
"description": "...",
"status": "confirmed",
"includeInReport": true,
"lens": "experience",
"designNotes": "Use aria-current with visible indicator",
"files": ["app/views/layouts/_nav.html.slim:12-28"]
}
]
}
Also print a summary:
Phase 4 Complete: Interactive Review
Reviewed by: Dallas
Confirmed: 12 findings (10 for client report, 2 internal-only)
Rejected: 3 findings
Modified: 2 findings
Maybe/discuss: 2 findings
Findings saved to: {outputDir}/reviewed-findings.json
Next steps:
1. Design work — create Figma mockups for the confirmed findings
2. When designs are ready, run: /ux-audit report
Session Break
This is where Session 1 ends. The team now does the design work:
- Create Figma mockups for confirmed findings
- Build prototypes if needed
- Record a video walkthrough of the redesigns
- Set up an interactive demo deploy (optional)
When designs are complete, start Session 2 with /ux-audit report.
Phase 5: Report Generation
Goal: Generate the comprehensive client-facing report using confirmed findings from Phase 4 and completed design work.
Pre-flight: Gather Design Assets
Before generating the report, ask the user about available design assets:
-
"Where are the Figma mockups?" — Get the Figma file key and node IDs for redesign screens. Use mcp__figma__get_screenshot(nodeId, fileKey) to pull them.
-
"Is there a video walkthrough?" — If yes, get the file path (e.g., rapidair-demo.mp4). This becomes a dedicated slide in the reveal deck.
-
"Is there a live demo URL?" — If yes (e.g., https://rapidair.vercel.app), this becomes an interactive embed slide using data-background-iframe.
-
"Any screenshots to include?" — Get paths to app screenshots (current state or redesigned). These go inline with each finding slide.
-
Read {outputDir}/reviewed-findings.json — This is the source of truth for which findings to include. Only findings with "includeInReport": true go in the client report. Use each finding's lens, designNotes, and severity to inform the narrative.
If reviewed-findings.json doesn't exist, warn the user: "No reviewed findings found. Run /ux-audit review first to walk through findings with the team." Offer to proceed with all Phase 3 findings as a fallback.
Steps
-
Select output path based on audience mode and format:
CRITICAL — Do not write any CSS. For HTML formats, the CSS files are complete and final. Copy the template HTML and its companion CSS file verbatim into the output directory. The only style override allowed is:
<style>:root { --accent: #F5A623; }</style>
Reveal format: Start from references/revealjs-template/index.html. Copy the full revealjs-template/ bundle into the output directory, then populate the deck by composing its audit-kit web components inside <section> slides. Keep audit-kit.js, reveal-audit-theme.css, local-fonts.css, RMS-lcon.svg, and fonts/ alongside index.html. Supports PDF export via ?print-pdf query parameter.
Figma format: Load the figma-use skill, then use use_figma to write content section-by-section to a duplicate of the Figma template. See references/figma-workflow.md for the complete workflow. The figma-generate-design skill handles discovering components and assembling screens.
Image sourcing (all formats):
- Cover image + client logo: Web scraped from
brand.portfolioUrl (Phase 1 step 5)
- Current state screenshots: Capture from
appUrl via Playwright or browser automation
- Redesign mockups from Figma: Use
mcp__figma__get_screenshot(nodeId, fileKey) to pull from the project's Figma design file
- Embedding: For reveal/HTML, use base64 data URIs for self-contained deployment, or external URLs for lighter files. For Figma format, images are inserted via the Plugin API
-
Apply tone rules from references/tone-guide.md:
- All finding titles, descriptions, and executive summary language must follow the active tone guide
- Client mode: every finding must be rewritten before inclusion (see tone guide for transformation rules)
-
Replace template placeholders:
{{PROJECT_NAME}} — from .ux-audit.json brand.name
{{DESIGN_SYSTEM}} — from .ux-audit.json designSystem.name
{{ACCENT_COLOR}} — computed from brand primary HSL
{{FONT_FAMILY}} — from .ux-audit.json brand.fontFamily
{{DATE}} — current date
{{FINDING_COUNT}} — total findings from Phase 1-3
{{TECH_STACK}} — from Phase 1 detection
-
Populate data sections (differs by audience):
Client mode — uses Then / Now / Next narrative arc from team guide:
Executive Summary (one page, shareable upward):
- 3 high-level stats meaningful to non-technical readers (e.g. "7/12 UX Principles Met", "5 Accessibility Improvements", "3 Strategic Opportunities")
- One narrative paragraph: plain language, no jargon, core opportunity + 2-3 recommended actions + shape of impact
- One callout with the single most important takeaway
Then — Honor the original work (green section):
- 4-6 genuine strengths of the existing product
- What were the constraints? What did it accomplish?
- This is NOT faint praise — it's real recognition of what was built well
- Frame: "this was well-executed for the context it was built in"
Now — What's changed, organized by 4 thematic lenses:
Each finding pairs "what we observed" with "what this means for users." Every observation must come from actually reading the application code. Never fabricate.
- Lens 1: Experience Gaps — Where users have to work harder than they should. Confusing navigation, flows that don't match mental models, missing confirmations, empty states, etc.
- Lens 2: Visual & Brand Coherence — Design inconsistencies that accumulate over time. Includes a type scale visual and color palette visual showing current state vs what's available in the target design system. Frame as: "there's an opportunity to make this feel like one cohesive, modern product again."
- Lens 3: Modernization Moments — Table-stakes improvements since the original design: accessibility (WCAG), mobile responsiveness, component systems, focus management, keyboard navigation.
- Lens 4: Strategic Opportunities — Where the product is constrained by old design decisions. What could it do that it doesn't today? This section should feel generative — a glimpse of v-next, not a punch list.
Also include:
- UX Principles Assessment — 8-12 principles from references/laws-of-ux.md evaluated against actual behavior. Use plain-language names (NOT academic law names like "Jakob's Law"). Each gets status:
pass (Aligned), opportunity, or attention (Needs Attention).
- Typography and color palette visuals within the Visual & Brand Coherence lens
Color palette visual — Optics token structure (when designSystem is "optics"):
- Primary:
--op-color-primary-* — steps: plus-eight, plus-five, plus-two, base, minus-three, minus-seven, minus-nine. Use brand HSL from config.
- Neutral:
--op-color-neutral-* — BLUE-TINTED (H:226, S:5%), NOT warm. Steps: plus-eight, plus-seven, plus-five, base, minus-five, minus-seven, minus-nine.
- Alerts (NOT "Semantic"):
--op-color-alerts-notice-base (green, ~H:134), --op-color-alerts-danger-base (red, ~H:0), --op-color-alerts-warning-base (yellow, ~H:48), --op-color-alerts-info-base (blue, ~H:217). Use plus-seven for light backgrounds (e.g. --op-color-alerts-danger-plus-seven). No standalone "light" variants — use the step scale.
- On-colors: Show WCAG-safe text pairings:
--op-color-primary-on-base, --op-color-neutral-on-plus-eight, --op-color-neutral-on-minus-seven, --op-color-alerts-danger-on-plus-seven.
- Do NOT use warm neutrals (H:46) for the neutral palette — Optics neutrals are blue-tinted (H:226).
Next — The opportunity:
- Roadmap with 3 effort tiers: "Quick Win" / "Phased Modernization" / "Comprehensive Refresh"
- Component enhancement opportunities grid
- "What's Next" invitation — an explicit, open-ended invitation to explore together. Starting a conversation, not closing a sale. What could phase one look like? What questions would we explore together?
Client mode rules:
- NEVER include file paths, line numbers, or code in client reports
- Findings grouped by theme, NOT severity
- Every finding has "observed" + "means" (no "benefit" or "law" labels)
- See references/tone-guide.md for language transformation rules
Internal mode — populate references/html-template/report-template.html:
The internal report uses the same visual style as the Day 1 checklist. It IS the working audit document — the agent fills it out as it conducts the audit, then adds code scan data at the end.
Fill in these placeholders from .ux-audit.json and Phase 1–3 findings:
{{PROJECT_NAME}}, {{DATE}}, {{AUDITOR}}, {{TECH_STACK}}, {{DESIGN_SYSTEM}}, {{APP_URL}}, {{FIGMA_FILE}}
{{CORE_TASK_1/2/3}} — the top 3 user tasks evaluated in Section 4
{{OBSERVATIONS_1}} through {{OBSERVATIONS_10}} — written findings per section (plain prose, include file paths and line numbers)
{{EXEC_VERDICT}} — one paragraph: what the audit found, the single most important recommendation, shape of the effort
- Stat boxes: 3–5 numbers meaningful to engineers (hardcoded value count, WCAG failures, token coverage %, components mappable)
{{HARDCODED_TOTAL}}, {{HARDCODED_FILE_COUNT}}
HTML sections to populate with generated markup (see comments in template for exact format):
- Token mapping tables: one
<h3> + <table class="token-table"> per category (Colors, Spacing, Border Radius, Typography, Shadows). Use <span class="match|close|miss"> for fit classification.
- Hardcoded values bar chart: one
.bar-row per file, sorted by count descending. Width = percentage of max count. Classes: high (>20), medium (10–20), low (<10).
- Component mapping grid: one
.comp-card per component mapping.
- Findings summary table: one
<tr> per finding, using <span class="severity-badge badge-critical|high|medium|pattern"> for severity.
- Claude Prompting Notes: any Claude prompts that generated notably useful output during this audit.
Severity classifications for findings in observations text:
- Critical (C): WCAG A/AA violations, correctness bugs, data loss risks
- High (H): UX quality issues — broken hierarchy, missing confirmations, missing empty states
- Medium (M): Maintainability — inconsistent tokens, missing type scale, magic numbers
- Pattern (P): Cross-cutting issues appearing in multiple places
Observation text format: [ID] **Title.** Description. (file:line if applicable)
-
Ensure mkdir -p {outputDir} exists
-
For html format: Copy the companion CSS file into the output directory (e.g. {outputDir}/report-template-client.css or {outputDir}/report-template.css) — do not modify it
For reveal format: Copy the entire references/revealjs-template/ bundle into the output directory so index.html, audit-kit.js, reveal-audit-theme.css, local-fonts.css, RMS-lcon.svg, and fonts/ stay together
-
Write report to {outputDir}/ux-audit-report.html
- html format: include a
<link rel="stylesheet"> pointing to the copied CSS file
- reveal format: generate from the copied
revealjs-template/index.html structure and preserve its relative asset links
-
Tell the user the file path and suggest opening in browser
-
If publish is configured in .ux-audit.json, inform the user they can deploy with:
./scripts/publish-report.sh
Or run /ux-audit publish to deploy the report to a public URL.
Phase 6: Figma Deliverables
Goal: Write the audit report to Figma's canvas when requested, and generate DTCG token JSON only when the token artifact rule says it is needed.
⚠ Usage check: Before starting, estimate Figma MCP calls needed (see Figma MCP Usage Limits) and confirm with the user. A full canvas write typically uses 15–35 calls. Token JSON generation uses zero Figma calls.
Steps
-
Decide whether token JSON is needed:
- Check
.ux-audit.json for tokens.generate === true
- Check whether the user explicitly requested Figma Variables import files or a token migration package
- Check whether the destination Figma file already has the needed variables/styles
- If none apply, skip token generation and document the reason
-
Generate DTCG token JSON files only if needed:
- If Optics: run
node ${CLAUDE_SKILL_ROOT}/scripts/generate-figma-variables.mjs --config .ux-audit.json --output {outputDir}
- This generates
light.tokens.json and dark.tokens.json
- See references/dtcg-format.md for format details
- Tell user: "Import these via Figma > Local Variables > Import"
-
Write report to Figma canvas (if format is "figma" or explicitly requested):
Follow the workflow in references/figma-workflow.md:
a. Load the figma-use skill — MANDATORY before every use_figma call
b. Duplicate the template — Copy figma.templateKey (iyfRvWyTHSbNYtpBcjuvGg) to create a project-specific file
c. Discover design system — Use search_design_system to find components, variables, and styles
d. Populate content section by section — Use use_figma to:
- Update text nodes with audit findings (exec summary, Then items, Now sections, recommendations)
- Set color swatches to the project's actual palette
- Insert cover image and client logo (from web scraping)
- Insert section screenshots (from
get_screenshot or browser capture)
- Update stat numbers and labels
e. Export if needed — Use
get_screenshot for PNG exports, or link directly to the Figma file
Alternative (HTML-to-Figma capture): If direct canvas write is unavailable, fall back to generate_figma_design with the HTML report:
- Start a local HTTP server to serve the report HTML
- Guide user to open the URL with
#figmacapture&figmadelay=2000
- Poll with captureId once user confirms the capture toast appeared
-
Report deliverables:
Phase 6 Complete: Figma Deliverables
Token files: [generated paths or "skipped — mapping documented in report; no importable token artifact requested"]
Audit report: {outputDir}/ux-audit-report.html
Figma: [URL or "skipped"]
Next steps:
- If token files were generated: import via Figma > Local Variables > Import
- Publish report: ./scripts/publish-report.sh
Demo Recording (Optional Deliverable)
For client-facing audits, an automated screen recording with narration can accompany the report. This uses Playwright for browser automation and ffmpeg for audio merging.
See references/demo-recording-guide.md for the full workflow, and scripts/record-demo-template.ts for a starter script.
Quick summary:
- Write a Playwright script that walks through the app, using
waitUntil() timestamps synced to narration audio
- Write narration text targeting the audience (client or internal)
- Generate audio via TTS (Hedra, ElevenLabs, etc.)
- Run
ffmpeg -af silencedetect on the audio to find section boundaries
- Update the script's
waitUntil() targets to match, re-record
- Merge video + audio:
ffmpeg -i video.webm -i audio.mp3 -c:v libx264 -c:a aac -shortest -y demo.mp4
Phase 7: Publishing
Deploy the generated report to a public URL for sharing with clients or stakeholders. The publish script handles everything — checking prerequisites, guiding auth setup, and deploying.
Invocation
At the end of Phase 5 (report generation), the skill automatically asks: "Ready to publish? I can deploy this to a shareable URL." If yes, it runs the publish flow. You can also run it standalone:
/ux-audit publish
./scripts/publish-report.sh
How it works
- Checks if the Vercel CLI is installed — installs it if not
- Checks if authenticated — guides through login if not
- Reads
.ux-audit.json for outputDir and brand.name
- Packages the report + assets (screenshots, video, SVGs, template CSS/JS, fonts) as a static site
- Links the temporary deploy directory to
publish.projectName so repeat publishes stay on the intended Vercel project
- Deploys and returns the public URL (e.g.,
rapidair-assessment.vercel.app)
First-Time Setup (handled automatically by the script)
The publish script detects when setup is needed and walks the user through it:
╔══════════════════════════════════════════╗
║ UX Audit Report Publisher ║
╚══════════════════════════════════════════╝
⚠ Vercel CLI not found. Installing...
✓ Installed.
⚠ Not authenticated with Vercel.
To log in, you'll need your Vercel credentials.
These are in 1Password under "Vercel" (or ask your team lead).
Run this command:
npx vercel login
Then re-run this script.
Configuration
Set in .ux-audit.json under "publish":
{
"publish": {
"provider": "vercel",
"projectName": "rapidair-assessment"
}
}
provider — "vercel" (default), "netlify", or "surge"
projectName — the URL slug (becomes {slug}.vercel.app). Default: {brand.name}-assessment. Keep it clean and client-facing — no internal tool names.
Requirements
- Node.js installed (for
npx)
- Vercel (default): The script checks auth automatically. Credentials are in 1Password under "Vercel". Run
npx vercel login to authenticate.
- Netlify:
npx netlify-cli login or NETLIFY_AUTH_TOKEN env var
- Surge:
npx surge login
Notes
- The reveal format works especially well for publishing because it is a small static bundle. The publisher copies the deck HTML plus local assets (screenshots, video, template CSS/JS, and fonts) into the deploy directory automatically.
- Published reports are static sites — no server-side code, no database, no build step
- Each deployment creates a unique URL. Re-deploying the same project name updates the existing URL.
- The audits repo (
rolemodel-ux-audits/) convention is one folder per client: rapidair/index.html, clientname/index.html, etc. Each folder can be published independently.
- For GitHub Pages catalog publishing, create or update
<project-slug>/audit/catalog.json in rolemodel-ux-audit-projects for the project title, summary, status, and external links. The projects repo catalog builder automatically links top-level .html, .pdf, .md, .mp4, .webm, and .mov artifacts from <project-slug>/audit/. The projects repo pre-commit hook, publish script, and Pages workflow rebuild the generated root index.html.
Strict Rules
-
Never fabricate findings. Every finding must reference a specific file path and line number or code pattern that you verified by reading the actual source code. If you cannot find evidence, do not report the finding.
-
Count precisely. When reporting "135 hardcoded values", that number must come from actual Grep results. Do not estimate or round creatively.
-
Verify token mappings. When mapping a value like #2C2C2C to --op-color-neutral-minus-six, verify the match by checking the actual token value via MCP or CSS source. State whether it's Exact, Close, or Miss.
-
Test contrast claims. When flagging a WCAG contrast failure, state the actual ratio and the required threshold. Use mcp__optics__check_contrast or calculate from the color values.
-
Acknowledge what works. If the project already uses tokens correctly in some areas, credit that. Not everything is broken.
-
Be specific about effort. Migration time estimates should be based on actual file count, component count, and token mapping completeness — not generic guesses.
-
Use the TodoWrite tool to track progress through the phases. Mark each phase as completed when done.
-
Never create, modify, or inject CSS. The report templates ship with styling assets that define all presentation. Copy them unchanged into the output directory. Do not add <style> blocks (except the small brand-token override already used by the reveal template), inline style attributes, or new class definitions. If a layout need is not covered by the existing HTML/components, use the closest existing structure — do not invent new styles. Exceptions: The reveal format uses the bundled revealjs-template/ assets (reveal-audit-theme.css, local-fonts.css, audit-kit.js, RMS-lcon.svg, fonts/) instead of an inline-only template. The Figma format uses the template's existing styles — do not create new Figma styles, only use what exists in the template.
-
Always load figma-use before use_figma. The figma-use skill MUST be invoked before every use_figma tool call. Skipping it causes hard-to-debug failures. This is a blocking requirement.
-
Never skip the interactive review. Phase 4 exists to build shared understanding. Present each finding individually and wait for the reviewer's input. Do not batch-approve, auto-confirm, or skip findings. If the user says "approve all remaining," confirm once that they want to skip individual review, then mark all as confirmed.
-
Only include confirmed findings in client reports. The reviewed-findings.json from Phase 4 is the source of truth for Phase 5. Rejected findings stay out. "Maybe" findings stay out of v1. Internal-only findings stay out of client deliverables.