# FeedbackDots (full text) > FeedbackDots is a visual feedback and bug reporting tool for websites and web apps. Reviewers drop a dot on the live page, and each report arrives with an annotated screenshot, the page URL, console logs, device details and a session replay, then goes to Linear, Jira, GitHub Issues or Slack. A REST API and an MCP server let AI coding agents like Claude Code and Cursor read and fix reports. Short index: https://feedbackdots.com/llms.txt ## What you get - Free plan: Starter: 1 seat, 25 tickets a month, 1 domain - Paid plan: Pro: $49 a month ($32 billed yearly) for up to 10 seats - Install: One script tag. Reporters need no extension or account - Each report: Annotated screenshot, page URL, console logs, device info, session replay - Routing (Pro): Linear, Jira, GitHub Issues, Slack and signed webhooks - Same snippet (Pro): NPS surveys and feature-request voting - Clients (Pro): Guest review links and a read-only client portal - AI agents: REST API and MCP server on every plan, for Claude Code and Cursor - Install: one script tag before . Works on any site, including WordPress, Webflow, Framer, Wix, Squarespace and apps built with Lovable, Bolt, v0, Replit and Cursor. - Reporters need no browser extension and no account. - Alternative to: BugHerd, Marker.io, Usersnap, Userback and Jam. - Also in the same snippet (Pro): NPS surveys, feature-request voting, guest review links and a read-only client portal. - Made by Forging Destiny Studios, LLC. Contact: hello@feedbackdots.com. ## Plans - Starter: $0 during early access. 25 tickets per month, 1 seat, 1 domain. Support through the docs. - Pro: $49 per month, or $32 per month billed yearly. Unlimited tickets, up to 10 seats, up to 3 domains, Linear, Jira, GitHub Issues and Slack sync, webhooks, NPS, feature voting, client sharing, and email support. - Enterprise: custom pricing, unlimited seats. Contact sales. - Details: [Pricing](https://feedbackdots.com/pricing) # Comparisons ## FeedbackDots as a BugHerd alternative URL: https://feedbackdots.com/alternatives/bugherd FeedbackDots is a BugHerd alternative for teams that want pin-on-the-page feedback without a separate task board. Reviewers drop a dot on the page, and each report includes an annotated screenshot, console logs, the page URL and a session replay. Reports go to Linear, Jira, GitHub Issues or Slack, and an MCP server lets AI coding agents read and fix them. There is a free Starter plan, and Pro is $49 a month for up to 10 seats. About BugHerd: BugHerd is a visual feedback tool where reviewers pin comments to elements of a website, and the comments become tasks on a built-in board. Starting price: $50 / month. Best for: Agencies collecting client feedback on websites. Why teams pick FeedbackDots: - Start free: The Starter plan costs nothing, so you can put FeedbackDots on a client site before anyone signs off on a budget. - Bugs go where you already work: Instead of another task board, Pro sends each report to Linear, Jira, GitHub Issues or Slack, and keeps Linear and GitHub statuses in sync. - Hand bugs to your AI agent: The MCP server on every plan lets Claude Code or Cursor read a report, fix it and mark it done. - Clients without the back-and-forth: Send a guest review link for one round of feedback, and share a read-only portal so clients can see what was fixed. When BugHerd may fit better: - You want a kanban board inside the feedback tool itself rather than in Linear, Jira or GitHub. - Your whole team already works out of BugHerd and the client workflow is settled. Q: Can clients leave feedback without an account? A: Yes. Anyone on a site with the FeedbackDots snippet can drop a dot and send a report. On Pro you can also limit the widget to people you invite with a guest review link. Q: How do I move from BugHerd to FeedbackDots? A: Add the FeedbackDots script to your site, approve the domain, and connect Linear, Jira, GitHub or Slack on Pro. You can run both tools side by side while you switch. ## FeedbackDots as a Marker.io alternative URL: https://feedbackdots.com/alternatives/marker-io FeedbackDots is a Marker.io alternative that combines bug reporting, NPS surveys and feature-request voting in one script tag. Each report includes an annotated screenshot, console logs, optional network requests and a session replay, and Pro routes reports to Linear, Jira, GitHub Issues or Slack. The REST API and MCP server are on every plan. There is a free Starter plan, and Pro is $49 a month for up to 10 seats. About Marker.io: Marker.io is a website bug reporting tool with a widget and browser extension that sends reports, with technical context, into issue trackers such as Jira, Linear and GitHub. Starting price: $39 / month. Best for: QA and product teams that live in an issue tracker. Why teams pick FeedbackDots: - Start free: Starter is free for one seat and one domain, so you can try FeedbackDots on a real site before you pay. - One snippet, three jobs: On Pro the same widget that takes bug reports also runs NPS surveys and a feature-request board with voting. - Ten seats for one price: Pro is $49 a month for up to 10 seats, so adding a teammate does not change the bill. - API and MCP on every plan: Claude Code, Cursor and your own scripts can read and update reports through the API and MCP server, even on Starter. When Marker.io may fit better: - You rely on an issue tracker FeedbackDots does not connect to yet, such as Asana, ClickUp or Trello. - You need a browser extension for reporting on sites where you cannot add a script. Q: Does FeedbackDots sync with Jira and Linear? A: Yes, on Pro. Reports open an issue in Linear, Jira or GitHub Issues, and status changes in Linear and GitHub flow back to FeedbackDots. Q: Does FeedbackDots capture network requests? A: Yes. On Pro you can turn on network capture per project. It records request metadata with URLs redacted, not request bodies. ## FeedbackDots as a Usersnap alternative URL: https://feedbackdots.com/alternatives/usersnap FeedbackDots is a Usersnap alternative for small teams that want bug reports, NPS and feature voting without a large feedback platform. One script tag adds a widget where users drop a dot on the page; each report includes an annotated screenshot, console logs, the page URL and a session replay. Pro adds NPS surveys, feature voting and routing to Linear, Jira, GitHub Issues or Slack for $49 a month with up to 10 seats, and there is a free Starter plan. About Usersnap: Usersnap is a customer feedback platform with in-app feedback widgets, screenshot bug reports, surveys and feature request tracking. Starting price: $69 / month. Best for: Product and customer teams running feedback programs at scale. Why teams pick FeedbackDots: - Live in two steps: Paste one script tag and approve your domain. There is no survey builder or project setup to work through first. - A lower starting price: Starter is free and Pro is $49 a month for up to 10 seats, with unlimited tickets. - Built for AI-assisted teams: Every report carries the context a coding agent needs, and the MCP server lets Claude Code or Cursor pick it up directly. - Feedback and QA together: Bug reports, NPS answers and feature votes land in one dashboard, and a For You story shows what needs attention first. When Usersnap may fit better: - You need advanced survey logic, many survey types or audience targeting rules. - You run feedback across many products and need enterprise controls today. Q: Can FeedbackDots run NPS surveys? A: Yes, on Pro. Turn on NPS for a project and the widget asks your question, collects a 0 to 10 score and an optional reason, and shows the results in your dashboard. Q: Does FeedbackDots have a feature request board? A: Yes, on Pro. Users suggest and vote on ideas from the widget, and you review new ideas before they appear for others. ## FeedbackDots as a Userback alternative URL: https://feedbackdots.com/alternatives/userback FeedbackDots is a Userback alternative focused on teams that build with AI coding tools. Users drop a dot on the page, and each report includes an annotated screenshot, console logs, the page URL and a session replay. The REST API and MCP server are included on every plan, so agents such as Claude Code and Cursor can read and close reports. There is a free Starter plan, and Pro is $49 a month for up to 10 seats with NPS, feature voting and Linear, Jira, GitHub and Slack routing. About Userback: Userback is a user feedback tool with visual bug reporting, session replay, surveys and a feature request portal. Starting price: $29 / month. Best for: SaaS teams collecting feedback from users in their product. Why teams pick FeedbackDots: - MCP and API on every plan: Connect Claude Code or Cursor once and your agent can list reports, read the context and mark them fixed. - One flat Pro price: Pro is $49 a month for up to 10 seats, with unlimited tickets, surveys, feature voting and integrations. - Tell reporters it is fixed: Turn on reporter updates and the person who reported a bug gets an email when it is resolved. - Client review built in: Guest review links and a read-only client portal make FeedbackDots work for agency projects too. When Userback may fit better: - You need integrations FeedbackDots does not offer yet, such as Asana, ClickUp or Trello. Q: Does FeedbackDots include session replay? A: Yes. The widget records the 30 seconds before someone opens it, so you can watch what led up to the bug. Q: Which AI tools work with FeedbackDots? A: Any MCP client, including Claude Code, Cursor, VS Code and Windsurf. The docs have the setup for each. ## FeedbackDots as a Jam alternative URL: https://feedbackdots.com/alternatives/jam FeedbackDots is a Jam alternative for collecting bug reports from people outside your team. Instead of a browser extension, it is one script tag on your site: any visitor, client or tester can drop a dot on the page, and each report includes an annotated screenshot, console logs, the page URL and a session replay. There is a free Starter plan, and Pro is $49 a month for up to 10 seats rather than per creator. About Jam: Jam is a bug reporting tool, best known as a browser extension, that captures a screen recording or screenshot with console and network logs in one click. Starting price: $16 / creator / month. Best for: Internal teams who report bugs from their own browsers. Why teams pick FeedbackDots: - No extension for reporters: Clients, testers and real users report from the site itself. Nobody installs anything or creates an account. - Seats, not creators: Pro is $49 a month for up to 10 seats, however many people send reports. - More than bug reports: The same snippet can run NPS surveys and a feature-request board on Pro. - Reports your agent can fix: The MCP server on every plan lets Claude Code or Cursor read a report and close it when the fix ships. When Jam may fit better: - Only your own team reports bugs, and they are happy with a browser extension. - You report bugs on sites where you cannot add a script tag. Q: Do reporters need to install anything? A: No. FeedbackDots runs from one script tag on your site, so anyone who visits can use it from any browser, including on their phone. Q: Can I use FeedbackDots on a staging site? A: Yes. Add the snippet to staging and approve that domain. On Pro you can show the widget only to people with a guest review link. # Install guides ## Add FeedbackDots to WordPress URL: https://feedbackdots.com/integrations/wordpress To add FeedbackDots to WordPress, install a header and footer code plugin such as WPCode, add the FeedbackDots script as an HTML snippet in the Footer (body end) location, enable it site-wide, and clear any page or CDN cache. 1. Install a code plugin: Install a header/footer code plugin such as WPCode, or edit your theme footer. 2. Add the snippet to the footer: Add the snippet as an HTML/JavaScript snippet in the Footer / Body End location. 3. Enable, save, and clear cache: Enable it site-wide, save, then clear any page or CDN cache. Q: Do I need a WordPress plugin for FeedbackDots? A: There is no dedicated FeedbackDots plugin to install. You paste one script tag using any header and footer code plugin, such as WPCode, or add it to your theme footer before the closing tag. Q: Will FeedbackDots work with Elementor, Divi, or a block theme? A: Yes. Because the script loads site-wide from the footer, it works with any page builder or theme that outputs a normal page. Q: The feedback button is not showing on my WordPress site. What should I check? A: Make sure the snippet is enabled and set to run site-wide, purge your caching plugin and CDN, and confirm your domain is listed in Allowed origins in your FeedbackDots project settings. ## Add FeedbackDots to Framer URL: https://feedbackdots.com/integrations/framer To add FeedbackDots to Framer, open Site Settings, go to Custom Code, paste the FeedbackDots script into the End of tag field, then save and publish the site. Custom code runs on the published site, not in the editor preview. 1. Open Custom Code: Open Site Settings → Custom Code. 2. Paste at the end of body: Paste the snippet into “End of body”. 3. Save and publish: Save and publish the site. Q: Why can’t I see the feedback button in the Framer editor? A: Framer does not run site-wide custom code inside the editor canvas. Publish the site and open the published URL to see the FeedbackDots launcher. Q: Can my clients leave feedback on a Framer site before launch? A: Yes. Publish to your staging or framer.website URL, add that domain to Allowed origins, and share the link. Clients can drop dots on any page without an account. ## Add FeedbackDots to cPanel URL: https://feedbackdots.com/integrations/cpanel To add FeedbackDots to a site hosted on cPanel, open File Manager, find your site files under public_html, and paste the FeedbackDots script immediately before the closing tag in the shared footer or layout file so it loads on every page. 1. Open File Manager: Open File Manager and locate the site template under public_html. 2. Paste before : Paste the snippet immediately before the closing tag. 3. Use the shared footer: Save it in the shared layout/footer so it loads on every page. Q: Which file should I edit in cPanel? A: Edit the file that renders the bottom of every page, usually a shared footer or layout file such as footer.php. On a static HTML site, add the script before in each HTML file. Q: Do I need to install anything on the server? A: No. FeedbackDots is a single script tag that loads in the visitor’s browser. There is nothing to install on your hosting account. ## Add FeedbackDots to Webflow URL: https://feedbackdots.com/integrations/webflow To add FeedbackDots to Webflow, open Site settings, go to Custom code, paste the FeedbackDots script into the Footer code field (before the tag), save, and publish to your domain. Site-wide custom code requires a paid Webflow site plan. 1. Open Custom code: Open Site settings → Custom code. 2. Paste into Footer code: Paste the snippet into Footer code (before tag). 3. Save and publish: Save changes and publish to your production domain. Site-wide custom code needs a paid site plan. Q: Can I add FeedbackDots to a single Webflow page? A: Yes. Instead of Site settings, open the page’s settings and paste the script into its Before tag field. Site-wide is usually better so feedback can come from any page. Q: Does the widget work in the Webflow Designer? A: Custom code does not run inside the Designer. Publish the site and open the live or staging URL to see the launcher. ## Add FeedbackDots to Squarespace URL: https://feedbackdots.com/integrations/squarespace To add FeedbackDots to Squarespace, open Settings, go to Code Injection (under Developer Tools or Advanced, depending on your site version), paste the FeedbackDots script into the Footer field, and save. Code Injection is only available on Squarespace plans that support custom code. 1. Open Code Injection: Open Settings → Developer Tools → Code Injection (older sites: Settings → Advanced → Code Injection). 2. Paste into Footer: Paste the snippet into the Footer field. 3. Save: Save. Code Injection requires a plan that supports custom code. Q: Why don’t I see Code Injection in Squarespace? A: Code Injection is limited to Squarespace plans that allow custom code. On the entry-level plan the option is hidden or locked until you upgrade. Q: Does FeedbackDots work with Squarespace 7.0 and 7.1? A: Yes. Both versions support site-wide Code Injection, and the FeedbackDots script works the same in either. ## Add FeedbackDots to Wix URL: https://feedbackdots.com/integrations/wix To add FeedbackDots to Wix, open your site dashboard, go to Settings → Custom Code (under Advanced), add the FeedbackDots script, apply it to All pages, place it in Body - end, then save and publish. Wix Custom Code requires a Premium plan with a connected domain. 1. Open Custom Code: Open your dashboard Settings → Custom Code (under Advanced). 2. Add to Body - end on all pages: Add the snippet to Body - end and choose All pages. 3. Enable and publish: Apply, then publish. Custom Code needs a Premium plan with a connected domain. Q: Do I need Wix Premium to use FeedbackDots? A: Yes. Wix only allows site-wide Custom Code on Premium sites with a connected domain. Free wixsite.com sites cannot run custom scripts. Q: Does it work with Wix Studio? A: Yes. Wix Studio sites use the same Custom Code settings, so you add the snippet to Body - end on all pages and publish. ## Add FeedbackDots to Canva URL: https://feedbackdots.com/integrations/canva FeedbackDots cannot be installed on Canva Websites because Canva does not currently allow site-wide custom JavaScript. To collect visual feedback, publish the site with a builder or host that accepts custom scripts, such as Framer, Webflow, Wix, or Squarespace, and add the FeedbackDots snippet there. 1. Know the limit: Canva Websites do not currently support site-wide custom JavaScript injection. 2. Use a builder that allows scripts: Use a host or site builder that allows custom scripts, then install this snippet there. Q: Can I add custom code to a Canva website? A: Not today. Canva Websites do not let you add site-wide JavaScript, which any script-based widget, including FeedbackDots, needs to run. Q: Can I embed FeedbackDots as an iframe in Canva instead? A: No. An embed runs inside its own frame, so it cannot see or screenshot the rest of your Canva page. The widget has to load on the page itself. ## Add FeedbackDots to Base44 URL: https://feedbackdots.com/integrations/base44 To add FeedbackDots to a Base44 app, ask the Base44 AI builder to add the FeedbackDots script once, globally, immediately before the closing tag, then publish the app and confirm the feedback launcher appears. 1. Ask the Base44 AI: Open the Base44 app builder and ask its AI to add the snippet globally. 2. Place it once before : Tell it to place the script once, immediately before the closing tag. 3. Publish and verify: Publish and verify the FeedbackDots launcher appears. Q: What should I tell Base44’s AI? A: Paste your FeedbackDots script and say: “Add this exact script once to every page, immediately before the closing tag. Do not change the URL or data-key.” Then publish. Q: Why use FeedbackDots on an AI-built app? A: AI-built apps change quickly and bugs are easy to miss. Each FeedbackDots report includes the screenshot, page URL, browser, and console logs, which is exactly the context you can paste back to the AI to fix the issue. ## Add FeedbackDots to Lovable URL: https://feedbackdots.com/integrations/lovable To add FeedbackDots to a Lovable app, paste the FeedbackDots script into the Lovable chat and ask it to add the script once to index.html, immediately before the closing tag. Then publish the app and confirm the feedback launcher appears. 1. Paste the snippet into the chat: Open your project in Lovable and paste your FeedbackDots script into the chat. 2. Ask for index.html before : Ask Lovable to add it once to index.html, immediately before the closing tag. 3. Publish and verify: Publish the app and check the FeedbackDots launcher appears on the live site. Q: What should I tell Lovable? A: Paste your FeedbackDots script and say: “Add this exact script once to index.html, immediately before the closing tag. Do not change the URL or data-key.” Then publish. Q: Will it show up in the Lovable preview? A: The launcher can appear in the preview, but reports are only accepted from domains you approve in FeedbackDots. Most people approve just the published domain, so testers report bugs on the real app. ## Add FeedbackDots to Bolt URL: https://feedbackdots.com/integrations/bolt To add FeedbackDots to a Bolt.new app, open index.html in the Bolt code editor (or ask Bolt in the chat) and add the FeedbackDots script once, immediately before the closing tag. Then deploy the app and confirm the feedback launcher appears. 1. Open index.html: In Bolt, open the Code view and find index.html at the project root. 2. Add the snippet before : Paste the script once, immediately before the closing tag, or ask Bolt to do it for you. 3. Deploy and verify: Deploy the app and check the FeedbackDots launcher appears on the live site. Q: Where does the script go in a Bolt project? A: Bolt projects usually start from a Vite template, so the page shell is index.html at the project root. Put the script just before there and it loads on every page. Q: Why use FeedbackDots on a Bolt app? A: Apps built by prompting change fast and break in places you did not test. Each FeedbackDots report includes the screenshot, page URL, browser, and console logs, which is the context Bolt needs to fix it. ## Add FeedbackDots to v0 URL: https://feedbackdots.com/integrations/v0 To add FeedbackDots to a v0 app, ask v0 to load the FeedbackDots script in app/layout.tsx with the next/script component and strategy="afterInteractive", keeping the script URL and data-key exactly as given. Then deploy to Vercel and confirm the feedback launcher appears. 1. Paste the snippet into v0: Open your v0 chat and paste your FeedbackDots script. 2. Ask for the root layout: Ask v0 to load it in app/layout.tsx with next/script and strategy="afterInteractive", keeping the src and data-key as they are. 3. Deploy and verify: Deploy to Vercel and check the FeedbackDots launcher appears on the live site. Q: What should I tell v0? A: Paste your FeedbackDots script and say: “Load this script on every page from app/layout.tsx using next/script with strategy afterInteractive. Keep the src and data-key exactly as they are.” Q: Does this work on any Next.js app? A: Yes. The same layout change works for any Next.js app router project, whether v0 generated it or not. ## Add FeedbackDots to Replit URL: https://feedbackdots.com/integrations/replit To add FeedbackDots to a Replit app, ask Replit Agent to add the FeedbackDots script once to the page every route uses (usually index.html or the root layout), immediately before the closing tag. Then redeploy and confirm the feedback launcher appears on the deployed URL. 1. Ask Replit Agent: Paste your FeedbackDots script into the Agent chat and ask it to add the script to every page. 2. Place it once before : Make sure it lands once in the shared HTML shell (index.html or the root layout), just before . 3. Redeploy and verify: Redeploy so the change goes live, then check the launcher on the deployed URL. Q: What should I tell Replit Agent? A: Paste your FeedbackDots script and say: “Add this exact script once to the HTML every page uses, immediately before the closing tag. Do not change the URL or data-key.” Then redeploy. Q: Why use FeedbackDots on a Replit app? A: Every report includes the screenshot, page URL, browser, and console logs, so you can paste it straight into Replit Agent and ask for a fix instead of guessing what the user saw. ## Add FeedbackDots to Cursor URL: https://feedbackdots.com/integrations/cursor To add FeedbackDots to an app you build with Cursor, ask Cursor’s agent to add the FeedbackDots script once to the page every route uses (index.html or the root layout), immediately before the closing tag, then deploy. To let Cursor fix reports, add the FeedbackDots MCP server to .cursor/mcp.json with an API key. 1. Ask Cursor to add the snippet: Paste your FeedbackDots script into Cursor’s agent and ask it to add the script once to your root layout or index.html, just before . 2. Deploy and verify: Deploy your app and check the FeedbackDots launcher appears on the live site. 3. Connect the MCP server: Create an API key under Developers and add the FeedbackDots MCP server to .cursor/mcp.json so Cursor can read and close reports. Q: What can Cursor do with the FeedbackDots MCP server? A: Cursor can list your open reports, read one with its screenshot, console logs, and page URL, and update its status once the fix is in. You stay in the editor the whole time. Q: Do I need the MCP server to use the widget? A: No. The widget works on its own and sends reports to your dashboard, Slack, Linear, Jira, or GitHub. The MCP server is an extra for fixing reports from Cursor. ## Add FeedbackDots to Cloudflare URL: https://feedbackdots.com/integrations/cloudflare To add FeedbackDots through Cloudflare, open your zone’s Zaraz settings, add a Custom HTML tool, paste the FeedbackDots script, and fire it on the Pageview trigger. Developers can instead deploy a Cloudflare Worker that uses HTMLRewriter to append the script to the end of on HTML responses. 1. Open Zaraz: In the Cloudflare dashboard, open your domain, then Zaraz → Tools configuration → Add new tool. 2. Add a Custom HTML tool: Choose Custom HTML, paste the snippet, and set it to fire on the Pageview trigger. 3. Save and verify: Save, then load the live site and confirm the FeedbackDots launcher appears. Q: Should I use Zaraz or a Cloudflare Worker? A: Use Zaraz if you want a no-code setup in the dashboard. Use a Worker with HTMLRewriter if you want the script in your own version control, need to limit it to certain paths, or already run Workers on the route. Q: What does the Cloudflare Worker look like? A: The Worker fetches the original response and, when it is HTML, passes it through new HTMLRewriter().on("body", { element(el) { el.append(snippet, { html: true }); } }).transform(response). Every other response passes through untouched. Q: Does injecting at the edge slow my site down? A: HTMLRewriter streams the page as it passes through, so it does not wait for the full response before sending it on. The widget itself loads in the visitor’s browser like any other script tag. ## Add FeedbackDots to Fastly URL: https://feedbackdots.com/integrations/fastly To add FeedbackDots through Fastly, put a Fastly Compute service in front of your origin that streams HTML responses through an HTML rewriter and appends the FeedbackDots script to the end of , then publish the service and purge the cache. 1. Create a Compute service: Create a Fastly Compute service (the JavaScript starter works well) with your existing site as its backend. 2. Append the snippet to : For text/html responses, stream the body through an HTML rewriter that appends the snippet to the end of . Pass every other response through unchanged. 3. Publish and purge: Run fastly compute publish, purge cached HTML, then load the live site and confirm the launcher appears. Q: Can I inject the script with Fastly VCL? A: Not reliably. VCL can change headers but cannot edit HTML response bodies, so script injection needs a Fastly Compute service in front of, or instead of, your VCL service. Q: Do I need to change my origin server? A: No. The Compute service fetches pages from your existing backend and adds the snippet on the way out. Your origin code stays the same. # Developer docs ## Build on FeedbackDots URL: https://feedbackdots.com/docs Read and manage bug reports and feature requests from your own code, from Zapier, or from an AI coding agent. FeedbackDots collects bug reports and feedback from your website with a screenshot, the dots the reporter dropped on the page, console logs and device details. Everything you see in the dashboard is also available to developers in four ways: | | What it's for | | --- | --- | | [REST API](/docs/api) | Read, create and update reports, comments and feature requests from any language. | | [Webhooks](/docs/webhooks) | Get a signed HTTP request the moment a report or feature request is created or changes status. | | [MCP server](/docs/mcp) | Let Claude Code, Cursor and other AI agents read reports, fix the bug and mark it done. | | [SDKs](/docs/sdks) | Typed clients for JavaScript and Python, with webhook verification built in. | ## Quickstart **1. Create an API key.** In the dashboard, open **Developers** and create a key. Copy it straight away; it's shown once. Only workspace owners and admins can create keys. **2. Check the key works.** ```sh export FEEDBACKDOTS_API_KEY=fd_live_... curl https://feedbackdots.com/api/v1/me \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" ``` ```json { "object": "workspace", "id": "4f1c…", "name": "Acme", "api_key": { "id": "9a2e…", "name": "Quickstart" } } ``` **3. List the reports waiting for triage.** ```sh curl "https://feedbackdots.com/api/v1/reports?status=Triage&limit=5" \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" ``` **4. Mark one done.** Connected trackers (Linear, GitHub, Jira) are updated, and the reporter gets a "fixed" email if the project has that turned on. ```sh curl -X PATCH https://feedbackdots.com/api/v1/reports/REPORT_ID \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"status": "Done"}' ``` ## What's in a workspace - **Projects** are the sites and apps that have the widget installed. - **Reports** are bug reports and feedback sent with the widget (the dashboard also calls them issues). Each has a status (Triage, In Progress, In Review, Done), a severity and the context the widget captured. - **Comments** are the team's discussion on a report. - **Feature requests** are ideas people suggest and vote on in the widget's Ideas tab. An API key belongs to one workspace and can see every project in it. ## Authentication URL: https://feedbackdots.com/docs/authentication Every request carries a workspace API key. Keep keys on your server. Send your key in the `Authorization` header as a bearer token: ```sh curl https://feedbackdots.com/api/v1/projects \ -H "Authorization: Bearer fd_live_..." ``` Tools that can only set custom headers can send `X-API-Key: fd_live_...` instead. ## Creating and revoking keys Open **Developers** in the dashboard. Give each key a name that says where it's used, such as "Zapier" or "Claude Code", so you know which one to revoke later. The full key is shown once; FeedbackDots stores only a hash of it. The list shows each key's first characters and when it was last used. Revoking a key stops it working straight away. A workspace can have 20 active keys. Only workspace owners and admins can see, create or revoke keys. ## What a key can do A key acts for the whole workspace: it can read every project, report, comment and feature request, and change them. It can't see billing, members or other workspaces, and it can't delete anything. Because a key is that powerful, never put it in browser code, a mobile app or a public repository. The widget uses a different, public key (`pk_...`) that can only send new reports. ## The widget key is not an API key Each project's `widget_public_key` identifies the project to the widget script. It is safe to publish and cannot read anything. API keys start with `fd_live_`. ## Errors and pagination URL: https://feedbackdots.com/docs/errors-and-pagination How the API reports problems, pages through long lists, and is versioned. ## Errors Failed requests return a 4xx or 5xx status and a JSON body with a stable `type` and a message written for people: ```json { "error": { "type": "invalid_request", "message": "status must be one of: Triage, In Progress, In Review, Done." } } ``` | Status | `type` | When | | --- | --- | --- | | 400 | `invalid_request` | A field is missing, too long or not one of the allowed values. | | 401 | `authentication_required`, `invalid_api_key` | No key, a malformed key, or a revoked one. | | 402 | `plan_limit_reached` | Creating a report when the workspace has used its monthly reports. | | 403 | `plan_upgrade_required` | Using feature requests from a Starter workspace. They are on the Pro plan. | | 404 | `not_found` | Nothing with that ID in this workspace. | | 409 | `project_archived` | Creating something in an archived project. | | 413 | `payload_too_large` | The body is over 256 KB. | | 429 | `plan_limit_reached` | The workspace has used its API and MCP requests for the month. | | 500 | `server_error` | Something broke on our side. Retry with backoff. | ## Plan limits The API and the MCP server are on every plan. Each request made with a workspace's keys, through either one, counts toward a monthly allowance that resets on the 1st of the month (UTC): | Plan | Requests per month | Active API keys | Support | | ---------- | ------------------ | --------------- | ---------- | | Starter | 1,000 | 1 | These docs | | Pro | 50,000 | 10 | Email | | Enterprise | Unlimited | 20 | Dedicated | Feature request endpoints and MCP tools need the Pro plan. The Developers page in the dashboard shows how many requests the workspace has used this month. ## Pagination List endpoints return a page of results: ```json { "object": "list", "data": [ ... ], "has_more": true, "next_cursor": "eyJvIjoyNX0" } ``` Pass `limit` (1 to 100, default 25) to set the page size. When `has_more` is true, pass `next_cursor` back as `cursor` to get the next page. Treat cursors as opaque strings. The SDKs' `listAll` and `list_all` methods follow cursors for you. ## Status and severity values Report statuses are `Triage`, `In Progress`, `In Review` and `Done`. Severities are `Blocker`, `High`, `Medium` and `Low`. The API also accepts snake_case forms such as `in_progress` and any capitalization, and always returns the forms above. Feature request statuses are `new`, `open`, `planned`, `in_progress`, `shipped` and `declined`. ## Versioning Every response carries a `FeedbackDots-Version` header with the date of the API version. Within `/api/v1` we only add things: new endpoints, new optional fields, new fields in responses and new webhook events. Write your code so it ignores fields it doesn't know. ## Spec The full OpenAPI 3.1 description is public at [`/api/v1/openapi.json`](/api/v1/openapi.json). Use it to generate a client in another language or import the API into Postman or Insomnia. ## Reports URL: https://feedbackdots.com/docs/reports List, read, create and update bug reports, and comment on them. A report is one piece of feedback sent with the widget: a bug, a question or a design note. The dashboard sometimes calls them issues. ## Finding reports ```sh curl "https://feedbackdots.com/api/v1/reports?project_id=PROJECT_ID&status=Triage&severity=High" \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" ``` Filters: `project_id`, `status`, `severity`, `q` (searches titles and descriptions) and `archived=true` to list archived reports instead of open ones. Results are newest first. ## Reading one report `GET /reports/{id}` returns the report plus a `context` object with everything the widget captured: ```json { "object": "report", "id": "c3d1…", "title": "Checkout button does nothing", "description": "Clicked Pay, nothing happened", "status": "Triage", "severity": "High", "page_url": "https://shop.example.com/checkout", "reporter": { "name": "Ana", "email": "ana@example.com" }, "issues": { "linear": { "key": "WEB-41", "url": "https://linear.app/…" }, "jira": null, "github": null }, "dashboard_url": "https://feedbackdots.com/reports/c3d1…", "context": { "screenshot_url": "https://…signed…", "device": { "browser": "Chrome 129", "os": "macOS", "viewport": "1440x900" }, "console_logs": [{ "level": "error", "message": "TypeError: pay is not a function", "at": "…" }], "pins": [ { "number": 1, "comment": "This button", "x": 0.62, "y": 0.41, "element": { "tag": "button", "text": "Pay", "selector": "#checkout > button.pay" } } ], "network_requests": [] } } ``` The screenshot link is signed and works for an hour; fetch the report again for a fresh one. Pin positions are fractions of the viewport. `network_requests` is only filled when the project captures network activity, and its URLs are redacted. ## Creating a report Use this to file reports from your own tools, such as a support inbox or an error tracker. ```sh curl -X POST https://feedbackdots.com/api/v1/reports \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "project_id": "PROJECT_ID", "title": "Customer cannot reset password", "description": "Reported by email. Reset link 404s.", "severity": "High", "page_url": "https://app.example.com/reset", "reporter_name": "Support inbox", "reporter_email": "customer@example.com" }' ``` New reports are handled exactly like widget reports: they go to the project's Linear, Jira, GitHub and Slack and fire the `report.created` webhook (both on Pro), and count toward the plan's monthly reports. Screenshots can't be attached through the API yet. ## Updating a report Send only the fields you want to change: `title`, `description`, `status`, `severity`, `area` or `archived`. ```sh curl -X PATCH https://feedbackdots.com/api/v1/reports/REPORT_ID \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"status": "In Review", "severity": "Medium"}' ``` A status change has the same effects as in the dashboard: connected trackers are updated, the reporter is emailed when it moves to Done (if the project has reporter updates on), and the `report.status_changed` webhook fires. ## Comments ```sh curl https://feedbackdots.com/api/v1/reports/REPORT_ID/comments \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" curl -X POST https://feedbackdots.com/api/v1/reports/REPORT_ID/comments \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"body": "Fixed in v2.3.1, deploying now."}' ``` Comments added with a key are signed with the key's name unless you pass `author_name`. They fire the `comment.created` webhook. ## Feature requests URL: https://feedbackdots.com/docs/feature-requests Read the ideas people suggest and vote on, add your own, and move them through your roadmap. When a project turns on the widget's Ideas tab, visitors can suggest features and vote on each other's ideas. The API gives you the same board. Feature requests are on the Pro plan; on Starter these endpoints return `403 plan_upgrade_required`. ## Statuses | Status | Meaning | On the public board? | | ------------- | ---------------------------------------------------------- | -------------------- | | `new` | Suggested by a visitor, waiting for the team to review it. | No | | `open` | Accepted for voting. | Yes | | `planned` | On the roadmap. | Yes | | `in_progress` | Being built. | Yes | | `shipped` | Released. | Yes | | `declined` | Not going to happen. | No | ## Listing ideas ```sh curl "https://feedbackdots.com/api/v1/feature-requests?status=open&sort=votes" \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" ``` ```json { "object": "list", "data": [ { "object": "feature_request", "id": "8b7e…", "project_id": "1f0a…", "title": "Dark mode", "description": "Our team works late", "status": "open", "votes": 42, "source": "widget", "author": { "name": "Sam", "email": null }, "page_url": "https://app.example.com/settings", "created_at": "2026-10-12T09:30:00Z", "updated_at": "2026-10-15T16:02:11Z" } ], "has_more": false, "next_cursor": null } ``` Sort by `votes` (the default) or `newest`, and filter by `project_id` and `status`. ## Adding an idea Ideas added through the API go straight to `open` unless you pass a `status`, and are tagged `"source": "api"`. ```sh curl -X POST https://feedbackdots.com/api/v1/feature-requests \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"project_id": "PROJECT_ID", "title": "Export reports as CSV", "author_email": "lee@example.com"}' ``` ## Moving an idea along ```sh curl -X PATCH https://feedbackdots.com/api/v1/feature-requests/IDEA_ID \ -H "Authorization: Bearer $FEEDBACKDOTS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"status": "shipped"}' ``` Creating an idea fires `feature_request.created` and changing its status fires `feature_request.status_changed`, whether the change came from the widget, the dashboard or the API. A common setup is a Zap that posts to your changelog or Slack when an idea moves to `shipped`. ## Webhooks URL: https://feedbackdots.com/docs/webhooks Get a signed HTTP request when reports and feature requests are created or change status. Webhooks are on the Pro plan. Each project can send events to one HTTPS endpoint: your own server, or a Zapier, Make or n8n hook. Set it in the project's settings, under **Capture**, then use **Send test event** to check it. ## Events | Event | Sent when | | --- | --- | | `report.created` | A report arrives from the widget or the API. | | `report.status_changed` | A report moves to a new status, from the dashboard, the API, the MCP server, or a synced Linear or GitHub issue. | | `comment.created` | Someone comments on a report. | | `feature_request.created` | Someone suggests a feature, in the widget, the dashboard or the API. | | `feature_request.status_changed` | A feature request moves to a new status. | | `webhook.test` | You press **Send test event**. It carries an example report. | ## Payloads Every event is a JSON `POST` with the same envelope: ```json { "id": "5d7c0a4e-…", "event": "report.status_changed", "occurred_at": "2026-10-18T14:03:22.104Z", "project": { "id": "1f0a…", "name": "Acme storefront" }, "report": { "id": "c3d1…", "title": "Checkout button does nothing", "status": "Done", "previous_status": "In Review", "severity": "High", "area": "Checkout", "description": "Clicked Pay, nothing happened", "page_url": "https://shop.example.com/checkout", "reporter": { "name": "Ana", "email": "ana@example.com" }, "created_at": "2026-10-17T09:12:44Z", "dashboard_url": "https://feedbackdots.com/reports/c3d1…", "issues": { "linear": "https://linear.app/…", "jira": null, "github": null } } } ``` `previous_status` is only present on `*.status_changed` events. `comment.created` adds a `comment` object with `id`, `author_name`, `body` and `created_at`. Feature request events carry a `feature_request` object instead of `report`: ```json { "id": "0b8e…", "event": "feature_request.status_changed", "occurred_at": "2026-10-18T14:05:00.000Z", "project": { "id": "1f0a…", "name": "Acme storefront" }, "feature_request": { "id": "8b7e…", "title": "Dark mode", "description": "Our team works late", "status": "shipped", "previous_status": "in_progress", "votes": 42, "source": "widget", "author": { "name": "Sam", "email": null }, "page_url": "https://app.example.com/settings", "created_at": "2026-10-12T09:30:00Z", "dashboard_url": "https://feedbackdots.com/feedback" } } ``` Fields may be added to payloads over time, so ignore ones you don't use. ## Headers | Header | Value | | --- | --- | | `X-FeedbackDots-Event` | The event name. | | `X-FeedbackDots-Delivery` | A unique ID for this delivery, the same as the body's `id`. Use it to ignore duplicates. | | `X-FeedbackDots-Timestamp` | Unix seconds when the request was signed. | | `X-FeedbackDots-Signature` | `sha256=` followed by the hex HMAC-SHA256 of `timestamp.body`, keyed with the project's signing secret. | ## Verifying the signature Find the signing secret (`whsec_...`) under the project's webhook settings. Compute the HMAC over the timestamp, a dot, and the raw request body, exactly as received, and compare it with the header in constant time. Reject requests whose timestamp is more than five minutes old. With the SDKs this is one call; see [SDKs](/docs/sdks). By hand in Node.js: ```js import { createHmac, timingSafeEqual } from 'node:crypto'; export function verify(secret, rawBody, headers) { const timestamp = headers['x-feedbackdots-timestamp']; const signature = headers['x-feedbackdots-signature'] || ''; if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; const expected = 'sha256=' + createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex'); return ( expected.length === signature.length && timingSafeEqual(Buffer.from(expected), Buffer.from(signature)) ); } ``` In Python: ```python import hashlib, hmac, time def verify(secret, raw_body, headers): timestamp = headers["X-FeedbackDots-Timestamp"] if abs(time.time() - int(timestamp)) > 300: return False expected = "sha256=" + hmac.new(secret.encode(), f"{timestamp}.{raw_body}".encode(), hashlib.sha256).hexdigest() return hmac.compare_digest(expected, headers["X-FeedbackDots-Signature"]) ``` ## Delivery - Respond with any 2xx status within 5 seconds. Do slow work after responding. - Redirects are not followed, and endpoints must be public HTTPS addresses. - Each event is sent once. The settings page shows the result of the last delivery, so you can spot a failing endpoint. - Rotating the secret in settings takes effect for the next event. ## MCP server URL: https://feedbackdots.com/docs/mcp Let Claude Code, Cursor and other AI agents read your reports, fix the bug and close the loop. FeedbackDots runs a remote [Model Context Protocol](https://modelcontextprotocol.io) server. Connect your coding agent to it and you can say "fix the newest high-severity report": the agent reads the report with its console errors, pins and screenshot, changes your code, then marks the report done and comments with what it changed. - **URL:** `https://feedbackdots.com/api/mcp` - **Transport:** Streamable HTTP - **Auth:** an API key, sent as `Authorization: Bearer fd_live_...` - **Plans:** every plan, within the monthly API and MCP request allowance (see [plan limits](/docs/errors-and-pagination#plan-limits)). The feature request tools need Pro. Create a key under **Developers** in the dashboard. Name it after the agent, such as "Claude Code", so you can revoke it on its own. ## Claude Code ```sh claude mcp add --transport http feedbackdots https://feedbackdots.com/api/mcp \ --header "Authorization: Bearer fd_live_..." ``` ## Cursor Add this to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` for every project: ```json { "mcpServers": { "feedbackdots": { "url": "https://feedbackdots.com/api/mcp", "headers": { "Authorization": "Bearer fd_live_..." } } } } ``` ## VS Code Add this to `.vscode/mcp.json`. VS Code asks for the key the first time and stores it securely: ```json { "inputs": [ { "type": "promptString", "id": "feedbackdots-key", "description": "FeedbackDots API key", "password": true } ], "servers": { "feedbackdots": { "type": "http", "url": "https://feedbackdots.com/api/mcp", "headers": { "Authorization": "Bearer ${input:feedbackdots-key}" } } } } ``` ## Windsurf and other clients Any client that supports remote MCP servers with custom headers works with the URL and header above. For clients that only run local servers, bridge with `mcp-remote`: ```json { "mcpServers": { "feedbackdots": { "command": "npx", "args": [ "-y", "mcp-remote", "https://feedbackdots.com/api/mcp", "--header", "Authorization: Bearer fd_live_..." ] } } } ``` ## Tools | Tool | What it does | | --- | --- | | `list_projects` | Lists the workspace's projects and their IDs. | | `list_reports` | Lists reports, filtered by project, status, severity or search text. | | `get_report` | Returns a report as Markdown with what happened, pins and their CSS selectors, console logs, device, network requests, comments and links, plus the screenshot as an image. | | `update_report` | Changes status, severity, title, description, area or archived. | | `add_comment` | Comments on a report, for example to say what was fixed. | | `create_report` | Files a new report in a project. | | `list_feature_requests` | Lists ideas, most votes first. | | `create_feature_request` | Adds an idea to a project's board. | | `update_feature_request` | Moves an idea to planned, shipped and so on. | Changes made through the MCP server behave like changes in the dashboard: moving a report to Done updates Linear, GitHub or Jira, can email the reporter, and fires webhooks. ## Prompts that work well - "List the Triage reports for the storefront project and fix the most severe one. When you're done, move it to In Review and comment with what you changed." - "Get report c3d1… and find the code behind the element in pin 1." - "Which feature requests have the most votes this month? Mark the dark mode one as planned." ## Security The key gives the agent the same access as the API: it can read and change everything in the workspace, but not delete anything. Give each agent its own key and revoke it under **Developers** when you stop using it. ## SDKs URL: https://feedbackdots.com/docs/sdks Typed clients for JavaScript and Python, with webhook verification built in. Both SDKs are built from the [OpenAPI spec](/api/v1/openapi.json), have no dependencies, and cover every endpoint in the [API reference](/docs/api). Use them on your server; never ship an API key to a browser. ## JavaScript and TypeScript Runs in Node.js 18+, Next.js, Remix, Express, Bun, Deno, Cloudflare Workers and Vercel Edge. ```sh npm install @feedbackdots/sdk ``` ```ts import { FeedbackDots } from '@feedbackdots/sdk'; const feedbackdots = new FeedbackDots({ apiKey: process.env.FEEDBACKDOTS_API_KEY! }); // Reports const { data } = await feedbackdots.reports.list({ status: 'Triage', severity: 'High' }); const report = await feedbackdots.reports.get(data[0].id); console.log(report.context.console_logs); await feedbackdots.reports.update(report.id, { status: 'Done' }); await feedbackdots.reports.comments.create(report.id, { body: 'Fixed in v2.3.1' }); // Feature requests, every page for await (const idea of feedbackdots.featureRequests.listAll({ status: 'open' })) { console.log(idea.votes, idea.title); } ``` Every method returns typed objects. Failed requests throw a `FeedbackDotsError` with `status`, `type` and `message`. | Method | Endpoint | | --- | --- | | `workspace.get()` | `GET /me` | | `projects.list()`, `projects.listAll()`, `projects.get(id)` | `/projects` | | `reports.list()`, `reports.listAll()`, `reports.get(id)`, `reports.create()`, `reports.update(id)` | `/reports` | | `reports.comments.list(reportId)`, `reports.comments.create(reportId)` | `/reports/{id}/comments` | | `featureRequests.list()`, `featureRequests.listAll()`, `featureRequests.get(id)`, `featureRequests.create()`, `featureRequests.update(id)` | `/feature-requests` | ### In a Next.js route handler ```ts // app/api/support-ticket/route.ts import { FeedbackDots } from '@feedbackdots/sdk'; const feedbackdots = new FeedbackDots({ apiKey: process.env.FEEDBACKDOTS_API_KEY! }); export async function POST(request: Request) { const ticket = await request.json(); const report = await feedbackdots.reports.create({ project_id: process.env.FEEDBACKDOTS_PROJECT_ID!, title: ticket.subject, description: ticket.body, reporter_email: ticket.from, }); return Response.json({ url: report.dashboard_url }); } ``` ## Python Works with Python 3.9+, Django, Flask, FastAPI and scripts. Responses are plain dicts shaped like the API reference. ```sh pip install feedbackdots ``` ```python import os from feedbackdots import FeedbackDots, FeedbackDotsError client = FeedbackDots(api_key=os.environ["FEEDBACKDOTS_API_KEY"]) reports = client.reports.list(status="Triage", severity="High")["data"] report = client.reports.get(reports[0]["id"]) client.reports.update(report["id"], status="Done") client.reports.comments.create(report["id"], body="Fixed in v2.3.1") for idea in client.feature_requests.list_all(status="open"): print(idea["votes"], idea["title"]) ``` Method names match the JavaScript SDK in snake_case: `feature_requests.list_all()` and so on. ## Verifying webhooks Both SDKs check the `X-FeedbackDots-Signature` header and the timestamp, and return the parsed event. Pass the raw body, before any JSON parsing. ```ts // Next.js: app/api/feedbackdots/route.ts import { verifyWebhook } from '@feedbackdots/sdk'; export async function POST(request: Request) { const event = await verifyWebhook({ secret: process.env.FEEDBACKDOTS_WEBHOOK_SECRET!, body: await request.text(), headers: request.headers, }); if (event.event === 'report.created') console.log('New report:', event.report.title); return new Response(null, { status: 204 }); } ``` ```python # Django from django.http import HttpResponse, HttpResponseBadRequest from feedbackdots import verify_webhook, WebhookVerificationError def feedbackdots_webhook(request): try: event = verify_webhook( secret=settings.FEEDBACKDOTS_WEBHOOK_SECRET, body=request.body, headers=request.headers, ) except WebhookVerificationError: return HttpResponseBadRequest() if event["event"] == "feature_request.status_changed": print(event["feature_request"]["title"], event["feature_request"]["status"]) return HttpResponse(status=204) ``` In Express, read the body with `express.raw({ type: 'application/json' })` so it isn't parsed before you verify it. ## Other languages Generate a client from [`/api/v1/openapi.json`](/api/v1/openapi.json) with any OpenAPI generator, or call the API directly; it's plain JSON over HTTPS. # Blog posts - [Turn a bug report into a prompt your AI assistant can fix](https://feedbackdots.com/blog/bug-report-to-ai-prompt) (Field Guide, 2026-11-04): AI coding assistants guess when you give them a vague bug. A simple template for turning a bug report into a prompt that gets a real fix on the first try. - [AI writes the code faster. Now QA is the bottleneck.](https://feedbackdots.com/blog/qa-in-the-age-of-ai-coding) (Feedback Loop, 2026-10-30): AI coding tools have made building cheap and fast. Knowing whether what you built actually works has not kept up. What changes for QA when your team ships with AI. - [How to run a client review without forty emails](https://feedbackdots.com/blog/client-review-without-the-email-thread) (Field Guide, 2026-10-28): Client feedback rounds drag on because feedback arrives scattered, vague, and late. A simple review process that gets clear, actionable feedback in one pass. - [Close the loop, or people stop giving feedback](https://feedbackdots.com/blog/close-the-feedback-loop) (Feedback Loop, 2026-10-23): Feedback is a conversation, not a form. Why the moment after someone reports a problem matters more than the report itself, and how to make it count. - [A 30-minute QA checklist before any website launch](https://feedbackdots.com/blog/pre-launch-qa-checklist) (Field Guide, 2026-10-21): You do not need a QA team to catch the bugs that embarrass a launch. A practical checklist you can run in half an hour on any site, built with anything. - [Meet FeedbackDots: feedback, right where it happens](https://feedbackdots.com/blog/meet-feedbackdots) (Product Updates, 2026-10-16): The first of our monthly product updates. What FeedbackDots is, how a report comes together, and everything that has shipped since launch in September. - [A screenshot is not a bug report](https://feedbackdots.com/blog/a-screenshot-is-not-a-bug-report) (Feedback Loop, 2026-10-16): Most bug reports arrive missing the five facts a developer needs to fix them. Here is what good QA feedback actually contains, and how to stop chasing it.