# ai-app-feedback

A Next.js-ready feedback widget that helps users send useful reports and gives developers enough context to reproduce issues. It captures recent navigation, selected interaction events, browser context, optional screenshots, and a prompt formatted for coding AI triage.

## Install

```bash
bun add ai-app-feedback
```

## Next.js App Router

Import the stylesheet once, then wrap the app in `NextFeedbackProvider`.

```tsx
// app/layout.tsx
import "ai-app-feedback/style.css";
import { NextFeedbackProvider } from "ai-app-feedback/next";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <NextFeedbackProvider
          appId="acme-web"
          endpoint="/api/feedback"
          metadata={{ environment: process.env.NEXT_PUBLIC_VERCEL_ENV ?? "local" }}
        >
          {children}
        </NextFeedbackProvider>
      </body>
    </html>
  );
}
```

Create an endpoint that stores the report, forwards it to an issue tracker, or hands `developerPrompt` to your coding AI agent.

```ts
// app/api/feedback/route.ts
import type { FeedbackReport } from "ai-app-feedback";

export async function POST(request: Request) {
  const report = (await request.json()) as FeedbackReport;

  console.log(report.developerPrompt);

  return Response.json({ ok: true });
}
```

## Screenshot capture

By default, screenshots use the browser `getDisplayMedia` permission flow when a user submits with screenshots enabled. Browsers do not allow silent page screenshots from arbitrary client code.

For DOM-rendered screenshots, install `html2canvas` in the host app and pass a custom capture function:

```tsx
import { createHtml2CanvasCapture } from "ai-app-feedback";

<NextFeedbackProvider
  endpoint="/api/feedback"
  captureScreenshot={createHtml2CanvasCapture(() => import("html2canvas"))}
>
  {children}
</NextFeedbackProvider>;
```

## Core API

Use the core session outside Next.js or with a custom UI.

```ts
import { createFeedbackSession } from "ai-app-feedback/core";

const session = createFeedbackSession({
  appId: "admin",
  endpoint: "/api/feedback",
});

session.recordNavigation({ url: window.location.href, title: document.title });

await session.submit({
  message: "The export button does nothing.",
  expected: "A CSV file should download.",
  severity: "high",
  category: "bug",
});
```

## Privacy defaults

- Input values are not recorded.
- Click tracking stores a small element summary, not full DOM snapshots.
- Screenshot capture is user-visible and permission-gated unless you provide a custom capture function.
- URLs are captured in full by default; pass `scrubUrl` to strip query strings or tokens before they are recorded.
- Reports include `developerPrompt`, a concise repro bundle intended for issue triage and coding agents.

```tsx
<NextFeedbackProvider
  endpoint="/api/feedback"
  scrubUrl={(url) => url.split("?")[0] ?? url}
>
```

`developerPrompt` contains end-user-controlled text fenced inside `<untrusted_user_content>` tags. If you hand it to a coding agent, run that agent with restricted permissions and treat the fenced content as data, not instructions.

## Development

```bash
bun install
bun test
bun run build
```
