Loupe

Add a Feedback Widget to Your Web App in 2 Minutes

Ahsan Ayaz |

Your users find bugs you never will. They're staring at a broken layout on a device you don't own, on a network you can't replicate, in a state your tests never exercise. The feedback loop between "user sees bug" and "you fix it" is where products die.

Most feedback ends up in Slack. "hey the thing is broken" with no screenshot, no URL, no context. Or worse — it just doesn't get reported at all because submitting feedback is too much work.

We built @loupeink/web-sdk to make feedback zero-friction. A floating button in the corner of your app. Click it, annotate the screenshot, type a note, done. It appears instantly in your Loupe dashboard — with the URL, viewport, browser, and annotated screenshot already attached.

Here's how to add it.

Install

If you're using a bundler (Vite, webpack, anything modern):

npm install @loupeink/web-sdk

Or if you want to drop it into an existing site without a build step:

<script src="https://cdn.jsdelivr.net/npm/@loupeink/web-sdk/dist/index.global.js"></script>

Initialize

One call. That's it.

import { init } from '@loupeink/web-sdk';

init({
  apiKey: 'lp_your_project_api_key',
});

Call init() once, early in your app boot — main.ts, App.tsx, wherever your entry point is. The widget mounts to document.body automatically. Shadow DOM isolation means it'll never conflict with your styles.

CDN version works the same way:

<script src="https://cdn.jsdelivr.net/npm/@loupeink/web-sdk/dist/index.global.js"></script>
<script>
  Loupe.init({ apiKey: 'lp_your_project_api_key' });
</script>

Place both tags before </body>.

Getting Your API Key

  1. Sign in at app.loupe.ink
  2. Go to Organization Settings → API Keys (top-right menu → Settings → API Keys tab)
  3. Select a project, optionally add a label, click Generate
  4. Copy the lp_… key — it is shown only once
  5. Pass it to init({ apiKey: '...' })

Customize It

You can adjust position, color, and button label. All optional — defaults work fine for most apps.

init({
  apiKey: 'lp_your_project_api_key',
  position: 'bottom-left',      // 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
  color: '#6366f1',              // any CSS color
  buttonLabel: 'Report a bug',  // button text
});

Using It with React

Initialize once at the app root. If you're using StrictMode (which double-invokes effects), clean up with destroy():

import { useEffect } from 'react';
import { init, destroy } from '@loupeink/web-sdk';

export function App() {
  useEffect(() => {
    init({ apiKey: import.meta.env.VITE_LOUPE_API_KEY });
    return () => destroy();
  }, []);

  return <YourApp />;
}

Store your API key in .env as VITE_LOUPE_API_KEY — never commit it directly.

What the Widget Actually Does

When a user clicks the feedback button:

  1. Screenshot capture — captures the visible viewport using html2canvas. No browser extension, no screen share permission.
  2. Annotation overlay — user can draw, circle, highlight, or blur regions on the screenshot before submitting.
  3. Context capture — the current URL, page title, viewport size, and user agent are attached automatically.
  4. Submit — everything POSTs to the Loupe Edge Function, authenticated with your API key. Feedback appears in your dashboard immediately.

Every submission includes the annotated screenshot, the user's comment, a severity level (critical / major / minor / suggestion), and the page context. No configuration needed — that's the default behavior.

Self-Hosting or Custom Endpoints

If you're running a self-hosted Loupe instance or want to route feedback through your own backend, pass the endpoint option:

init({
  apiKey: 'lp_your_key',
  endpoint: 'https://your-own-server.com/feedback',
});

Your endpoint will receive a JSON body with apiKey, comment, severity, screenshotDataUrl (base64 PNG), and a context object.

Cleanup

If you need to unmount the widget (SPA route changes, test teardown, etc.), call destroy():

import { destroy } from '@loupeink/web-sdk';

destroy(); // removes the widget from the DOM

That's It

Two minutes from npm install to a working feedback widget in your app. Feedback lands in Loupe with screenshot, URL, and context — ready to triage, link to a Linear issue, or forward to GitHub.

If you're building something and want to close the feedback loop between your users and your team, this is the fastest way to get started.

Full SDK source is on GitHub. Issues and PRs welcome.

Try Loupe free for 14 days

Download Loupe and start giving frame-precise feedback today. No credit card required.

Download Free Trial