Inspiration

Most website analytics tools tell you how many people visited, not where they got stuck. The tools that do show friction (session replays, heatmaps) often record far too much about the user. We wanted a privacy-first alternative: detect where people struggle without ever recording what they type or read, and then explain it in plain language, even by voice.

What it does

UXLens is a UX-friction analytics system.

  • A Chrome extension records only anonymous interaction signals: event type, a sanitized page path (IDs become :id), the element's tag or role, and timestamps. It never records typed text, field values, page content or query strings.
  • A backend turns those events into four friction signals: dead clicks, repeated clicks, hesitation and backtracking.
  • Each problem is mapped to a Nielsen usability heuristic (for example, dead click → Visibility of system status), with a confidence level and a concrete suggested fix.
  • A dashboard shows the UX health score, friction breakdown, top problem elements, and user journeys.
  • An MCP server exposes the analysis as tools (get_ux_summary, get_ux_problems, get_problem_details, get_design_suggestions, get_session_timeline).
  • A "Talk to UXLens" voice panel is a simulated Alexa+-style experience. You ask by voice or text ("what should I fix first?") and it answers aloud from the project's real data through the MCP server.

How we built it

  • Extension: Chrome Manifest V3 with a content script, a service worker, a storage-backed event queue with retries, and a one-time pairing flow between dashboard and extension.
  • Backend: Node.js, Express, Prisma and Postgres (Supabase), deployed on Render.
  • Dashboard: React and Vite, deployed on Vercel.
  • MCP server: the official MCP TypeScript SDK over Streamable HTTP, deployed on Render.
  • Voice: the browser's Web Speech API for speech in and out, calling the MCP server.
  • AI help: [VERIFY: the Gemini API, if /ask is live] writes the spoken answers strictly from the project's data, with a rule-based fallback.

Challenges we ran into

  • Single-page apps lie about navigation. On sites like chatgpt.com, clicking between chats changes the URL without a page load, so our first "dead click" rule flagged almost everything. We fixed it by detecting whether the page actually responded after a click (DOM change or URL change) and by tracking real URL changes.
  • Privacy versus usefulness. Replacing IDs in paths, dropping element text and ignoring hidden iframes kept the data anonymous, but it meant suggestions had to come from behaviour alone.
  • MV3 reality. "Extension context invalidated" errors after reloads, a pairing window that issues each key once, and event queues that race when many events arrive at once.
  • Free-tier hosting. Cold starts, and a deploy that crashed on startup because of a rewritten server file. We learned to keep Render's previous deploy running and to make small, verified changes.
  • MCP over HTTP from a browser. Preflight CORS handling and returning JSON objects (not arrays) as structured results.

Accomplishments we're proud of

  • It works end to end on a real, complex site (not a mock): real clicks become real findings.
  • Every finding comes with evidence, a named Nielsen heuristic, and a concrete fix.
  • A voice interface that answers from live data.

Built With

Share this project:

Updates

Submission history