Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 74 additions & 5 deletions src/content/docs/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ These attributes control the fundamental behavior of the widget.
| `data-color` | `"#7c3aed"` | Primary accent color (any CSS color value) |
| `data-icon` | *(default bug icon)* | Custom icon: URL to an image, `"none"` to hide, or omit for default |
| `data-label` | `""` | Text label displayed next to the button icon |
| `data-category-labels` | built-in labels | Self-hosted JSON mapping from built-in categories to GitHub labels |
| `data-button` | `"true"` | Show the floating button: `"true"` or `"false"` |
| `data-welcome` | `"Report a bug or request a feature"` | Welcome message displayed at the top of the form |

Expand Down Expand Up @@ -112,15 +113,81 @@ When a user dismisses the button:

## Feedback Categories

Users can choose from three feedback categories when submitting a report. Each category maps to a specific GitHub label:
Users can choose from three feedback categories when submitting a report. By default, each category maps to a specific GitHub label:

| Category | Emoji | GitHub Label | Description |
|----------|-------|-------------|-------------|
| Bug | :beetle: | `bug` | Something is not working correctly |
| Feature | :sparkles: | `enhancement` | A new feature or improvement request |
| Question | :question: | `question` | A question about the product or usage |

These categories are built into the widget and cannot be customized at this time. The corresponding GitHub labels are created automatically in your repository if they do not already exist.
These categories are built into the widget. Self-hosted deployments can customize which GitHub labels each category applies. There are two configuration paths:

### Server-side mapping (recommended)

Set `CATEGORY_LABELS` on your worker. The mapping is authoritative — clients cannot override it. Two shapes are supported:

**Flat shape** — same labels for every repo your worker serves:

```json
{
"bug": ["defect", "frontend"],
"feature": "product-feedback",
"question": "support"
}
```

**Per-repo shape** — different labels per repo, with an optional `"*"` wildcard fallback:

```json
{
"acme-corp/my-app": {
"bug": ["defect", "frontend"],
"feature": "product-feedback"
},
"acme-corp/docs": {
"bug": "docs-bug"
},
"*": {
"bug": "triage"
}
}
```

The shape is detected automatically: keys containing `/` or equal to `*` mean per-repo; otherwise it's treated as flat.

### Client-side mapping (self-hosts only, opt-in)

Self-hosted deployments can also let pages set labels via the `data-category-labels` attribute. This is **disabled by default** because it lets any page that loads your worker dictate which labels appear on issues. Enable it by setting `ALLOW_CLIENT_CATEGORY_LABELS` to the literal string `"true"` (case-sensitive — values like `"True"`, `"1"`, or `"yes"` keep the gate closed):

```html
<script
src="https://bugdrop.neonwatty.workers.dev/widget.js"
data-repo="acme-corp/my-app"
data-category-labels='{"bug":["defect","frontend"],"feature":"product-feedback","question":"support"}'
></script>
```

Only enable this when your worker's `ALLOWED_ORIGINS` is locked down to trusted domains.

### Rules and behavior

- Recognized keys: `bug`, `feature`, `question`. Other keys are ignored with a warning.
- Each category accepts a single label string or an array of 1-5 strings; each label must be 1-50 characters after trimming (GitHub's limit). Labels containing control characters are rejected.
- Every issue also receives the `bugdrop` label (always added).
- **Precedence**: when both server and client mappings are present, `CATEGORY_LABELS` wins.
- **Fail-closed on misconfig**: if `CATEGORY_LABELS` is set but unusable (malformed JSON, wrong shape, or a per-repo map with no entry for the current repo and no `"*"` fallback), the worker uses default labels and emits a warning — it does **not** silently fall back to `data-category-labels`. This keeps a typo from handing label control back to the browser.
- **GitHub rejection retry**: if GitHub rejects a configured label (e.g. it doesn't exist in the repo), BugDrop retries once with default labels and embeds a label-mapping warning in the issue body.
- **Warnings in the response**: if any warnings were emitted, the `/feedback` JSON success response includes a `labelMappingWarnings: string[]` field so callers can surface configuration issues programmatically.

### Troubleshooting

| Symptom | Likely cause |
|---------|--------------|
| Issues are filed with default labels (`bug`, `enhancement`, `question`) instead of yours | `CATEGORY_LABELS` JSON is malformed, the shape is wrong, or the per-repo map has no entry for this repo and no `"*"` fallback. Check the issue body for a `## Label mapping warning` section, or the worker logs for `[BugDrop] Category label config warnings`. |
| `data-category-labels` is ignored | `ALLOW_CLIENT_CATEGORY_LABELS` is unset or not exactly the string `"true"`. Or `CATEGORY_LABELS` is also set, in which case it always wins. |
| Some categories take effect but others don't | Unknown category keys (anything other than `bug`/`feature`/`question`) are dropped with a warning. Check spelling. |
| GitHub returns a 422 | A configured label doesn't exist in the repo. BugDrop retries with default labels automatically; the issue still gets created and the rejection is recorded in the body. |

## Automatic System Information

Expand All @@ -147,9 +214,11 @@ Control how screenshots are collected during the feedback flow.

### Screenshot Modes

- **`optional`** -- Shows the screenshot checkbox checked by default. Users can choose full page, element, area, annotate, or skip.
- **`auto`** -- Automatically captures a full-page screenshot after the form is submitted, without showing the manual screenshot picker.
- **`required`** -- Requires a screenshot before submission. Users can choose full page, element, or area, but cannot skip the screenshot step.
- **`optional`** -- Shows the screenshot checkbox checked by default. Users can choose full page, element, area, annotate, redact, or skip.
- **`auto`** -- Automatically captures a full-page screenshot after the form is submitted, without showing the manual screenshot picker or redaction step.
- **`required`** -- Requires a screenshot before submission. Users can choose full page, element, or area, then annotate or redact before submitting.

Manual redaction is controlled by the person submitting feedback. Use developer-configured masking for fields that should never appear in screenshots, especially with automatic screenshots.

```html
<!-- Automatically attach a full-page screenshot -->
Expand Down
31 changes: 21 additions & 10 deletions src/content/docs/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ Answers to the most common questions about BugDrop. If your question is not cove

BugDrop is a lightweight, open-source bug reporting widget that you add to your website with a single script tag. When users encounter a bug, they click the floating button, fill out a simple form, and the report is automatically created as a GitHub Issue in your repository -- complete with a screenshot and system information.

You can try it on the [Sample App Demo](https://bugdrop-widget-test.vercel.app/) before installing anything.

### How does BugDrop work?

BugDrop works in three steps:
Expand Down Expand Up @@ -47,12 +45,13 @@ Since BugDrop uses Shadow DOM for isolation, it does not conflict with any frame
BugDrop uses [html2canvas](https://html2canvas.hertzen.com/) to capture screenshots entirely on the client side. When a user clicks the screenshot button:

1. html2canvas renders the current page to an HTML Canvas element in the user's browser
2. The canvas is converted to a PNG image
3. The image is sent to the BugDrop API along with the form submission
4. The API commits the image to the `bugdrop-screenshots` branch in your GitHub repository
5. A link to the screenshot is included in the GitHub Issue
2. In optional and required manual screenshot flows, the user can annotate the screenshot and cover sensitive regions with opaque blocks
3. The canvas is converted to a PNG image
4. The image is sent to the BugDrop API along with the form submission
5. The API commits the image to the `bugdrop-screenshots` branch in your GitHub repository
6. A link to the screenshot is included in the GitHub Issue

No server-side rendering or page access is involved. The screenshot captures exactly what the user sees in their browser at the time of submission.
No server-side rendering or page access is involved. The initial capture is rendered from the current page in the user's browser. In manual flows, the submitted PNG may include user annotations or opaque redaction blocks. Auto screenshots upload without a user redaction step.

### Are screenshots stored securely?

Expand Down Expand Up @@ -103,9 +102,9 @@ BugDrop needs to initialize synchronously to ensure the widget is ready as early

## Configuration

### Does BugDrop support custom labels?
### Can I customize the feedback button label?

Yes. The `data-label` attribute adds a text label next to the button icon:
Yes. The `data-label` attribute changes the text displayed next to the button icon:

```html
<script src="https://bugdrop.neonwatty.workers.dev/widget.js"
Expand All @@ -122,9 +121,21 @@ You can also set `data-icon="none"` to show only the text label without an icon:
data-label="Report a Bug"></script>
```

### Can I customize GitHub issue labels?

Yes. Self-hosted deployments can map the three built-in categories to custom GitHub labels with `data-category-labels` when `ALLOW_CLIENT_CATEGORY_LABELS` is set to `"true"`:

```html
<script src="https://bugdrop.neonwatty.workers.dev/widget.js"
data-repo="owner/repo"
data-category-labels='{"bug":"defect","feature":["product-feedback","triage"],"question":"support"}'></script>
```

Hosted deployments use server-side `CATEGORY_LABELS` configuration instead of trusting labels from public browser requests. Every issue still receives the `bugdrop` label.

### Can I customize the feedback categories?

The three categories (Bug, Feature Request, and Question) are built into the widget and cannot currently be customized through data attributes. Each category maps to a GitHub label (`bug`, `enhancement`, and `question` respectively). If you need custom categories, consider [self-hosting](/docs/self-hosting) and modifying the widget source code.
The three categories (Bug, Feature Request, and Question) are built into the widget and cannot currently be renamed or replaced through data attributes. You can customize which GitHub labels those categories apply.

### Can I collect the user's name and email?

Expand Down
1 change: 0 additions & 1 deletion src/content/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ That is it. No servers to run, no databases to manage, no user accounts required

Ready to get started? Here is where to go next:

- **[Sample App Demo](/docs/demo)** -- Try BugDrop in a realistic page before installing it
- **[Installation](/docs/installation)** -- Step-by-step setup guide to add BugDrop to your site
- **[Configuration](/docs/configuration)** -- All widget attributes for customizing behavior
- **[Styling](/docs/styling)** -- Theme your widget with colors, fonts, borders, and shadows
Expand Down
17 changes: 15 additions & 2 deletions src/content/docs/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

Getting BugDrop running on your site takes about 30 seconds. There are only two steps: install the GitHub App and add a script tag. No npm packages, no build configuration, no backend setup required.

Want to try it first? Open the [Sample App Demo](https://bugdrop-widget-test.vercel.app/) to use the widget before installing it.

## Step 1: Install the GitHub App

BugDrop needs access to your GitHub repository to create issues and store screenshots. Install the official GitHub App to grant these permissions.
Expand Down Expand Up @@ -73,6 +71,21 @@ You can add data attributes to customize the widget's appearance and behavior:

See the [Configuration](/docs/configuration) and [Styling](/docs/styling) docs for all available attributes.

## Protecting sensitive data

If your page renders customer data, billing details, or any other content you do not
want to appear in submitted screenshots, mark those elements with `data-bugdrop-mask`:

```html
<div class="customer-row" data-bugdrop-mask>
Jane Doe — jane@acme.com
</div>
```

BugDrop covers each marked element with an opaque rectangle on the captured screenshot.
Password inputs and credit-card autocomplete fields are masked automatically. See
[Screenshot masking](/security#screenshot-masking) on the Security page for details.

## Step 3: You Are Done

That is it. Load your page and you will see the BugDrop button in the corner of your site. Click it to open the feedback form, fill it out, and submit -- a GitHub Issue will be created in your repository automatically.
Expand Down
47 changes: 46 additions & 1 deletion src/content/docs/security.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,12 @@ Treat screenshots as unauthenticated user-generated content. The hosted service

Screenshots are captured client-side using [html2canvas](https://html2canvas.hertzen.com/), which renders the current page to a canvas element in the user's browser. The canvas is then converted to a PNG image and uploaded. This means:

- The screenshot captures what the user actually sees
- The initial screenshot capture is rendered from what the user actually sees
- No server-side rendering or page access is required
- The screenshot is generated entirely in the user's browser before being sent to the API
- Users can redact additional screenshot regions before submitting when using the manual screenshot flow

Manual redaction is user-driven and does not automatically detect sensitive content. It complements, but does not replace, developer-configured masking for fields that should never appear in screenshots, especially when using automatic screenshots.

Because clients are untrusted, the API validates screenshot uploads server-side before storing them. BugDrop currently accepts PNG data URLs only and rejects SVG, malformed base64, oversized payloads, and data that does not have a PNG file signature.

Expand All @@ -73,6 +76,48 @@ BugDrop is built with a privacy-first approach:
- **Client-side screenshots** -- Screenshots are rendered in the user's browser, not captured server-side
- **Open source** -- The entire codebase is open source (MIT licensed) and auditable

### Screenshot masking

You can mark sensitive elements so they never appear in submitted screenshots. Add the
`data-bugdrop-mask` attribute to any element you want covered:

```html
<input type="email" data-bugdrop-mask />

<div data-bugdrop-mask>
<span>Customer name</span>
<span>customer@example.com</span>
</div>
```

When a user submits feedback, BugDrop paints an opaque rectangle over each tagged
element's bounding box on the captured PNG before showing the user the annotator
preview. The user sees what is masked and can audit it before submitting.

**Inheritance.** When an ancestor has `data-bugdrop-mask`, the entire ancestor box is
masked as a single rectangle. Descendants do not get individual rectangles — this
prevents gaps from CSS `gap` or non-masked siblings inside a masked container.

**Built-in defaults.** These are always masked, with or without an explicit attribute:

- `input[type="password"]`
- Any input with `autocomplete="cc-number"`, `cc-csc`, or `cc-exp`

**Known limitations:**

- Elements inside Shadow DOM and cross-origin iframes are not traversed in this
iteration.
- Mask rectangles are collected at the start of capture. If the page reflows or reveals
sensitive elements between collection and the moment `html-to-image` finishes
rendering, the mask may not cover the final pixels. Keep masked content stable during
the brief capture window.
- **Viewport capture fallback (very complex pages):** When the page exceeds the
full-page DOM-complexity threshold, BugDrop falls back to a screen-recording
capture (via the browser's `getDisplayMedia` API). That path captures the
visible viewport directly and does not apply element masks. If you rely on
masking, ensure the user is not capturing through this fallback when sensitive
elements are visible.

The only network requests BugDrop makes are:

1. Loading the widget script from Cloudflare Workers
Expand Down
Loading