From cc824933c4d5d6e77fb884f06ddfc178b4f60e2e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 5 Apr 2026 19:16:07 +0000 Subject: [PATCH] docs: sync documentation from bugdrop repo --- src/content/docs/ci-testing.mdx | 297 +++++++++++++++++++++++++++ src/content/docs/configuration.mdx | 235 +++++++++++++++++++-- src/content/docs/faq.mdx | 214 ++++++++++++++++++- src/content/docs/getting-started.mdx | 83 ++++++++ src/content/docs/installation.mdx | 154 +++++++++++++- src/content/docs/javascript-api.mdx | 237 +++++++++++++++++++++ src/content/docs/security.mdx | 158 ++++++++++++++ src/content/docs/self-hosting.mdx | 136 ++++++++++++ src/content/docs/styling.mdx | 209 +++++++++++++++++-- src/content/docs/version-pinning.mdx | 132 ++++++++++++ 10 files changed, 1813 insertions(+), 42 deletions(-) create mode 100644 src/content/docs/ci-testing.mdx create mode 100644 src/content/docs/getting-started.mdx create mode 100644 src/content/docs/javascript-api.mdx create mode 100644 src/content/docs/security.mdx create mode 100644 src/content/docs/self-hosting.mdx create mode 100644 src/content/docs/version-pinning.mdx diff --git a/src/content/docs/ci-testing.mdx b/src/content/docs/ci-testing.mdx new file mode 100644 index 0000000..b1c8370 --- /dev/null +++ b/src/content/docs/ci-testing.mdx @@ -0,0 +1,297 @@ +# CI Testing with Playwright + +BugDrop can be tested in your CI/CD pipeline using Playwright. This guide covers everything from a quick verification check to a comprehensive test suite that validates functionality, accessibility, and configuration. + +## Quick Check + +The fastest way to verify BugDrop is loading correctly is to check for its console message. When the widget initializes successfully, it logs: + +``` +[BugDrop] Widget initialized +``` + +You can check for this in a simple Playwright test: + +```typescript +import { test, expect } from '@playwright/test'; + +test('BugDrop loads', async ({ page }) => { + const messages: string[] = []; + page.on('console', (msg) => messages.push(msg.text())); + + await page.goto('https://your-site.com'); + await page.waitForTimeout(2000); + + expect(messages.some((m) => m.includes('[BugDrop]'))).toBe(true); +}); +``` + +## Full Playwright Test Suite + +Here is a comprehensive test file that validates BugDrop's functionality, accessibility (WCAG AA compliance), and configuration. You can copy this directly into your project: + +```typescript +import { test, expect } from "@playwright/test"; + +// ── EXPECTED configuration ────────────────────────────────────── +// Update these values to match YOUR script tag's data-* attributes. +const EXPECTED = { + theme: "light", + position: "bottom-right", + color: "#7c3aed", + showName: false, + requireName: false, + showEmail: false, + requireEmail: false, + buttonDismissible: false, + showRestore: true, + welcomeMessage: "Report a bug or request a feature", +}; + +const URL = "https://your-site.com"; // Replace with your site URL + +// ── Helper: reach into the Shadow DOM ─────────────────────────── +async function shadowEl(page, hostSel: string, innerSel: string) { + return page.evaluateHandle( + ([h, s]) => { + const host = document.querySelector(h); + if (!host?.shadowRoot) throw new Error(`No shadow root on ${h}`); + const el = host.shadowRoot.querySelector(s); + if (!el) throw new Error(`${s} not found in shadow DOM`); + return el; + }, + [hostSel, innerSel] + ); +} + +// ── Tests ─────────────────────────────────────────────────────── + +test.describe("BugDrop Widget", () => { + test.beforeEach(async ({ page }) => { + await page.goto(URL); + await page.waitForSelector("bug-drop-widget"); + }); + + test("renders the floating button", async ({ page }) => { + const btn = await shadowEl(page, "bug-drop-widget", ".floating-btn"); + expect(btn).toBeTruthy(); + }); + + test("opens and closes the form", async ({ page }) => { + const btn = await shadowEl(page, "bug-drop-widget", ".floating-btn"); + await (btn as any).click(); + + const form = await shadowEl(page, "bug-drop-widget", ".feedback-form"); + expect(form).toBeTruthy(); + + const closeBtn = await shadowEl(page, "bug-drop-widget", ".close-btn"); + await (closeBtn as any).click(); + }); + + test("has correct position", async ({ page }) => { + const pos = await page.evaluate(() => { + const host = document.querySelector("bug-drop-widget"); + const btn = host?.shadowRoot?.querySelector(".floating-btn"); + if (!btn) throw new Error("Button not found"); + const style = window.getComputedStyle(btn); + return { right: style.right, left: style.left, bottom: style.bottom }; + }); + + if (EXPECTED.position === "bottom-right") { + expect(parseInt(pos.right)).toBeLessThan(100); + } else { + expect(parseInt(pos.left)).toBeLessThan(100); + } + }); + + test("uses correct accent color", async ({ page }) => { + const bgColor = await page.evaluate(() => { + const host = document.querySelector("bug-drop-widget"); + const btn = host?.shadowRoot?.querySelector(".floating-btn"); + if (!btn) throw new Error("Button not found"); + return window.getComputedStyle(btn).backgroundColor; + }); + expect(bgColor).toBeTruthy(); + }); + + test("displays correct welcome message", async ({ page }) => { + const btn = await shadowEl(page, "bug-drop-widget", ".floating-btn"); + await (btn as any).click(); + + const welcomeText = await page.evaluate(() => { + const host = document.querySelector("bug-drop-widget"); + const welcome = host?.shadowRoot?.querySelector(".welcome-message, h2"); + return welcome?.textContent?.trim(); + }); + + expect(welcomeText).toContain(EXPECTED.welcomeMessage); + }); + + test("shows/hides name field based on config", async ({ page }) => { + const btn = await shadowEl(page, "bug-drop-widget", ".floating-btn"); + await (btn as any).click(); + + const nameFieldVisible = await page.evaluate(() => { + const host = document.querySelector("bug-drop-widget"); + const nameField = host?.shadowRoot?.querySelector( + '[name="name"], #name, .name-field' + ); + if (!nameField) return false; + return window.getComputedStyle(nameField).display !== "none"; + }); + + expect(nameFieldVisible).toBe(EXPECTED.showName); + }); + + test("shows/hides email field based on config", async ({ page }) => { + const btn = await shadowEl(page, "bug-drop-widget", ".floating-btn"); + await (btn as any).click(); + + const emailFieldVisible = await page.evaluate(() => { + const host = document.querySelector("bug-drop-widget"); + const emailField = host?.shadowRoot?.querySelector( + '[name="email"], #email, .email-field' + ); + if (!emailField) return false; + return window.getComputedStyle(emailField).display !== "none"; + }); + + expect(emailFieldVisible).toBe(EXPECTED.showEmail); + }); + + // ── Accessibility (WCAG AA) ───────────────────────────────── + test("button meets WCAG AA contrast ratio", async ({ page }) => { + const contrast = await page.evaluate(() => { + function luminance(r: number, g: number, b: number) { + const [rs, gs, bs] = [r, g, b].map((c) => { + c /= 255; + return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); + }); + return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs; + } + function parseRgb(color: string) { + const match = color.match(/(\d+)/g); + return match ? match.map(Number) : [0, 0, 0]; + } + + const host = document.querySelector("bug-drop-widget"); + const btn = host?.shadowRoot?.querySelector(".floating-btn"); + if (!btn) return 0; + const style = window.getComputedStyle(btn); + const [r1, g1, b1] = parseRgb(style.backgroundColor); + const bgLum = luminance(r1, g1, b1); + const whiteLum = luminance(255, 255, 255); + const ratio = + (Math.max(bgLum, whiteLum) + 0.05) / + (Math.min(bgLum, whiteLum) + 0.05); + return ratio; + }); + + // WCAG AA requires 4.5:1 for normal text, 3:1 for large text + expect(contrast).toBeGreaterThanOrEqual(3); + }); + + test("form elements are keyboard accessible", async ({ page }) => { + // Open the form + await page.keyboard.press("Tab"); + await page.keyboard.press("Enter"); + + // Verify form opened and is focusable + const formExists = await page.evaluate(() => { + const host = document.querySelector("bug-drop-widget"); + return !!host?.shadowRoot?.querySelector(".feedback-form, form"); + }); + + expect(formExists).toBe(true); + }); +}); +``` + +## Installation and Setup + +To run the tests, you need Playwright installed in your project: + +```bash +# Install Playwright +npm install --save-dev @playwright/test + +# Install browsers +npx playwright install +``` + +Create or update your `playwright.config.ts`: + +```typescript +import { defineConfig } from '@playwright/test'; + +export default defineConfig({ + testDir: './e2e', + timeout: 30000, + use: { + baseURL: 'https://your-site.com', + }, +}); +``` + +Then run the tests: + +```bash +npx playwright test +``` + +## What the Tests Check + +The test suite covers three areas: + +### Functional Tests + +- **Renders the floating button** -- Verifies the widget loads and the button appears in the Shadow DOM +- **Opens and closes the form** -- Clicks the button, verifies the form appears, then closes it +- **Correct position** -- Validates the button is in the expected corner (bottom-right or bottom-left) +- **Correct accent color** -- Checks the button's background color +- **Welcome message** -- Opens the form and verifies the correct welcome text is displayed +- **Name/email field visibility** -- Confirms fields show or hide based on your configuration + +### Accessibility Tests (WCAG AA) + +- **Contrast ratio** -- Calculates the luminance contrast ratio between the button's background color and white text, ensuring it meets WCAG AA standards (3:1 for large text) +- **Keyboard accessibility** -- Verifies the form can be opened and navigated using only the keyboard + +### Configuration Verification + +The `EXPECTED` object at the top of the test file defines your expected configuration. Update it to match your actual `data-*` attributes: + +```typescript +const EXPECTED = { + theme: "light", // data-theme + position: "bottom-right", // data-position + color: "#7c3aed", // data-color + showName: false, // data-show-name + requireName: false, // data-require-name + showEmail: false, // data-show-email + requireEmail: false, // data-require-email + buttonDismissible: false, // data-button-dismissible + showRestore: true, // data-show-restore + welcomeMessage: "Report a bug or request a feature", // data-welcome +}; +``` + +If any of these values do not match what the widget actually renders, the corresponding test will fail -- catching configuration drift between your script tag and your expected behavior. + +## Running in CI + +Add the test to your CI workflow (GitHub Actions example): + +```yaml +- name: Install Playwright + run: npx playwright install --with-deps chromium + +- name: Run BugDrop tests + run: npx playwright test e2e/bugdrop.spec.ts +``` + +## Next Steps + +- [Configure the widget](/docs/configuration) with data attributes +- [Review security and rate limiting](/docs/security) +- [Pin your widget version](/docs/version-pinning) for stable CI runs diff --git a/src/content/docs/configuration.mdx b/src/content/docs/configuration.mdx index fd428db..85407f6 100644 --- a/src/content/docs/configuration.mdx +++ b/src/content/docs/configuration.mdx @@ -1,18 +1,227 @@ # Configuration -BugDrop is configured entirely through `data-*` attributes on the script tag. +BugDrop is configured entirely through data attributes on the script tag. No JavaScript configuration object, no external config file -- just HTML attributes. This page covers every available attribute. ## Core Attributes -| Attribute | Values | Default | -|-----------|--------|---------| -| `data-repo` | `owner/repo` | required | -| `data-theme` | `light`, `dark`, `auto` | `auto` | -| `data-position` | `bottom-right`, `bottom-left` | `bottom-right` | -| `data-welcome` | `once`, `always`, `false`/`never` | `once` | -| `data-color` | Hex color (e.g. `#FF6B35`) | `#14b8a6` | -| `data-button-dismissible` | `true`, `false` | `false` | -| `data-button` | `true`, `false` | `true` | -| `data-label` | Any string | `Feedback` | - -See [Styling](/docs/styling) for visual customization options. +These attributes control the fundamental behavior of the widget. + +| Attribute | Default | Description | +|-----------|---------|-------------| +| `data-repo` | **(required)** | GitHub repository in `owner/repo` format | +| `data-theme` | `"light"` | Widget theme: `"light"` or `"dark"` | +| `data-position` | `"bottom-right"` | Button position: `"bottom-right"` or `"bottom-left"` | +| `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-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 | + +### Basic Example + +```html + +``` + +### Theme Options + +The `data-theme` attribute controls the overall color scheme of the widget: + +- **`light`** (default) -- White background with dark text. Suitable for most sites. +- **`dark`** -- Dark background with light text. Ideal for sites with dark color schemes. + +```html + + + + + +``` + +### Position Options + +The `data-position` attribute controls where the floating button appears: + +- **`bottom-right`** (default) -- Fixed to the bottom-right corner +- **`bottom-left`** -- Fixed to the bottom-left corner + +## Submitter Information + +Control whether the feedback form collects the submitter's name and email address. + +| Attribute | Default | Description | +|-----------|---------|-------------| +| `data-show-name` | `"false"` | Show the name field in the form | +| `data-require-name` | `"false"` | Make the name field required (implies `data-show-name="true"`) | +| `data-show-email` | `"false"` | Show the email field in the form | +| `data-require-email` | `"false"` | Make the email field required (implies `data-show-email="true"`) | + +### Submitter Info Example + +```html + + +``` + +When submitter information is collected, it is included in the GitHub Issue body so your team knows who reported the issue. + +## Dismissible Button + +Allow users to dismiss the floating button so it does not obstruct their view. This is especially useful for content-heavy sites where the button might overlay important elements. + +| Attribute | Default | Description | +|-----------|---------|-------------| +| `data-button-dismissible` | `"false"` | Allow users to dismiss (hide) the floating button | +| `data-dismiss-duration` | `"session"` | How long the button stays dismissed: `"session"` (until tab close) or a number in minutes (e.g., `"60"`) | +| `data-show-restore` | `"true"` | Show a small restore link after dismissing | + +### Dismissible Button Example + +```html + + +``` + +When a user dismisses the button: + +1. The floating button hides +2. If `data-show-restore` is `"true"`, a small "Restore feedback button" link appears in the corner +3. The button stays hidden for the duration specified by `data-dismiss-duration` +4. After the duration expires (or the session ends), the button reappears automatically + +## Feedback Categories + +Users can choose from three feedback categories when submitting a report. 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. + +## Automatic System Information + +Every feedback submission automatically captures the following system information, with no configuration required: + +| Field | Example | Description | +|-------|---------|-------------| +| Browser | `Chrome 120.0.0.0` | Browser name and version | +| OS | `macOS 14.2.1` | Operating system and version | +| Viewport | `1920x1080` | Browser window dimensions | +| Language | `en-US` | Browser language setting | +| URL | `https://example.com/page` | Current page URL | + +This information is included in every GitHub Issue body under a "System Info" section, giving your team the context they need to reproduce and fix bugs. + +## Custom Icon and Label + +### Custom Icon + +The `data-icon` attribute lets you replace the default bug icon with your own: + +```html + + + + + +``` + +When using a custom icon URL, the image is displayed at 24x24 pixels inside the button. SVG format is recommended for best quality at all screen densities. + +### Custom Label + +The `data-label` attribute adds a text label next to the button icon: + +```html + + + + + +``` + +## API-Only Mode + +Set `data-button="false"` to hide the floating button entirely. This is useful when you want to trigger the widget from your own UI elements using the [JavaScript API](/docs/javascript-api): + +```html + +``` + +In API-only mode, the widget loads but no button appears. Use `window.BugDrop.open()` to show the feedback form programmatically. See the [JavaScript API documentation](/docs/javascript-api) for details. + +## Complete Configuration Example + +Here is a script tag using many configuration options together: + +```html + +``` + +This configuration creates a dark-themed widget in the bottom-left corner with an indigo accent color, collects the submitter's name and email (email required), and shows a "Feedback" label on the button. The button is dismissible for 2 hours with a restore link. + +## Next Steps + +- [Style the widget](/docs/styling) with custom fonts, colors, borders, and shadows +- [Use the JavaScript API](/docs/javascript-api) for programmatic control +- [Pin to a specific version](/docs/version-pinning) for production stability diff --git a/src/content/docs/faq.mdx b/src/content/docs/faq.mdx index 90042fb..f2b5a13 100644 --- a/src/content/docs/faq.mdx +++ b/src/content/docs/faq.mdx @@ -1,21 +1,213 @@ -# FAQ +# Frequently Asked Questions -## Does BugDrop work with private repositories? +Answers to the most common questions about BugDrop. If your question is not covered here, open an issue on the [GitHub repository](https://github.com/mean-weasel/bugdrop/issues). -Yes. The GitHub App works with both public and private repositories. +## General -## Is any data stored on your servers? +### What is BugDrop? -Screenshots are uploaded as part of the GitHub issue creation process and stored on GitHub, not on BugDrop servers. +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. -## Does BugDrop use cookies or tracking? +### How does BugDrop work? -No. BugDrop uses no cookies, no tracking, and no analytics. URLs in bug reports are automatically redacted. +BugDrop works in three steps: -## Can I customize the widget's appearance? +1. **User clicks the button** -- A floating button appears on your site. Clicking it opens a feedback form rendered inside a Shadow DOM. +2. **User submits feedback** -- The user fills in a title, description, selects a category (Bug, Feature, or Question), and optionally attaches a screenshot. System info (browser, OS, viewport, language, URL) is captured automatically. +3. **GitHub Issue created** -- The form submission is sent to a Cloudflare Worker API, which creates a GitHub Issue in your repository with all the details, labels, and screenshot. -Yes. BugDrop supports extensive [styling customization](/docs/styling) through `data-*` attributes. +### Is BugDrop free? -## What browsers are supported? +Yes. BugDrop is completely free and open source under the [MIT License](https://github.com/mean-weasel/bugdrop/blob/main/LICENSE). There are no paid tiers, usage limits (beyond rate limiting), or premium features. You can use it on personal projects, commercial products, and enterprise applications without restriction. -BugDrop works in all modern browsers (Chrome, Firefox, Safari, Edge). It uses Shadow DOM for style isolation. +### Is BugDrop free for commercial use? + +Yes. The MIT License permits commercial use, modification, distribution, and private use. You can use BugDrop on commercial websites, SaaS products, and internal tools without paying any fees or attributing the project (though attribution is appreciated). + +### Does BugDrop work with React, Next.js, Vue, and other frameworks? + +Yes. BugDrop is a plain JavaScript widget loaded via a ` + + + +``` + +Each site sends feedback to its own repository. There is no limit to the number of repositories you can use BugDrop with. + +### How do I remove BugDrop? + +To completely remove BugDrop: + +1. **Remove the script tag** from your HTML. This immediately stops the widget from appearing on your site. +2. **Uninstall the GitHub App** (optional) -- Go to GitHub Settings > Applications > Installed GitHub Apps and uninstall the BugDrop app. This revokes all permissions. +3. **Delete the screenshots branch** (optional) -- Delete the `bugdrop-screenshots` branch from your repository to remove stored screenshots. + +Removing the script tag is all that is needed to stop BugDrop from appearing. Steps 2 and 3 are optional cleanup. + +### Why can't I use async or defer on the script tag? + +BugDrop needs to initialize synchronously to ensure the widget is ready as early as possible and to properly read its configuration from the script tag's data attributes. Using `async` or `defer` can cause the widget to initialize after other scripts have run, which may lead to race conditions with the `bugdrop:ready` event or the `window.BugDrop` API. + +## Configuration + +### Does BugDrop support custom labels? + +Yes. The `data-label` attribute adds a text label next to the button icon: + +```html + +``` + +You can also set `data-icon="none"` to show only the text label without an icon: + +```html + +``` + +### 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. + +### Can I collect the user's name and email? + +Yes. By default, the name and email fields are hidden. Enable them with data attributes: + +```html + + +``` + +When enabled, the submitter's name and email are included in the GitHub Issue body. + +## Rate Limiting and Errors + +### What happens if the API is rate limited? + +When a rate limit is exceeded, the API returns an HTTP `429 Too Many Requests` response with a `Retry-After` header indicating how many seconds to wait. The widget displays a user-friendly message telling the user to try again later. + +Rate limits are: + +| Scope | Limit | Window | +|-------|-------|--------| +| Per IP | 10 requests | 15 minutes | +| Per Repository | 50 requests | 1 hour | + +These limits are designed to be invisible to legitimate users while preventing automated abuse. If you need higher limits, consider [self-hosting](/docs/self-hosting). + +### What if the GitHub API is down? + +If the GitHub API is unavailable when a user submits feedback, the BugDrop API will return an error and the widget will display a message asking the user to try again later. Submissions are not queued or retried automatically -- the user must resubmit after the issue is resolved. + +## Privacy and Security + +### Does BugDrop track users? + +No. BugDrop does not set cookies, use local storage for tracking, send analytics, or fingerprint users. The only data sent to the server is the feedback form contents (title, description, category, optional screenshot, optional name/email, and automatically captured system information). This data goes directly to your GitHub repository and is not stored anywhere else. + +### Where is my data stored? + +All data is stored in your GitHub repository: + +- **Issues** are created as GitHub Issues with labels and formatted bodies +- **Screenshots** are committed to the `bugdrop-screenshots` branch in a `.bugdrop/` directory + +No data is stored on the Cloudflare Worker. The API is stateless -- it receives the form submission, creates the GitHub Issue, and discards the data. + +### Can I self-host BugDrop? + +Yes. BugDrop can be self-hosted on your own Cloudflare Workers account with your own GitHub App. This gives you full control over the infrastructure, credentials, and rate limits. See the [Self-Hosting](/docs/self-hosting) page for an overview and the [SELF_HOSTING.md](https://github.com/mean-weasel/bugdrop/blob/main/SELF_HOSTING.md) file in the repository for full instructions. + +## Troubleshooting + +### The widget is not appearing on my site + +Check the following: + +1. **Verify the script tag** -- Make sure it does not have `async` or `defer` attributes +2. **Check the console** -- Open your browser's developer console and look for `[BugDrop]` messages or errors +3. **Check CSP** -- If your site uses a Content Security Policy, make sure `https://bugdrop.neonwatty.workers.dev` and `https://cdn.jsdelivr.net` are allowed in `script-src` +4. **Check the repo** -- Ensure `data-repo` matches your GitHub repository path exactly (case-sensitive) +5. **Check app installation** -- Verify the BugDrop GitHub App is installed on the repository + +### Issues are not being created + +If the widget appears but submissions fail: + +1. **Check the GitHub App** -- Make sure it is installed on the correct repository with Issues and Contents permissions +2. **Check rate limits** -- You may have hit the per-IP or per-repository rate limit +3. **Check the console** -- Look for error messages in the browser developer console +4. **Check the network tab** -- Inspect the API request to see the response status and body + +### Screenshots are not being uploaded + +If issues are created but without screenshots: + +1. **Check branch protection** -- The GitHub App needs permission to push to the `bugdrop-screenshots` branch. See the [Installation](/docs/installation) page for details on branch protection configuration. +2. **Check CSP** -- The html2canvas library is loaded from `cdn.jsdelivr.net`. Make sure it is allowed by your Content Security Policy. +3. **Cross-origin content** -- html2canvas cannot capture cross-origin iframes or images loaded without CORS headers. These elements may appear blank in the screenshot. + +## Still Have Questions? + +- Browse the [GitHub Issues](https://github.com/mean-weasel/bugdrop/issues) for existing discussions +- Open a new issue on the [GitHub repository](https://github.com/mean-weasel/bugdrop/issues/new) +- Read the full [README](https://github.com/mean-weasel/bugdrop/blob/main/README.md) for additional details diff --git a/src/content/docs/getting-started.mdx b/src/content/docs/getting-started.mdx new file mode 100644 index 0000000..5cfd97b --- /dev/null +++ b/src/content/docs/getting-started.mdx @@ -0,0 +1,83 @@ +# Getting Started with BugDrop + +BugDrop is a lightweight, open-source bug reporting widget that lets your users submit bugs, feature requests, and questions directly from your website — straight into GitHub Issues. No backend to manage, no dashboard to maintain, and no third-party accounts for your users to create. Just a single script tag and you're up and running. + +## How It Works + +BugDrop operates in three simple steps, creating a seamless bridge between your users and your GitHub repository: + +### Step 1: User Clicks the Bug Button + +A small, customizable floating button appears on your site. When a user clicks it, a clean feedback form opens -- right inside the page, wrapped in a Shadow DOM so it never interferes with your site's styles. + +### Step 2: User Submits Feedback + +The user fills out the form with a title, description, and optional screenshot. They choose a category -- Bug, Feature Request, or Question -- and hit submit. BugDrop automatically captures system information like browser type, operating system, viewport size, language, and current URL. + +### Step 3: GitHub Issue Created + +BugDrop sends the report to your Cloudflare Worker API, which creates a GitHub Issue in your repository. Screenshots are committed to a dedicated `bugdrop-screenshots` branch, and the issue is labeled and formatted with all the context your team needs. + +That is it. No servers to run, no databases to manage, no user accounts required. + +## Why BugDrop? + +| Feature | BugDrop | Traditional Bug Trackers | +|---------|---------|--------------------------| +| Setup time | 30 seconds | Hours to days | +| Backend required | No (Cloudflare Workers) | Yes | +| User accounts | None required | Usually required | +| Where issues live | GitHub Issues | Separate dashboard | +| Cost | Free | Often paid | +| Customizable | Fully | Limited | +| Open source | Yes (MIT) | Rarely | + +## Key Features + +- **One-line installation** -- Add a single script tag and BugDrop is live on your site +- **Automatic screenshots** -- Users can attach screenshots captured client-side with html2canvas +- **System info capture** -- Browser, OS, viewport, language, and URL are automatically included +- **GitHub-native** -- Issues land directly in your repository with proper labels and formatting +- **Shadow DOM isolation** -- The widget never conflicts with your site's CSS +- **Fully customizable** -- Colors, position, icons, labels, themes, and more +- **JavaScript API** -- Programmatic control for advanced integrations +- **Version pinning** -- Pin to major, minor, or patch versions for stability +- **Rate limiting** -- Built-in protection against abuse +- **Privacy-first** -- No user data stored on external servers + +## Quick Links + +Ready to get started? Here is where to go next: + +- **[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 +- **[JavaScript API](/docs/javascript-api)** -- Programmatic control with `window.BugDrop` +- **[Version Pinning](/docs/version-pinning)** -- Lock to specific versions for production stability +- **[CI Testing](/docs/ci-testing)** -- Automated testing with Playwright +- **[Security](/docs/security)** -- Permissions, data storage, privacy, and rate limiting +- **[Self-Hosting](/docs/self-hosting)** -- Run your own BugDrop instance +- **[FAQ](/docs/faq)** -- Common questions answered + +## Requirements + +BugDrop works with any website. There are no framework dependencies, no build step required, and no npm packages to install. All you need is: + +1. A **GitHub repository** where issues will be created +2. The **BugDrop GitHub App** installed on that repository +3. A **script tag** added to your HTML + +BugDrop supports all modern browsers including Chrome, Firefox, Safari, and Edge. The widget is built with vanilla JavaScript and Web Components, so it works alongside React, Next.js, Vue, Svelte, Angular, or any other framework -- or no framework at all. + +## Example + +Here is the simplest possible BugDrop installation: + +```html + +``` + +That single script tag gives your users a fully functional bug reporting widget. From there, you can customize everything -- read the [Configuration](/docs/configuration) and [Styling](/docs/styling) docs to make it your own. diff --git a/src/content/docs/installation.mdx b/src/content/docs/installation.mdx index 2a47282..2765a85 100644 --- a/src/content/docs/installation.mdx +++ b/src/content/docs/installation.mdx @@ -1,21 +1,163 @@ # Installation -Get BugDrop running on your site in under a minute. +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. ## Step 1: Install the GitHub App -Install the [BugDrop GitHub App](https://github.com/apps/neonwatty-bugdrop/installations/new) on the repository where you want issues created. +BugDrop needs access to your GitHub repository to create issues and store screenshots. Install the official GitHub App to grant these permissions. -The app needs permission to create issues on your behalf. +**[Install BugDrop GitHub App](https://github.com/apps/neonwatty-bugdrop/installations/new)** + +During installation you will be asked which repositories to grant access to. You can choose specific repositories or grant access to all repositories in your account or organization. + +### What permissions does the app request? + +| Permission | Access Level | Purpose | +|-----------|-------------|---------| +| Issues | Read & Write | Create bug reports as GitHub Issues | +| Contents | Read & Write | Store screenshots in the repository | + +These are the minimum permissions required for BugDrop to function. The app does not request access to your code, pull requests, actions, or any other repository data. ## Step 2: Add the Script Tag -Add this to your HTML, replacing `owner/repo` with your GitHub repository: +Add the BugDrop script tag to your HTML, just before the closing `` tag: + +```html + +``` + +Replace `your-username/your-repo` with your actual GitHub repository path (e.g., `acme-corp/my-website`). + +### Full HTML Example + +```html + + + + + + My Website + + + + + + + + +``` + +### Customized Example + +You can add data attributes to customize the widget's appearance and behavior: ```html + +``` + +See the [Configuration](/docs/configuration) and [Styling](/docs/styling) docs for all available attributes. + +## 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. + +## Important Notes + +### Do Not Use async or defer + +The BugDrop script tag should **not** include the `async` or `defer` attributes. The widget needs to load synchronously to properly initialize: + +```html + + + + + ``` -## Step 3: Done +### Content Security Policy (CSP) + +If your site uses a Content Security Policy, you will need to allow `cdn.jsdelivr.net` in your CSP directives. BugDrop loads the html2canvas library from jsDelivr for screenshot functionality: + +``` +Content-Security-Policy: script-src 'self' https://bugdrop.neonwatty.workers.dev https://cdn.jsdelivr.net; +``` + +If you have a strict CSP, make sure both the BugDrop worker domain and jsDelivr are included in your `script-src` directive. + +### Branch Protection and the Screenshots Branch + +BugDrop stores screenshots in a dedicated branch called `bugdrop-screenshots` in your repository. This branch is created automatically when the first screenshot is uploaded. + +**If you use branch protection rules**, make sure the BugDrop GitHub App has permission to push to the `bugdrop-screenshots` branch. You can do this by either: + +1. **Excluding the branch from protection rules** -- Add `bugdrop-screenshots` to the exclusion list in your branch protection settings +2. **Allowing the app to bypass protection** -- Add the BugDrop GitHub App (`neonwatty-bugdrop`) to the list of actors that can bypass branch protection + +Without this, screenshot uploads will fail silently, though the issue itself will still be created. + +### Framework-Specific Notes + +**React / Next.js**: Add the script tag to your `index.html`, or use a ` +``` + +## API-Only Mode + +When you want to trigger BugDrop entirely from your own UI -- such as a menu item, button, or keyboard shortcut -- set `data-button="false"` to hide the default floating button: + +```html + +``` + +In this mode, the widget loads and initializes but no floating button appears on the page. The feedback form is only accessible through `window.BugDrop.open()`. + +### Custom Trigger Button + +Here is a complete example of using API-only mode with your own button: + +```html + + + + + +``` + +## Menu Item Integration + +A common pattern is integrating BugDrop into your application's navigation or help menu. The key is waiting for BugDrop to be ready before wiring up your UI. + +### Using the `bugdrop:ready` Event + +BugDrop dispatches a `bugdrop:ready` event on the `document` when it finishes initializing. This is the recommended way to set up integrations: + +```html + + + + + +``` + +This pattern ensures: + +1. The "Report a Bug" link is hidden until BugDrop is ready +2. Once the widget initializes, the link becomes visible +3. Clicking the link opens the feedback form +4. The default floating button is hidden (`data-button="false"`) + +### Synchronous Check + +If your code runs after the page is fully loaded and you want to check whether BugDrop is already available, you can do a synchronous check: + +```html + +``` + +This "check first, listen second" pattern is useful in single-page applications where your code might run at various points in the page lifecycle. + +## Keyboard Shortcut Example + +You can bind BugDrop to a keyboard shortcut for power users: + +```html + +``` + +## React Integration Example + +In a React application, you can create a wrapper component: + +```tsx +import { useEffect, useState } from 'react'; + +function ReportBugButton() { + const [ready, setReady] = useState(false); + + useEffect(() => { + if (window.BugDrop) { + setReady(true); + } else { + const handler = () => setReady(true); + document.addEventListener('bugdrop:ready', handler); + return () => document.removeEventListener('bugdrop:ready', handler); + } + }, []); + + if (!ready) return null; + + return ( + + ); +} +``` + +## Combining API with Visible Button + +You do not have to choose between the floating button and the API. You can use both: + +```html + + + + + + Report a Bug + +``` + +In this setup, users can either click the floating button or your navigation link to open the form. Both approaches open the same feedback form. + +## Programmatic Show/Hide + +The `show()` and `hide()` methods let you control the floating button's visibility. This is useful for contexts where the button should only appear on certain pages or under certain conditions: + +```html + +``` + +## Next Steps + +- [Configure the widget](/docs/configuration) with data attributes +- [Style the widget](/docs/styling) to match your site design +- [Test your integration](/docs/ci-testing) with Playwright diff --git a/src/content/docs/security.mdx b/src/content/docs/security.mdx new file mode 100644 index 0000000..56efd81 --- /dev/null +++ b/src/content/docs/security.mdx @@ -0,0 +1,158 @@ +# Security + +BugDrop is designed with security and privacy at its core. This page covers the permissions the GitHub App requires, how data is stored, privacy guarantees, and the built-in rate limiting that protects against abuse. + +## GitHub App Permissions + +The BugDrop GitHub App requests the minimum permissions necessary to function: + +| Permission | Access Level | Purpose | +|-----------|-------------|---------| +| **Issues** | Read & Write | Create bug reports, feature requests, and questions as GitHub Issues | +| **Contents** | Read & Write | Store screenshots in the repository on the `bugdrop-screenshots` branch | + +BugDrop does **not** request access to: + +- Your source code (contents access is limited to the `bugdrop-screenshots` branch) +- Pull requests +- Actions or workflows +- Secrets or environment variables +- Organization settings +- Collaborators or team membership +- Any other repository or account data + +You can review and revoke the app's access at any time from your GitHub settings under **Applications > Installed GitHub Apps**. + +## Data Storage + +BugDrop follows a "GitHub-native" storage model. All data stays within your GitHub repository -- nothing is stored on external servers. + +### Issues + +Feedback submissions are created as GitHub Issues in your repository. Each issue includes: + +- Title and description from the user +- Feedback category (Bug, Feature, or Question) as a GitHub label +- Automatic system information (browser, OS, viewport, language, URL) +- Submitter name and email (if configured and provided) +- Link to the screenshot (if attached) + +### Screenshots + +Screenshots are stored as image files in a `.bugdrop/` directory on a dedicated `bugdrop-screenshots` branch in your repository. This design has several benefits: + +- **Screenshots do not clutter your main branch** -- They live on a separate branch that never merges into your codebase +- **Full version history** -- Every screenshot is a Git commit, giving you a full audit trail +- **GitHub-hosted** -- Images are served directly from GitHub, with no external image hosting +- **Easy cleanup** -- Delete the `bugdrop-screenshots` branch to remove all screenshots at once + +The screenshot branch is created automatically when the first screenshot is uploaded. No manual setup is required. + +### Screenshot Format + +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 +- 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 + +## Privacy + +BugDrop is built with a privacy-first approach: + +- **No user tracking** -- BugDrop does not set cookies, use local storage for tracking, or fingerprint users +- **No analytics** -- The widget does not send any telemetry, usage data, or analytics to any server +- **No external data storage** -- All data (issues and screenshots) is stored in your GitHub repository +- **No user accounts** -- Users submitting feedback do not need to create accounts or log in +- **No PII collection by default** -- Name and email fields are off by default. When enabled, this data goes only to the GitHub Issue in your repository +- **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 + +The only network requests BugDrop makes are: + +1. Loading the widget script from Cloudflare Workers +2. Loading html2canvas from cdn.jsdelivr.net (for screenshot functionality) +3. Submitting the feedback form to the BugDrop Cloudflare Worker API + +The API acts as a pass-through to the GitHub API -- it receives the form data, creates the issue and uploads the screenshot, and discards the data. Nothing is persisted on the Cloudflare Worker. + +## Rate Limiting + +BugDrop includes built-in rate limiting to protect against abuse and ensure fair usage. Rate limits are applied at the Cloudflare Worker API level. + +### Rate Limit Tiers + +| Scope | Limit | Window | Description | +|-------|-------|--------|-------------| +| **Per IP** | 10 requests | 15 minutes | Limits individual users from flooding the API | +| **Per Repository** | 50 requests | 1 hour | Limits total submissions to any single repository | + +Both limits are enforced simultaneously. A request must pass both the per-IP and per-repository checks to succeed. + +### Rate Limit Headers + +Every API response includes rate limit headers so you can monitor usage: + +| Header | Description | Example | +|--------|-------------|---------| +| `X-RateLimit-Limit` | Maximum requests allowed in the window | `10` | +| `X-RateLimit-Remaining` | Requests remaining in the current window | `7` | +| `Retry-After` | Seconds until the rate limit resets (only on 429 responses) | `420` | + +### 429 Response Behavior + +When a rate limit is exceeded, the API returns an HTTP `429 Too Many Requests` response with: + +- A JSON body containing an error message explaining which limit was hit +- A `Retry-After` header indicating how many seconds to wait before retrying + +The widget handles 429 responses gracefully by displaying a user-friendly message in the form. The user is told to try again later and shown approximately how long to wait. + +Example 429 response: + +```json +{ + "error": "Rate limit exceeded. Please try again later.", + "retryAfter": 420 +} +``` + +### Rate Limit Design Rationale + +The rate limits are set to be generous enough for legitimate usage while preventing abuse: + +- **10 per IP / 15 minutes** -- Even an active bug reporter rarely submits more than a few reports in 15 minutes. This limit stops automated scripts and spam while being invisible to real users. +- **50 per repository / hour** -- This allows a team of users to submit feedback without hitting limits, while preventing a single repository from being overwhelmed by a flood of submissions. + +If these limits are too restrictive for your use case, consider [self-hosting](/docs/self-hosting) BugDrop with custom rate limit configuration. + +## Security Best Practices + +### For Site Owners + +1. **Review app permissions** -- Periodically check the BugDrop GitHub App's permissions in your GitHub settings +2. **Monitor the screenshots branch** -- Occasionally review the `bugdrop-screenshots` branch for unexpected content +3. **Use branch protection** -- Keep your main branch protected. BugDrop only needs write access to the `bugdrop-screenshots` branch +4. **Set up CSP** -- If you use a Content Security Policy, explicitly whitelist the required domains rather than using broad wildcards + +### For Self-Hosters + +If you run your own instance of BugDrop: + +1. **Rotate your GitHub App credentials** regularly +2. **Set appropriate rate limits** for your expected traffic +3. **Monitor your Cloudflare Worker logs** for unusual activity +4. **Keep your instance updated** with the latest version + +## Reporting Security Issues + +If you discover a security vulnerability in BugDrop, please report it responsibly: + +- **Do not** create a public GitHub Issue for security vulnerabilities +- Contact the maintainers directly through GitHub's private vulnerability reporting feature on the [BugDrop repository](https://github.com/mean-weasel/bugdrop) + +## Next Steps + +- [Install BugDrop](/docs/installation) on your site +- [Self-host BugDrop](/docs/self-hosting) for full control +- [View the FAQ](/docs/faq) for common questions diff --git a/src/content/docs/self-hosting.mdx b/src/content/docs/self-hosting.mdx new file mode 100644 index 0000000..b256a5a --- /dev/null +++ b/src/content/docs/self-hosting.mdx @@ -0,0 +1,136 @@ +# Self-Hosting + +BugDrop can be self-hosted on your own infrastructure if you need full control over the API, custom rate limits, or want to keep everything within your own accounts. This page provides an overview of what is needed and points you to the full setup instructions. + +## Why Self-Host? + +The hosted version of BugDrop at `bugdrop.neonwatty.workers.dev` works great for most users. However, self-hosting makes sense when: + +- **You need custom rate limits** -- The hosted version has fixed rate limits (10 per IP / 15 min, 50 per repo / hour). Self-hosting lets you set whatever limits make sense for your traffic. +- **Compliance requirements** -- Your organization may require that all services run on infrastructure you control. +- **Custom domain** -- You want the API to run on your own domain (e.g., `bugdrop.yourcompany.com`). +- **Network isolation** -- You want the API within your own Cloudflare account for network-level controls. +- **Custom modifications** -- You want to modify the widget or API behavior beyond what the configuration options allow. + +## What You Need + +Self-hosting BugDrop requires two things: + +### 1. Cloudflare Workers Account + +BugDrop's API is built on [Cloudflare Workers](https://workers.cloudflare.com/), a serverless platform that runs at the edge. You need: + +- A Cloudflare account (free tier is sufficient for moderate usage) +- The [Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/) installed for deployment +- A Workers route or custom domain configured + +### 2. GitHub App + +You need to create your own GitHub App to replace the hosted BugDrop app. The app needs: + +| Setting | Value | +|---------|-------| +| **Permissions: Issues** | Read & Write | +| **Permissions: Contents** | Read & Write | +| **Webhook** | Not required (optional) | +| **Installation scope** | Your repositories | + +You will need the App ID, private key, and installation ID to configure the Worker. + +## Architecture Overview + +A self-hosted BugDrop deployment has the same architecture as the hosted version: + +``` +User's Browser + │ + ├── Loads widget.js from your Cloudflare Worker + │ + └── Submits feedback form + │ + ▼ + Your Cloudflare Worker (API) + │ + ├── Creates GitHub Issue (via GitHub API) + │ + └── Uploads screenshot to bugdrop-screenshots branch (via GitHub API) +``` + +The Cloudflare Worker acts as a secure proxy between the user's browser and the GitHub API. It holds the GitHub App credentials and handles authentication, so no secrets are ever exposed to the client. + +## Setup Instructions + +Full self-hosting instructions, including environment variables, Wrangler configuration, and deployment steps, are available in the repository: + +**[SELF_HOSTING.md on GitHub](https://github.com/mean-weasel/bugdrop/blob/main/SELF_HOSTING.md)** + +The guide covers: + +1. **Forking the repository** -- Get your own copy of the BugDrop codebase +2. **Creating a GitHub App** -- Step-by-step instructions for creating and configuring the app +3. **Configuring Wrangler** -- Setting up `wrangler.toml` with your account details +4. **Setting secrets** -- Storing your GitHub App credentials as Worker secrets +5. **Deploying** -- Publishing the Worker to your Cloudflare account +6. **Testing** -- Verifying the deployment works end-to-end +7. **Updating the script tag** -- Pointing your widget to your own Worker URL + +## Updating the Script Tag + +After deploying your own instance, update the script tag on your site to point to your Worker: + +```html + + + + + +``` + +If you have configured a custom domain for your Worker: + +```html + +``` + +All `data-*` attributes work the same regardless of whether you use the hosted or self-hosted version. + +## Keeping Up to Date + +When new versions of BugDrop are released, you can pull the latest changes into your fork and redeploy: + +```bash +# Add the upstream remote (one-time setup) +git remote add upstream https://github.com/mean-weasel/bugdrop.git + +# Pull latest changes +git fetch upstream +git merge upstream/main + +# Redeploy +npx wrangler deploy +``` + +Check the [CHANGELOG](https://github.com/mean-weasel/bugdrop/blob/main/CHANGELOG.md) before updating to review any breaking changes or new configuration options. + +## Support + +If you run into issues with self-hosting: + +- Check the [FAQ](/docs/faq) for common questions +- Open an issue on the [GitHub repository](https://github.com/mean-weasel/bugdrop/issues) +- Review the [Security](/docs/security) page for permission and rate limiting details + +## Next Steps + +- [Read the full self-hosting guide](https://github.com/mean-weasel/bugdrop/blob/main/SELF_HOSTING.md) +- [Review security and permissions](/docs/security) +- [Configure the widget](/docs/configuration) diff --git a/src/content/docs/styling.mdx b/src/content/docs/styling.mdx index ac6880e..a51b2b6 100644 --- a/src/content/docs/styling.mdx +++ b/src/content/docs/styling.mdx @@ -1,17 +1,202 @@ # Styling -BugDrop's widget can be fully styled to match your app's design system using `data-*` attributes. +BugDrop is designed to blend seamlessly into any website. Beyond the core theme and color options, a full set of styling attributes gives you fine-grained control over fonts, border radius, backgrounds, text colors, borders, and shadows. The widget renders inside a Shadow DOM, so your site's styles never leak in and the widget's styles never leak out. ## Styling Attributes -| Attribute | Values | Default | -|-----------|--------|---------| -| `data-font` | `inherit`, or font-family string | Space Grotesk | -| `data-radius` | Pixels (e.g. `0`, `8`, `16`) | `6` | -| `data-bg` | CSS color | theme default | -| `data-text` | CSS color | theme default | -| `data-border-width` | Pixels (e.g. `4`) | `1` | -| `data-border-color` | CSS color | theme default | -| `data-shadow` | `soft`, `hard`, `none` | `soft` | - -The widget renders inside a Shadow DOM, so your page styles won't interfere with it. +All styling is done through data attributes on the script tag. No CSS files to import, no class names to override. + +| Attribute | Default | Description | +|-----------|---------|-------------| +| `data-font` | `"system-ui, sans-serif"` | Font family for all widget text | +| `data-radius` | `"8px"` | Border radius for the form and elements | +| `data-bg` | Theme-dependent | Background color of the widget form | +| `data-text` | Theme-dependent | Text color inside the widget | +| `data-border-width` | `"1px"` | Border width of the form container | +| `data-border-color` | Theme-dependent | Border color of the form container | +| `data-shadow` | `"0 8px 30px rgba(0,0,0,0.12)"` | Box shadow of the form container | + +### Defaults by Theme + +The `data-theme` attribute sets sensible defaults for colors, which you can then override individually: + +| Attribute | Light Theme Default | Dark Theme Default | +|-----------|--------------------|--------------------| +| `data-bg` | `#ffffff` | `#1a1a2e` | +| `data-text` | `#1a1a2e` | `#e0e0e0` | +| `data-border-color` | `#e0e0e0` | `#2a2a4a` | + +## Shadow DOM Isolation + +BugDrop renders inside a [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM), which provides complete CSS isolation between the widget and your website. This means: + +- **Your site's CSS cannot affect the widget** -- No accidental style overrides, even with aggressive global selectors +- **The widget's CSS cannot affect your site** -- BugDrop's internal styles stay contained +- **No class name collisions** -- BugDrop uses its own scoped styles internally +- **Predictable rendering** -- The widget looks the same regardless of what CSS frameworks or resets your site uses + +This is why styling is done through data attributes rather than CSS classes. The Shadow DOM boundary means external CSS simply cannot reach the widget's internals. + +### The `data-font="inherit"` Exception + +There is one exception to the Shadow DOM isolation: the `data-font="inherit"` value. When you set `data-font="inherit"`, BugDrop reads your page's computed `font-family` at initialization time and applies it inside the Shadow DOM. This lets the widget match your site's typography without you needing to specify the exact font stack: + +```html + + +``` + +This is especially useful when your site uses a custom font loaded via `@font-face` or Google Fonts -- you do not need to repeat the font family name in the data attribute. + +## Design Examples + +### Elegant Serif Site + +For a sophisticated, editorial-style site with serif typography: + +```html + +``` + +This creates a widget with: +- Classic serif fonts that match an editorial design +- Minimal border radius for sharp, refined corners +- Warm off-white background with muted gold accents +- Subtle shadow that does not compete with the content + +### Bold Brutalist Design + +For a bold, high-contrast site with a brutalist aesthetic: + +```html + +``` + +This creates a widget with: +- Monospace font for a raw, technical feel +- Zero border radius for hard, square corners +- Thick black borders with a hard offset shadow (no blur) +- High contrast black and white with a red accent + +### Minimal Dark Mode + +For a clean dark-themed site: + +```html + +``` + +### Soft Pastel Theme + +For a friendly, approachable site with soft colors: + +```html + +``` + +## Custom Icon and Label + +The button's icon and label text can be customized through the `data-icon` and `data-label` attributes: + +### Custom Icon + +```html + + +``` + +The custom icon is rendered at 24x24 pixels inside the floating button. Use an SVG or a high-resolution PNG (at least 48x48) for best results on retina displays. + +### Hiding the Icon + +Set `data-icon="none"` to show only a text label: + +```html + +``` + +### Icon + Label Combination + +Combine a custom icon with a text label for maximum clarity: + +```html + +``` + +## Tips for Consistent Styling + +1. **Match your site's border radius** -- If your site uses rounded corners (e.g., Tailwind's `rounded-lg` is `8px`), set `data-radius` to match +2. **Use your brand's primary color** -- Set `data-color` to your brand's primary or accent color for the button and form highlights +3. **Consider `data-font="inherit"`** -- Unless you want the widget to look deliberately different from your site, `inherit` is the easiest way to match typography +4. **Test both themes** -- If your site supports light and dark mode, test BugDrop with both `data-theme="light"` and `data-theme="dark"` +5. **Shadow depth signals importance** -- A larger shadow makes the widget feel more prominent; a subtle shadow lets it blend in + +## Next Steps + +- [Configure widget behavior](/docs/configuration) with all available attributes +- [Use the JavaScript API](/docs/javascript-api) for programmatic control +- [Test your configuration](/docs/ci-testing) with automated Playwright tests diff --git a/src/content/docs/version-pinning.mdx b/src/content/docs/version-pinning.mdx new file mode 100644 index 0000000..e9d99e8 --- /dev/null +++ b/src/content/docs/version-pinning.mdx @@ -0,0 +1,132 @@ +# Version Pinning + +BugDrop supports version pinning so you can control exactly which version of the widget runs on your site. By default, you always get the latest version. For production sites, you can pin to a major, minor, or exact patch version to avoid unexpected changes. + +## Default Behavior + +The default script URL always loads the latest version of the widget: + +```html + +``` + +This is fine for development and testing, but for production sites you may want more control over when updates are applied. + +## Version URL Reference + +BugDrop follows [semantic versioning](https://semver.org/) (major.minor.patch). You can pin to any level of specificity: + +| URL | Example | Update Behavior | Best For | +|-----|---------|----------------|----------| +| `/widget.js` | Always latest | Gets all updates automatically | Development, testing | +| `/widget.v1.js` | Major pin | Gets minor and patch updates (1.x.x) | **Production (recommended)** | +| `/widget.v1.1.js` | Minor pin | Gets patch updates only (1.1.x) | Cautious production | +| `/widget.v1.1.0.js` | Exact pin | Never updates automatically | Maximum control | + +### Major Version Pin (Recommended for Production) + +```html + +``` + +This loads the latest `1.x.x` release. You get bug fixes and new features automatically, but never a breaking change. This is the recommended approach for production sites because: + +- **You get bug fixes automatically** -- No action needed when patches are released +- **You get new features** -- Minor version updates add functionality without breaking existing behavior +- **You are protected from breaking changes** -- Major version bumps (which may change the API or behavior) require you to explicitly update the URL + +### Minor Version Pin + +```html + +``` + +This loads the latest `1.1.x` release. You only get patch updates (bug fixes and security patches). New features from minor versions are not included until you manually update the URL. Use this if you want maximum stability while still receiving critical fixes. + +### Exact Version Pin + +```html + +``` + +This loads exactly version `1.1.0` and never changes. You must manually update the URL to get any updates, including bug fixes and security patches. Use this only if you need absolute reproducibility or are running your own update process. + +## How Versioned URLs Work + +When a new version of BugDrop is released, the build process generates versioned copies of the widget file: + +- `widget.js` -- Always points to the latest version +- `widget.v1.js` -- Points to the latest `1.x.x` version +- `widget.v1.1.js` -- Points to the latest `1.1.x` version +- `widget.v1.1.0.js` -- Points to exactly `1.1.0` + +All versioned files are served from the same Cloudflare Worker, so there is no performance difference between them. + +## Choosing the Right Pin Level + +Here is a decision guide: + +### Use `/widget.js` (no pin) when: +- You are in active development +- You are testing the widget locally +- You want to always have the latest features and fixes +- You are comfortable with occasional behavior changes + +### Use `/widget.v1.js` (major pin) when: +- You are running a production site +- You want automatic bug fixes and new features +- You want protection from breaking API changes +- **This is the recommended default for most production sites** + +### Use `/widget.v1.1.js` (minor pin) when: +- You want only bug fixes, not new features +- You have specific behavior you depend on and want to avoid any UI changes +- You prefer to manually opt in to new features + +### Use `/widget.v1.1.0.js` (exact pin) when: +- You need bit-for-bit reproducibility +- You have a formal change management process +- You run your own testing pipeline before updating dependencies +- You are embedding BugDrop in a product where stability is critical + +## Upgrading Versions + +To upgrade from one version to another, simply change the URL in your script tag: + +```html + + + + + +``` + +Before upgrading to a new major version, check the [CHANGELOG](https://github.com/mean-weasel/bugdrop/blob/main/CHANGELOG.md) for breaking changes and migration instructions. + +## Checking Your Current Version + +You can check which version of BugDrop is loaded by opening your browser's developer console and typing: + +```javascript +console.log(window.BugDrop); +``` + +The widget version is also included in the console log message when the widget initializes. + +## Next Steps + +- [View the CHANGELOG](https://github.com/mean-weasel/bugdrop/blob/main/CHANGELOG.md) for release history +- [Configure the widget](/docs/configuration) with data attributes +- [Test your setup](/docs/ci-testing) with Playwright