Skip to main content

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.

CONCEPTS

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

  1. 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.

  2. Open Widget keys

    Open your project and go to Widget keys. This is where you create, rotate, and revoke the keys for this project.

  3. Create a key for an environment

    Create a new key and set its environment — for example local, staging, or production. Use one key per environment rather than reusing a single key everywhere (see the strategy below).

  4. 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, or https://app.yourcompany.com. Only listed origins will be accepted.

  5. Copy the public key

    Copy the bp_pub_… value and pass it to your capture method as projectKey. 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:

local

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.

staging

Pre-production / QA environments. Allowed origins are your staging hostnames, e.g. https://staging.yourcompany.com.

production

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:3000 and http://localhost:5173 are different origins.
  • http and https are different origins — list whichever your environment actually serves.
  • Subdomains are distinct: app.yourcompany.com does not cover staging.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 local never touches production, and revoking a leaked staging key leaves live traffic unaffected.

Key hygiene

Do
  • 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 local keys scoped to localhost only
Don't
  • 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

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.

Next steps