Widget
The embeddable script your end users see. What it does, what it ships, and how the API key is treated.
The widget is a single <script> tag. It renders a floating "Report a bug" button, opens a modal when clicked, posts the report to your honeycomb's inbox, and optionally lets the user attach an image.
Install
<script
src="https://bichito-api.fly.dev/widget.js"
data-key="sk_your_project_key"
async
></script>
That's it — no SDK to install, no build step. The data-key is your project's publishable API key (more on what that means in Transparency below).
For framework-specific snippets (Next.js, React, Vue, Astro, WordPress), use the Onboarding → Install step inside the dashboard — it generates the right one with your key already filled in.
Image attachments
The widget always lets the user attach one image per report, up to 2 MB. Allowed types: PNG, JPEG, WEBP.
The user clicks "Attach image", picks a file from their device, and sees a preview before submitting. They can also paste an image with Ctrl+V while the modal is open. There is no setting to enlarge the cap, lower it, or disable it — same contract on every plan.
If you want the widget to also offer a "Capture screen" button that screenshots the current page (uses html2canvas, ~50 KB lazy-loaded), opt in:
<script
src="https://bichito-api.fly.dev/widget.js"
data-key="sk_your_project_key"
data-screenshots="true"
async
></script>
The 2 MB cap applies to screen captures too — html2canvas downscales the page to fit on most viewports, but on very dense screens you may want to omit the option.
Configuration
All knobs are data-* attributes on the <script> tag.
| Attribute | Default | Effect |
|---|---|---|
data-key | — | Required. Your project's API key. Starts with sk_. |
data-position | bottom-right | Launcher button position. One of bottom-right, bottom-left, top-right, top-left. |
data-button | true | Set to false to hide the floating button (open the modal yourself via window.BugWidget.open()). |
data-show-email | true | Show the email field on the form. |
data-require-email | false | Make the email field required. |
data-lang | auto-detect | Force es or en. Auto-detects from navigator.language. |
data-screenshots | false | Add a "Capture screen" button alongside the file picker. |
CSS variables let you re-skin without forking — see the theming section.
Theming
The widget ships its own styles inside a Shadow DOM, so it can't break your CSS and your CSS can't break it. To customize, set CSS variables on :root (they're inherited into the Shadow DOM):
:root {
--bugw-primary: oklch(0.78 0.17 75); /* launcher + submit button */
--bugw-primary-hover: oklch(0.74 0.18 70);
--bugw-radius: 18px; /* modal corner radius */
--bugw-launcher-radius: 999px; /* round launcher */
--bugw-z-index: 2147483000; /* float above your modals */
}
Full list of variables in the widget.js source.
Transparency
Is the
sk_key in my HTML a security risk?No — and we want to be upfront about why.
The widget runs inside your end-user's browser, so the sk_… key has to ship to the browser. Anyone visiting your site can read it from DevTools → Network. We treat it the way Stripe treats pk_… keys or Sentry treats DSNs: publishable by design, not secret.
What that means in practice:
- The key only grants the right to POST a bug report for the project it belongs to. It cannot read other reports, see your dashboard, change project settings, or touch other projects.
- It is rate-limited to 60 reports / minute / key (rate-limits doc) so a leaked key cannot be used to DDoS your inbox.
- Free plans are additionally capped at 100 reports / month.
- Image uploads go through a presigned URL flow, gated server-side by the same key, with the 2 MB hardcoded cap mentioned above.
- If you ever suspect a key is being abused, rotate it from your honeycomb's Settings → Additional API keys (the old key stops working immediately).
What we don't do
- We don't try to "hide" the key by minifying or obfuscating it. That gives a false sense of security.
- We don't gate POST behind a server-side proxy — that would make the widget useless for static-site embedders and add a hop without changing the security model.
When env vars are still a good idea
Even though the key is publishable, storing it in an env var (NEXT_PUBLIC_BICHITO_KEY, VITE_BICHITO_KEY, etc.) and templating it into your snippet is good hygiene: a leaked source repo doesn't leak the key, and you can rotate without touching code. We recommend it where your framework supports it. For pure HTML / WordPress / static sites with no build step, inlining the key is fine.
Calling the widget from JS
The script exposes a tiny global once it loads:
window.BugWidget.open(); // open the modal programmatically
window.BugWidget.close(); // close it
window.BugWidget.identify({
user_id: "user_123", // anything that helps you find this user
email: "you@example.com" // pre-fills + saves you asking
});
If you set data-button="false", you get no floating button and you're expected to call open() from your own UI (e.g. a "Report a problem" link in your footer).
Branding
On the Free plan the modal shows a small "Powered by bichito" link in the footer. Pro projects hide it automatically — no data-* flag to toggle, the widget reads your project's plan from /api/v1/widget/info on init and decides for itself. The badge stays hidden on errors too, so if the bootstrap call fails (offline, blocked) Pro customers never see a stray badge.