Skip to content

trihead/BugReporter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bug-report-widget

A floating bug-report button for React / Next.js apps.

  • Captures a full-page screenshot (via html-to-image, handles modern CSS colour functions)
  • Records console logs, warnings, errors, uncaught exceptions and unhandled promise rejections
  • Compresses the screenshot to under 2 MB automatically
  • Rate-limited on both client (localStorage) and server (in-memory per IP)
  • Two consent checkboxes before submission
  • Ships a ready-made Next.js App Router API handler that sends the report by email via Resend
  • Pure Tailwind CSS — no shadcn/ui dependency

Installation

npm install bug-report-widget
# peer dependencies (skip any you already have)
npm install lucide-react html-to-image
# optional — only needed for the built-in email handler
npm install resend

Quick start

1 — Add the button to your layout

// app/layout.tsx  (or _app.tsx in Pages Router)
import { BugReportButton } from "bug-report-widget";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <BugReportButton
          endpoint="/api/report"
          authToken={session?.user?.id}   // optional — sent as Bearer token
          reporter={{ name: session?.user?.name, email: session?.user?.email }}
          enabled={true}
        />
      </body>
    </html>
  );
}

2 — Add the API route

Option A — zero config (uses environment variables)

// app/api/report/route.ts
export { POST } from "bug-report-widget/nextjs";

Option B — custom configuration

// app/api/report/route.ts
import { createNextjsBugReportHandler } from "bug-report-widget/nextjs";

export const POST = createNextjsBugReportHandler({
  resendApiKey: process.env.RESEND_API_KEY!,
  emailTo:      process.env.BUG_REPORT_EMAIL!,
  emailFrom:    "Bug Reporter <noreply@yourapp.com>",

  // Optional: check a feature flag in your database before accepting reports
  isEnabled: async () => {
    const settings = await db.settings.findUnique({ where: { id: "singleton" } });
    return settings?.bugReportEnabled !== false;
  },

  // Optional: persist the report to your own database
  onReport: async (report, clientIp) => {
    await db.bugReports.create({ data: { ...report, clientIp } });
  },
});

3 — Environment variables

Variable Required Description
RESEND_API_KEY Yes (for email) Your Resend API key
BUG_REPORT_EMAIL Yes (for email) Recipient address for bug reports
EMAIL_FROM No Sender address (default: Bug Reporter <noreply@example.com>)

Component props

Prop Type Default Description
endpoint string "/api/report" POST endpoint URL
authToken string Sent as Authorization: Bearer <token>
enabled boolean true Hide the button entirely when false
reporter { name, email } Included in the email report
storageKey string "bug_report_last_ts" localStorage key for client-side rate limiting

Custom handler (non-Next.js)

Use handleBugReport directly if you are using a different framework:

import { handleBugReport } from "bug-report-widget";

// Express example
app.post("/api/report", async (req, res) => {
  const result = await handleBugReport(req.body, req.ip, {
    onReport: async (report) => {
      // your email / Slack / webhook logic
      console.log("Bug report received:", report);
    },
    isEnabled: async () => true,
  });
  res.status(result.status).json(result.body);
});

Report payload shape

interface ReportPayload {
  screenshot?:    string;       // base64 JPEG data URL
  comment:        string;       // max 1000 chars
  consoleErrors:  string[];     // up to 50 captured log lines
  url:            string;
  userAgent:      string;
  timestamp:      string;       // ISO 8601
  reporter?:      { name?: string | null; email?: string } | null;
}

How it works

  1. User clicks the floating camera button (bottom-right corner, 40% opacity).
  2. The component hides any open dialogs from the capture, then calls html-to-image to render the page as a JPEG, cropping cross-origin images to avoid CORS errors.
  3. The image is compressed iteratively until it is under 2 MB.
  4. The user optionally adds a comment and ticks two consent checkboxes.
  5. The payload is POSTed to your endpoint along with the accumulated console log buffer.
  6. On the server, IP rate limiting and payload validation run before onReport is called.
  7. Resend sends an HTML email with the screenshot, console logs and metadata.

License

MIT

About

Bug Reporters helps to take screenshot from app and report to developer

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors