Create a project & widget key
A project organizes your bugs, and a widget key is the credential that lets a capture method submit to it. This page explains what each one is, why widget keys can be public yet safe, how to name environments and set allowed origins, and a key strategy that keeps things clean as you grow.
If you just want the fastest path, the Quickstart covers the minimum. This page is the deeper reference for getting the setup right.
What a project is
A project is a container for related bugs — typically one application or product surface. It sits inside a workspace (your team's top-level container), and it's the scope for the widget keys that authorize submissions.
Most teams start with a single project and split into more as separate apps or surfaces emerge. Reports filed against a project all share the same dashboard view, status/severity workflow, comments, and activity timeline.
What a widget key is
A widget key is a public credential, formatted like bp_pub_…, that a
capture method uses to submit bugs to a specific project. You create widget keys
per project, per environment, and each key carries a list of allowed
origins.
You pass the key to the widget as its projectKey prop (also accepted as
publicKey). It identifies which project a submission belongs to and which
origins are permitted to send it.
Why a public key is safe
It's normal to be cautious about shipping a key in client-side code. Widget keys are designed for exactly that:
- They're public by design — they identify a project and authorize widget submissions, nothing more. They don't grant dashboard access, can't read other workspaces' data, and aren't your account credentials.
- They're origin-restricted — a submission is only accepted from an origin in the key's allowed origins list. A key copied to an unlisted site is rejected.
- They're rotatable and revocable — if a key is misused, rotate or revoke it in the dashboard and the old value stops working.
Think of a widget key like a publishable client key: safe to embed because its power is narrow and its accepted origins are pinned. Your private credentials — Supabase session JWTs and MCP tokens — are never used in widget code.
How it fits together
A workspace contains projects; each project has one or more widget keys; each key pins the origins allowed to use it; and only requests from those origins produce widget submissions on that project.
Create a project and key
- Create the project
In the dashboard, open Projects → New project and name it after the app or surface it covers. You can add more projects later.
- Open Widget keys
Open your project and go to Widget keys. This is where you create, rotate, and revoke the keys for this project.
- Create a key for an environment
Create a new key and set its environment — for example
local,staging, orproduction. Use one key per environment rather than reusing a single key everywhere (see the strategy below). - Add allowed origins
Add the exact origins permitted to submit with this key. An origin is scheme + host + port — for example
http://localhost:3000,https://staging.yourcompany.com, orhttps://app.yourcompany.com. Only listed origins will be accepted. - Copy the public key
Copy the
bp_pub_…value and pass it to your capture method asprojectKey. For the widget, see NPM widget; the same project's keys also back the browser extension.
Environment naming
Name keys for where they run so you can tell them apart at a glance and revoke the right one without disrupting others:
Development on a workstation. Allowed origin is usually http://localhost:3000
(use your actual dev port). Keep this separate so churn here never affects
production.
Pre-production / QA environments. Allowed origins are your staging hostnames,
e.g. https://staging.yourcompany.com.
Live traffic. Allowed origins are your production hostnames, e.g.
https://app.yourcompany.com. Treat this key as the one you protect most.
The key's environment also flows onto the reports it creates, so triagers can
see whether a bug came from local, staging, or production.
Allowed origins
Allowed origins are the security boundary for a public key. A few practical rules:
- Match the exact origin: scheme, host, and (if non-default) port must all
line up.
http://localhost:3000andhttp://localhost:5173are different origins. httpandhttpsare different origins — list whichever your environment actually serves.- Subdomains are distinct:
app.yourcompany.comdoes not coverstaging.yourcompany.com. - Keep the list tight — only the origins that genuinely load the widget. If
a submission returns a
403/origin error, the page's origin isn't on the list.
Rotation and revocation
Keys can change over time without breaking your setup if you plan for it:
- Rotate a key when you suspect exposure or on a routine cadence. Issue a new key, deploy it, then revoke the old one.
- Revoke a key immediately if it's leaked to an untrusted place or is no longer needed. Revoked keys stop being accepted.
- Because keys are per environment, rotating
localnever touchesproduction, and revoking a leakedstagingkey leaves live traffic unaffected.
Key hygiene
- Create one key per environment (
local,staging,production) - Pin allowed origins to the exact hosts that load the widget
- Rotate keys periodically and revoke promptly when exposed or unused
- Keep
localkeys scoped tolocalhostonly
- Reuse a single key across every environment
- Add broad or wildcard-style origins "just in case"
- Put private credentials (Supabase JWTs, MCP tokens) in widget code
- Leave keys for retired apps or origins active
Recommended strategy
Use one widget key per environment, per project. This gives you isolation (a problem in one environment never forces a change in another), clean attribution (reports show which environment they came from), and least-privilege origins (each key only trusts the hosts that actually run there). When you add a new project, repeat the same pattern rather than stretching an existing key across projects.