For the teams that run client software
Feedback from the people using the build, with the context attached.
Shutterbug sits in your dev, demo and preview environments. A client points at what is wrong and writes a line. You get the route, the build, the failing request, the console and a masked screenshot in your backlog, ready for a developer or their agent. A camera, not a chatbot. Nothing waits on a model.
What a report carries
Everything the developer would have asked for, attached before anyone asks.
- 01screenshot, masked in the browser
- 02the picked element, outlined
- 03a line from the reporter, optional
- 04one press
- 05route
- 06build sha, dirty or not
- 07the failing request, with its body
- 08console errors
- 09browser and viewport
Install
Ten minutes, two files.
Three env values, a token route behind your sign-in, and one tag on signed-in pages. The console tells you when the first report lands. Free for two projects.
- 01 · Token route
app/api/shutterbug/token/route.ts import { auth, currentUser } from "@clerk/nextjs/server"; export async function GET() { const { userId } = await auth(); if (userId === null) { return Response.json({ error: "sign_in_required" }, { status: 401 }); } const user = await currentUser(); const url = process.env.SHUTTERBUG_URL + "/api/reporter-tokens"; const upstream = await fetch(url, { method: "POST", headers: { authorization: "Bearer " + process.env.SHUTTERBUG_PROJECT_SECRET, "content-type": "application/json", }, body: JSON.stringify({ projectKey: process.env.SHUTTERBUG_PROJECT_KEY, reporter: { id: userId, email: user?.primaryEmailAddress?.emailAddress ?? null, }, }), cache: "no-store", }); return new Response(upstream.body, { status: upstream.status, headers: { "content-type": "application/json", "cache-control": "no-store", }, }); } - 02 · Tag
app/(app)/layout.tsx import Script from "next/script"; <Script src="https://shutterbug.dev/shutterbug/loader.js" strategy="afterInteractive" data-shutterbug-project-key="pk_…" data-shutterbug-endpoint="https://shutterbug.dev" data-shutterbug-token-url="/api/shutterbug/token" data-shutterbug-release={process.env.VERCEL_GIT_COMMIT_SHA} />
Any stack: the route is one POST.Read the docs
One press replaces the call, the screenshot and the paragraph explaining it.
- 01 · Capture
Your client presses the mark inside the build, points at the thing, writes a line. The widget attaches the route, the build, the failing request, the console and a masked screenshot before anyone asks.
- 02 · Backlog
Every report lands on one board as a receipt: what was said, what was shown, what the browser was doing. It is to do or done. The client sees it move.
- 03 · Tackle
Developers, or their agents, pull the report with the whole picture attached and update the board when the change ships. No transcribing a call, no chasing a screenshot in Slack.