<gh-feedback>

Add a feedback button to any website. Files GitHub Issues.

Trigger Button

Style
Icon
Size
Color
Border
Position (FAB only)
Look for the feedback button in the corner of the page ↘
Theme
Color
Categories

Setup

1. Add the component to your page

Copy gh-feedback.js into your project and add to your HTML:

<script type="module" src="gh-feedback.js"></script>
<gh-feedback
  repo="https://github.com/you/repo"
  endpoint="https://your-worker.workers.dev/feedback"
></gh-feedback>

A hosted copy is also available as a convenience:

<script type="module" src="https://gh-feedback.synapticnoise.com/gh-feedback.js"></script>

2. Deploy a proxy backend

The component needs a backend to securely file GitHub Issues (so your token stays server-side). See Proxy Setup below, or use any backend that accepts the JSON payload.

Attributes Reference

Attribute Type Default Description
repo string -- GitHub repository URL or owner/repo format. Required.
endpoint string -- URL of the proxy endpoint (recommended). Component POSTs JSON here.
token string -- GitHub PAT for direct mode. Exposed in page source -- use proxy mode for public sites.
trigger string fab Trigger style: fab (floating action button), button (inline button), link (text link), or none (no trigger; open programmatically).
icon string memo Icon: chat, bug, megaphone, lightbulb, pencil, flag, memo, none.
size string md Size: sm, md, lg, or a number for pixel size (e.g. 40).
color string #238636 Primary color (hex). Sets the FAB, button, and accent color.
position string bottom-right FAB corner position: bottom-right, bottom-left, top-right, top-left. Only applies when trigger="fab".
theme string light Popup color theme: light or dark.
labels string -- Comma-separated labels added to every issue (e.g. "feedback,ui").
button-text string -- Text shown on the trigger. For FAB, makes it pill-shaped.
show-severity boolean -- When present, shows a severity selector (Low / Medium / High / Critical) for bug reports.
types string bug,feature,question Comma-separated list of feedback types to show. Available: bug, feature, question, ui, docs, performance.
border-color string -- Border color on the trigger element.
border-width string -- Border width in pixels on the trigger element.
border-radius string -- Border radius in pixels on the trigger element (overrides default).
popup-color string #238636 Accent color used inside the popup (e.g. submit button). Defaults to the primary color.
no-type-icons boolean -- When present, hides the emoji icons next to feedback type names in the popup.

Proxy Setup (Recommended)

The proxy keeps your GitHub token on the server. Users never see it.

1. Prerequisites

2. Create the worker

Copy the worker/ directory from this repo into your project, or start fresh:

mkdir gh-feedback-worker && cd gh-feedback-worker
cp -r /path/to/gh-feedback/worker/* .
npm init -y

3. Set your GitHub token

Create a fine-grained Personal Access Token:

  1. Go to github.com/settings/tokens
  2. Click Generate new token
  3. Name it something descriptive, e.g., gh-feedback-proxy
  4. Under Repository access, select Only select repositories and choose the repo
  5. Under Permissions > Repository permissions, set Issues to Read and Write
  6. Click Generate token and copy it

Then store it as a Wrangler secret:

npx wrangler secret put GITHUB_TOKEN
# Paste the token when prompted

4. Configure the worker

Open worker/wrangler.toml and set these two values:

5. Deploy

cd worker
npx wrangler deploy

Wrangler prints the worker URL, e.g., https://gh-feedback-proxy.your-account.workers.dev.

6. Use it

<gh-feedback repo="https://github.com/you/repo" endpoint="https://gh-feedback-proxy.your-account.workers.dev/feedback"></gh-feedback>

7. Verify

curl -X POST https://gh-feedback-proxy.your-account.workers.dev/feedback \
  -H "Content-Type: application/json" \
  -d '{"title": "Test issue from curl", "type": "bug"}'

You should get back {"issueNumber": ..., "issueUrl": "..."} and see the issue in your GitHub repo.

Multi-repo note: The worker always files issues to the repo configured in GITHUB_REPO. To file to multiple repos, deploy one worker per repo.

Alternative Backends

The component POSTs JSON to any URL. The worker/ template is for Cloudflare Workers, but any backend works. The contract:

POST { title, type, severity?, description, labels?, repo?, context? }
--> 201 { issueNumber, issueUrl }
--> 4xx/5xx { error: "message" }

Your backend receives this JSON, creates a GitHub Issue using a server-side token, and returns the result. The key requirement is that the endpoint holds the GitHub token server-side -- it never reaches the browser.

Any of these work:

The Cloudflare Worker in worker/ is a good reference implementation (~80 lines). Adapt it to your platform.

Direct Mode

If you don't want to set up a proxy, you can pass a GitHub token directly:

<gh-feedback repo="https://github.com/you/repo" token="ghp_yourTokenHere"></gh-feedback>
Warning: The token is visible in your page source and browser DevTools. Anyone who views your page can extract it. Only use direct mode for internal tools, localhost development, or pages behind authentication. For public sites, use proxy mode.

Events

Event Detail Cancelable Description
gh-feedback:submit { title, type, description, labels, repo, severity? } Yes Fires before submission. Call preventDefault() to cancel.
gh-feedback:filed { issueNumber, issueUrl } No Fires after issue is successfully created.

Listener example

document.querySelector('gh-feedback')
  .addEventListener('gh-feedback:filed', (e) => {
    console.log(`Issue #${e.detail.issueNumber}: ${e.detail.issueUrl}`);
  });

Context Capture

Set the getContext property to a function that returns an object. The data is attached to the issue body in a collapsible details section.

const fb = document.querySelector('gh-feedback');
fb.getContext = () => ({
  url: location.href,
  viewport: `${innerWidth}x${innerHeight}`,
  userAgent: navigator.userAgent,
  timestamp: new Date().toISOString()
});

Theming

For fine-grained control beyond the color attribute, override CSS custom properties on the gh-feedback element:

Property Light Default Dark Default
--gh-feedback-primary#238636#238636
--gh-feedback-primary-hover#2ea043#2ea043
--gh-feedback-bg#ffffff#1c2128
--gh-feedback-text#1f2328#e6edf3
--gh-feedback-border#d1d9e0#444c56
--gh-feedback-input-bg#f6f8fa#22272e
--gh-feedback-error#d1242f#d1242f
--gh-feedback-success#238636#238636
--gh-feedback-fab-bg(primary)(primary)
--gh-feedback-fab-text#ffffff#ffffff
<style>
  gh-feedback {
    --gh-feedback-primary: #6f42c1;
    --gh-feedback-primary-hover: #8250df;
  }
</style>
<gh-feedback repo="https://github.com/you/repo" endpoint="..." theme="dark"></gh-feedback>

Security & CSP

Proxy mode (recommended): Your GitHub token stays on the server. The browser only communicates with your worker endpoint.

Direct mode: The token is in the HTML source. Only for internal tools or pages behind auth.

If your site uses a strict Content Security Policy, add the proxy endpoint to connect-src:

Content-Security-Policy: connect-src 'self' https://your-worker.workers.dev;

Shadow DOM <style> elements are CSP-exempt in modern browsers, so no style-src changes are needed.

Development

Run the unit tests (worker):

npm install
npm test

Run the Playwright E2E tests:

npx playwright install --with-deps chromium
npx playwright test

Run all tests:

npm run test:all

License

MIT -- use it anywhere.