How to Add a Feedback Widget to a React App
Why a Provider, Not a Script Tag
Most feedback widgets are installed via a script tag — paste a snippet into your HTML head, configure an API key, and the widget appears as a floating button. This works for chat widgets and screenshot tools because they operate independently of your application. They do not need to understand your component tree, your routing, or your element structure.
Element-anchored feedback is different. It needs to interact with the DOM that your React application renders — identifying elements by CSS selector, capturing computed styles, resolving elements after SPA navigation. A script tag cannot participate in React's component lifecycle. A provider component can.
The LayProvider wraps your application's root layout and provides the feedback context to every component in the tree. It handles comment mode activation, element highlighting, metadata capture, and comment submission — all through React's standard patterns. No global variables, no DOM mutation observers fighting with React's reconciler, no style conflicts with your application's CSS.
Setup
Step 1: Install the SDK
Install @uselay/sdk using your preferred package manager. The SDK is published on npm and has zero peer dependencies beyond React.
Step 2: Add the Provider
Wrap your application's root layout with LayProvider. In a Next.js App Router project, this goes in app/layout.tsx. In a Vite or Create React App project, this wraps your <App /> component.
The provider accepts two required props:
projectId— Your project's unique identifier from the Lay dashboardmode— Either"review"for internal team feedback or"support"for end-user feedback
Step 3: Choose the Mode
The mode determines the entire feedback experience — who can leave feedback, how comments are organized, and what the AI produces.
Review mode is designed for internal teams on staging or preview environments. Team members press C to enter comment mode, click any element to anchor a comment, and discuss in threaded conversations. AI enrichment classifies each comment by design category (visual, accessibility, layout, copy, interaction) and suggests specific CSS fixes. This is the mode for design reviews, QA passes, and stakeholder walkthroughs.
Support mode is designed for end users in production. Users click a feedback trigger to enter comment mode, click the relevant element, and submit a one-line report. Each comment is a standalone report — no threading. AI enrichment detects intent (bug report, feature request, confusion, complaint, question, praise), assigns urgency, and generates structured developer triage. This is the mode for customer bug reports, beta program feedback, and user research.
The mode can be set statically or toggled based on environment. Many teams use review mode on staging and support mode in production, switched by a single environment variable.
Step 4: Enter Comment Mode
In review mode, pressing C activates comment mode. The cursor changes, elements highlight on hover, and clicking an element anchors a comment input to it. The Three-Layer Anchoring system captures the CSS selector, element fingerprint, and viewport coordinates simultaneously.
In support mode, a floating feedback button (or your own custom trigger) activates comment mode. The interaction is identical — hover to highlight, click to anchor — but the UX is simplified for non-technical users.
Step 5: Review in the Dashboard
Every comment, with its full Context Stack, appears in the Lay dashboard at uselay.com/dashboard. The dashboard shows feedback organized by page, element, intent, urgency, and cluster. Each report includes the element's CSS selector, computed styles, viewport dimensions, annotated screenshot, and AI classification.
From the dashboard, feedback flows to connected integrations: Linear issues with Developer Handoff Packs, Slack notifications, and automated triage through Pattern Collapse clustering.
Widget Approaches Compared
Not all feedback widgets capture the same level of context or survive the same conditions. The approach determines what is useful after the feedback is submitted.
Chat widgets and screenshot tools are easiest to install but capture the least context. Element-anchored feedback requires a provider component — slightly more setup — but captures the full Context Stack and survives deploys through self-healing selectors.
What the SDK Captures
When a user clicks an element and submits a comment, the SDK captures six layers of metadata automatically:
Element Identity — Tag name, visible text content, CSS selector path, data-feedback-id (if present), ARIA role, and key attributes. The developer can use the CSS selector directly in DevTools or code search to find the element.
Computed Styles — The actual rendered CSS values: font size, color, padding, margin, background, border, opacity, z-index. These are the values from getComputedStyle(), not the authored CSS — what the browser actually rendered on that element at that moment.
Accessibility — Contrast ratio between text and background colors, ARIA attributes, semantic role. Accessibility violations are flagged automatically, even if the reporter did not notice them.
Viewport — Screen width and height, device pixel ratio, scroll position, detected breakpoint. This eliminates "works on my machine" — the developer knows exactly what viewport the reporter was using.
Screenshot — A cropped viewport capture with the target element highlighted by a bounding box. The screenshot is generated at feedback time and embedded in the report.
AI Classification — Intent (bug, feature request, confusion), urgency, interpretation, and developer triage. This layer runs asynchronously after submission — the user sees their comment immediately.
All six layers travel with the feedback to the dashboard, to Linear, and to Slack. The developer receives a complete Developer Handoff Pack regardless of where they view the report.
Framework Considerations
Next.js App Router — LayProvider is a client component. Mark it with "use client" or wrap it in a client boundary in your root layout. Server components above the provider are unaffected.
Next.js Pages Router — Add LayProvider to _app.tsx, wrapping the <Component> render.
Vite / Create React App — Wrap your root <App /> component in main.tsx or index.tsx.
SPA routing — The SDK detects route changes and re-resolves anchored feedback on navigation. Comments left on /checkout reattach when the user navigates back to /checkout, even after visiting other pages.
Strict Mode — The SDK is compatible with React Strict Mode's double-render behavior in development. Effect cleanup and re-initialization are handled correctly.