DevPinSign in

Install the widget

Find your project key (proj_...) on your project's settings page, then drop the snippet into your app. Replaceproj_YOURKEY with it.

<!-- Just before </body> -->
<script src="https://devpin.app/v1/widget.js" data-project="proj_YOURKEY" defer></script>

Optional: skip the sign-in popup

If your app already knows who the user is, hand their identity to the widget so reviewers skip typing their email. Set this before the widget script runs. On an invite-only project the reviewer still confirms the address once per device with a 6-digit code we email them, because anyone can set this value in their own browser.

<script>
  window.__pinit = { userEmail: 'user@example.com', userName: 'Jane Doe' };
</script>
<script src="https://devpin.app/v1/widget.js" data-project="proj_YOURKEY" defer></script>

Connect your AI coding tool

DevPin runs an MCP server at https://devpin.app/mcp. Your agent connects to it with an API token, lists the open pins, makes the changes in your code and marks each pin fixed. Nothing to install. Create a token under Connect your AI tool in your project settings, then:

Claude Code

claude mcp add --transport http devpin https://devpin.app/mcp \
  --header "Authorization: Bearer devpin_yourtoken"

Cursor, Windsurf, VS Code and other MCP clients

Add this to the tool's MCP settings (for Cursor, ~/.cursor/mcp.json). Any client that supports remote MCP servers over HTTP with a custom header works.

{
  "mcpServers": {
    "devpin": {
      "url": "https://devpin.app/mcp",
      "headers": {
        "Authorization": "Bearer devpin_yourtoken"
      }
    }
  }
}

Then ask your agent to "fix the open DevPin feedback". It has seven tools:

  • list_feedback: the open pins, each with the page address, the element and its CSS selector, the component that renders it (when your development build or a data-component attribute shows it), the reviewer's words, a screenshot link, the browser, and the console errors and failed network requests captured before the report. Reports marked as the same issue come as one pin. Each pin says whether the reviewer has checked a fix; pins they sent back as still broken come first, with their note.
  • get_feedback: one pin in full, with the conversation with the reviewer.
  • resolve_feedback: marks a pin fixed (or dismissed, or open again) with a note of what changed, which your team sees in the pin's history. When it marks a pin fixed, DevPin emails the reviewers who reported it to check. The agent can add a preview_url where they can see the fix and an after_screenshot_url, shown next to their screenshot.
  • get_round: a review round, such as "Homepage, round 2": its deadline, how far along it is, which reviewers have looked, and the pins that still need a fix. list_feedback also takes a round (its name or id) to list only that round's pins.
  • claim_feedback: tells other agents it is working on some pins, so two agents never fix the same thing. A claim lasts 30 minutes (up to 120) and ends when the pin is resolved; a pin another agent holds is left alone.
  • get_page_tasks: the open pins grouped by page, so the agent can take one page as one task and fix all of its reports in one pass.
  • reply_to_feedback: adds a message to the pin's conversation, for example to ask which browser the reviewer used.

Prefer plain HTTP, for a script or CI? The same data is one request away:

curl -H "Authorization: Bearer devpin_yourtoken" \
  "https://wfvsgxzhdimuoqzihisb.supabase.co/functions/v1/feedback-api?status=open"

A token reads and updates only its own project. The agent runs in your environment with your own AI keys; DevPin never sees your code. On the issue-tracker side, exporting a pin to GitHub can also tag the Claude Code GitHub Action so it opens a pull request.

Content Security Policy

If your site sends a Content-Security-Policy header, add these sources to it, otherwise the browser blocks the widget or stops it saving:

Content-Security-Policy:
  script-src 'self' https://devpin.app;
  connect-src 'self' https://wfvsgxzhdimuoqzihisb.supabase.co;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: blob:;
  • script-src loads widget.js from https://devpin.app.
  • connect-src lets the widget read your project's settings and save pins, screenshots and sign-in codes. These go to DevPin's backend at https://wfvsgxzhdimuoqzihisb.supabase.co, not to https://devpin.app.
  • style-src 'unsafe-inline' lets the widget style its own panel. Its styles stay inside the widget and do not touch your page.
  • img-src data: blob: lets the widget show the screenshot it just took, so the reviewer can draw on it.

Merge these into the directives you already have rather than replacing them. If your policy has nodefault-src and nostyle-src orimg-src, those last two lines are not needed.

Heads up: the screenshot uses the browser canvas. Cross-origin images on your page without CORS headers can taint the canvas and skip the screenshot; the pin and comment still save. This is the same tradeoff every in-page screenshot tool has.