Feedback DevTools
2-Minute Quickstart
Create a project on the dashboard, get your SDK token, and embed the feedback toolbar. No build tool changes needed — the SDK works with any host framework.
- 1. Create a project — Go to /login, create an account, then create a project from the dashboard. You'll receive an
sdkToken. - 2. Embed the toolbar — Choose your path below (React or plain HTML).
- 3. Collect feedback — Testers click the floating feedback button, select an element, annotate, and submit. The server captures the full context (screenshot, console logs, network logs, page URL).
React & Next.js
Install the @feedback/sdk package and mount the FeedbackToolbar component.
Install
npm install @feedback/sdk@npm:feedback-devtools-sdkThe @feedback npm scope belongs to another account, so the SDK publishes unscoped as feedback-devtools-sdk — the npm alias above keeps your imports as @feedback/sdk.
One-command setup is coming. npx -y feedback-devtools-init will wire all of this automatically once it lands on npm. Until then, this is exactly what it would write:
# 1. Install the SDK (npm alias — imports stay @feedback/sdk)
npm install @feedback/sdk@npm:feedback-devtools-sdk
# 2. .env — the SDK token from your dashboard project
FEEDBACK_SDK_TOKEN=YOUR_SDK_TOKEN
# 3. next.config — wrap your export for file:line source mapping
import withFeedbackSDK from '@feedback/sdk/next';
export default withFeedbackSDK(config);
# 4. .mcp.json — optional: gives your coding agent the feedback-devtools tools
{
"mcpServers": {
"feedback-devtools": {
"command": "npx",
"args": [
"-y",
"feedback-devtools-mcp"
],
"env": {
"FEEDBACK_API_URL": "https://server-production-14a9.up.railway.app/api/v1",
"FEEDBACK_SDK_TOKEN": "YOUR_SDK_TOKEN"
}
}
}
}Usage
'use client';
import { FeedbackToolbar } from '@feedback/sdk';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<FeedbackToolbar
projectToken="YOUR_SDK_TOKEN"
serverUrl={process.env.NEXT_PUBLIC_FEEDBACK_SERVER_URL}
/>
</body>
</html>
);
}Props:
projectToken(required) — Your project's SDK token from the dashboard.serverUrl(optional) — Defaults tohttp://localhost:3000in development. Set tohttps://server-production-14a9.up.railway.appfor production.
Plain HTML & Any Framework
No React needed. Paste the loader snippet from your project's dashboard page before your closing </body> tag:
<script>window.feedbackDevTools=window.feedbackDevTools||{queue:[],_initialized:false,init:function(c){if(!this._initialized){this._initialized=true;this.push(['init',c]);}return true;},open:function(){this.push(['open'].concat([].slice.call(arguments)));},destroy:function(){this.push(['destroy'].concat([].slice.call(arguments)));},recordFlow:function(){this.push(['recordFlow'].concat([].slice.call(arguments)));},push:function(a){this.queue.push(a);}};
(function(){try{const s=document.createElement('script');s.src="https://server-production-14a9.up.railway.app/loader/channel.js";s.async=true;s.onerror=()=>console.error('Failed to load Feedback DevTools');document.head.appendChild(s);}catch(error){console.error('Feedback DevTools loader error:',error);}})();window.feedbackDevTools.init({token:"YOUR_SDK_TOKEN",api:"https://server-production-14a9.up.railway.app"});</script>It loads /loader/channel.js, which always serves the latest widget, so new releases reach your site without changing the snippet. Never pin a versioned widget URL. Theme, side, label and feature flags go in the same init({...}) call.
What Data Is Captured
When a user submits feedback through the full SDK toolbar, the server captures the following context alongside their description:
| Field | Description |
|---|---|
| whatToChange | User's description of what needs to change |
| expectedBehavior | What the user expected instead |
| screenshotDataUrl | Base64 screenshot of the full page |
| selectedElement | CSS selector, tag, class, and text of the element the user selected |
| pageContext | URL, viewport dimensions, user agent, referrer, session timestamp |
| consoleLogs | Browser console entries (log, warn, error) captured during the session |
| networkLogs | Captured fetch/XHR requests, status codes, and timings |
| annotations | Highlighted regions and arrow annotations the user drew on the screenshot |
| changeType | Category: bug, feature request, UX issue, question, praise, or documentation |
Framework Notes
Next.js (App Router)
Add 'use client' to any page or layout that imports FeedbackToolbar. Mount it in your root layout so it appears on every page. Set NEXT_PUBLIC_FEEDBACK_SERVER_URL to the production server URL for deployed builds.
React (non-Next)
Works with any React 18+ setup (Create React App, Vite, Remix). Import FeedbackToolbar and mount as a child of your root component.
Plain HTML / Any Framework
Use the loader snippet above. It works in any browser and any framework (Vue, Svelte, Angular, WordPress) and always loads the latest widget.
Signed webhook
Signed webhook: each matching item POSTs JSON to your HTTPS URL with header x-fd-signature: sha256=<hex HMAC-SHA256 of the raw body> using the project signing secret. Payload fields: id, projectId, projectName, projectSlug, changeType, whatToChange, expectedBehavior, priority, status, pageContext, screenshotUrl, consoleLogs, networkLogs, classification, createdAt. Works with any HTTPS endpoint, e.g. a Zapier Catch Hook, Make or n8n webhook. Not a native Zapier app.
Zapier Catch Hook setup (not a native Zapier app): /integrations/zapier. Linear issue export (personal API key, not a Linear OAuth app): /integrations/linear.
Live Demo
See how feedback looks end-to-end:
- Create an account → Set up a project and get your SDK token in under a minute.
- Compare plans → Free tier includes unlimited feedback collection.
/share/<token>— Each submitted feedback item can be shared via a public link (accessible without login)./preview/<projectId>— Preview and test the feedback collection flow for a project in a side-by-side viewer with element selection and annotation tools.