feat: whyrating - initial project from turbostarter boilerplate
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
---
|
||||
title: Overview
|
||||
description: Get started with browser extension monitoring in TurboStarter.
|
||||
url: /docs/extension/monitoring/overview
|
||||
---
|
||||
|
||||
# Overview
|
||||
|
||||
TurboStarter includes powerful, provider-agnostic monitoring helpers for the browser extension so you can understand **what failed**, **where it failed** (popup, content script, background), and **who it impacted**. The API is intentionally designed for simplicity and extensibility, so you can swap providers without rewriting your extension code.
|
||||
|
||||
## Capturing exceptions
|
||||
|
||||
Extensions have multiple runtimes. To get good coverage, capture errors in the places users actually feel them:
|
||||
|
||||
* **Popup / options UI**: React pages where runtime errors break interactions.
|
||||
* **Background (service worker)**: long-lived logic like alarms, message routing, and sync.
|
||||
* **Content scripts**: page integrations where DOM differences and CSP can trigger failures.
|
||||
* **Manual reporting**: wrap critical flows (auth, billing, webhooks-to-extension sync, imports) with `try/catch` and report with context.
|
||||
|
||||
<Tabs items={["Popup / options", "Background", "Content script"]}>
|
||||
<Tab value="Popup / options">
|
||||
```tsx
|
||||
import { captureException } from "@turbostarter/monitoring-extension";
|
||||
|
||||
export function ExampleButton() {
|
||||
const onPress = async () => {
|
||||
try {
|
||||
/* some risky operation */
|
||||
} catch (error) {
|
||||
captureException(error);
|
||||
}
|
||||
};
|
||||
|
||||
return <button onClick={onPress}>Trigger Exception</button>;
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab value="Background">
|
||||
```ts
|
||||
import { captureException } from "@turbostarter/monitoring-extension";
|
||||
|
||||
browser.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
||||
try {
|
||||
/* handle message */
|
||||
sendResponse({ ok: true });
|
||||
} catch (error) {
|
||||
captureException(error);
|
||||
sendResponse({ ok: false });
|
||||
}
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab value="Content script">
|
||||
```ts
|
||||
import { captureException } from "@turbostarter/monitoring-extension";
|
||||
|
||||
try {
|
||||
/* interact with the page DOM */
|
||||
} catch (error) {
|
||||
captureException(error);
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Callout type="warn" title="Don't rely on a single runtime">
|
||||
An exception in a content script won't automatically show up in your background logs (and vice versa). Add capture points in each runtime you ship, especially if you do message passing between them.
|
||||
</Callout>
|
||||
|
||||
## Identifying users
|
||||
|
||||
Monitoring becomes far more useful once reports can be tied to a stable identity. In extensions you often have two “identities”:
|
||||
|
||||
* **Anonymous, stable install id**: useful before sign-in (and to correlate issues with a device/install).
|
||||
* **Signed-in user**: once the user authenticates, identify with their user id so issues map to a real account.
|
||||
|
||||
TurboStarter's monitoring layer supports identifying the current user when your auth session resolves. When signed out, pass `null` (or your provider's preferred anonymous identity strategy).
|
||||
|
||||
```tsx title="monitoring.tsx"
|
||||
import { useEffect } from "react";
|
||||
import { identify } from "@turbostarter/monitoring-extension";
|
||||
import { authClient } from "~/lib/auth/client";
|
||||
|
||||
export const MonitoringProvider = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const session = authClient.useSession();
|
||||
|
||||
useEffect(() => {
|
||||
if (session.isPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
identify(session.data?.user ?? null);
|
||||
}, [session]);
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
```
|
||||
|
||||
<Callout title="Privacy defaults" type="error">
|
||||
Prefer **stable IDs** over PII. Only attach traits that help debugging (plan, role, extension version) and avoid secrets (tokens, passwords) or sensitive fields unless you've explicitly chosen to send them.
|
||||
</Callout>
|
||||
|
||||
## Providers
|
||||
|
||||
The starter supports multiple monitoring providers behind the same API, so you can start with one and switch later.
|
||||
|
||||
<Cards>
|
||||
<Card title="Sentry" href="/docs/extension/monitoring/sentry" />
|
||||
|
||||
<Card title="PostHog" href="/docs/extension/monitoring/posthog" />
|
||||
</Cards>
|
||||
|
||||
## Best practices
|
||||
|
||||
<Cards>
|
||||
<Card title="Include runtime + version context" className="shadow-none">
|
||||
Extension issues are often environment-specific. Make sure you can filter by
|
||||
runtime (popup/background/content script), extension version, and browser.
|
||||
</Card>
|
||||
|
||||
<Card title="Capture actionable failures" className="shadow-none">
|
||||
Focus on crashes and failures that break core flows; skip “expected” states
|
||||
like validation errors or user cancellations.
|
||||
</Card>
|
||||
|
||||
<Card title="Dedupe noisy loops" className="shadow-none">
|
||||
Background alarms, retries, and message loops can generate many identical
|
||||
errors. Guard your capture calls to keep signal high (and costs low).
|
||||
</Card>
|
||||
|
||||
<Card title="Keep environments separate" className="shadow-none">
|
||||
Don't mix dev/beta/stable releases. Tag builds so you can correlate spikes
|
||||
with a rollout and verify fixes quickly.
|
||||
</Card>
|
||||
</Cards>
|
||||
|
||||
With capture points in each runtime, user identification wired up, and a provider configured, extension monitoring becomes a tight feedback loop: you can spot regressions early, understand which surface area is failing and validate fixes confidently as you ship new versions.
|
||||
@@ -0,0 +1,167 @@
|
||||
---
|
||||
title: PostHog
|
||||
description: Learn how to setup PostHog as your browser extension monitoring provider.
|
||||
url: /docs/extension/monitoring/posthog
|
||||
---
|
||||
|
||||
# PostHog
|
||||
|
||||
[PostHog](https://posthog.com/) is a product analytics platform that also supports monitoring capabilities like error tracking and session replay. In extensions, it's especially useful when you want to connect “what broke” with “what the user did” right before the issue occurred.
|
||||
|
||||
TurboStarter keeps monitoring behind a unified API, so you can route exception captures from your popup, background, and content scripts to PostHog without rewriting the call sites.
|
||||
|
||||
<Callout type="warn" title="Prerequisite: PostHog account">
|
||||
To use PostHog as your monitoring provider, you'll need a PostHog instance. You can use [PostHog Cloud](https://app.posthog.com/signup) or [self-host](https://posthog.com/docs/self-host).
|
||||
</Callout>
|
||||
|
||||
<Callout type="info" title="You can also use it for extension analytics">
|
||||
PostHog is also supported as an analytics provider for the extension. If you want to track in-extension events, see the [analytics overview](/docs/extension/analytics/overview) and the [PostHog analytics configuration](/docs/extension/analytics/configuration#posthog).
|
||||
</Callout>
|
||||
|
||||

|
||||
|
||||
## Configuration
|
||||
|
||||
Here you'll configure PostHog as the monitoring provider for your extension so exceptions from the popup, background/service worker, and content scripts show up with enough context to debug.
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
### Create a project
|
||||
|
||||
Create a PostHog [project](https://app.posthog.com/project/settings) for your extension. You can do this from the [PostHog dashboard](https://app.posthog.com) via the *New Project* action.
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Activate PostHog as your monitoring provider
|
||||
|
||||
TurboStarter picks the extension monitoring provider through exports in the monitoring package. To route captures to PostHog, export the PostHog implementation from the extension monitoring entrypoint:
|
||||
|
||||
```ts title="index.ts"
|
||||
// [!code word:posthog]
|
||||
export * from "./posthog";
|
||||
export * from "./posthog/env";
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Set environment variables
|
||||
|
||||
Add your PostHog project key (and host, if you're not using the default cloud region) to your extension env. Set these locally and in whatever build environment produces your extension bundles:
|
||||
|
||||
```dotenv title="apps/extension/.env.local"
|
||||
VITE_POSTHOG_KEY="your-posthog-project-api-key"
|
||||
VITE_POSTHOG_HOST="https://us.i.posthog.com"
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
That's it — load the extension, trigger a test error from the popup/background/content script, and confirm events are arriving in your PostHog project.
|
||||
|
||||

|
||||
|
||||
If you want to go beyond basic capture (session replay, feature flags, richer context), follow PostHog's web/extension guidance.
|
||||
|
||||
<Cards>
|
||||
<Card title="Error tracking" href="https://posthog.com/docs/error-tracking" description="posthog.com" />
|
||||
|
||||
<Card title="Web error tracking installation" href="https://posthog.com/docs/error-tracking/installation/web" description="posthog.com" />
|
||||
</Cards>
|
||||
|
||||
## Uploading source maps
|
||||
|
||||
**Source maps** map the minified/bundled JavaScript shipped with your extension back to your original source code. Without them, stack traces in PostHog often point at compiled output, which makes debugging much slower.
|
||||
|
||||
<Callout>
|
||||
PostHog’s source map flow for web builds relies on injecting metadata into the bundled assets. You must deploy/ship the injected assets, otherwise PostHog can’t match captured errors to the uploaded symbol sets.
|
||||
</Callout>
|
||||
|
||||
For extensions built with Vite (which [WXT](https://wxt.dev/) is using under the hood), the high-level flow is:
|
||||
|
||||
* generate `.map` files during the production build
|
||||
* inject PostHog metadata into the built assets
|
||||
* upload the injected source maps to PostHog
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
### Install the PostHog CLI
|
||||
|
||||
Install the CLI globally:
|
||||
|
||||
```bash
|
||||
npm install -g @posthog/cli
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Authenticate the CLI
|
||||
|
||||
Authenticate interactively:
|
||||
|
||||
```bash
|
||||
posthog-cli login
|
||||
```
|
||||
|
||||
In CI, you can authenticate with environment variables:
|
||||
|
||||
```dotenv
|
||||
POSTHOG_CLI_HOST="https://us.posthog.com"
|
||||
POSTHOG_CLI_ENV_ID="your-posthog-project-id"
|
||||
POSTHOG_CLI_TOKEN="your-personal-api-key"
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Build with source maps enabled
|
||||
|
||||
Make sure your extension build outputs source maps by modifying your `wxt.config.ts` file.
|
||||
|
||||
```ts title="wxt.config.ts"
|
||||
import { defineConfig } from "wxt";
|
||||
|
||||
export default defineConfig({
|
||||
/* existing WXT configuration options */
|
||||
vite: () => ({
|
||||
build: {
|
||||
sourcemap: "hidden", // [!code ++] Source map generation must be turned on ("hidden", true, etc.)
|
||||
},
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
After building, you should have `.js` and `.js.map` files in your output directory.
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Inject PostHog metadata into the built assets
|
||||
|
||||
Inject release/chunk metadata so PostHog can associate uploaded maps with the shipped bundles:
|
||||
|
||||
```bash
|
||||
posthog-cli sourcemap inject --directory ./path/to/assets --project my-extension --version 1.2.3
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Upload source maps
|
||||
|
||||
Upload the injected source maps to PostHog:
|
||||
|
||||
```bash
|
||||
posthog-cli sourcemap upload --directory ./path/to/assets
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Verify injection and uploads
|
||||
|
||||
After deployment, confirm your production bundles include the injected comment (for example `//# chunkId=...`) and verify symbol sets exist in your PostHog project settings.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
With this in place, PostHog can symbolicate extension errors (popup/options UI, background/service worker, and content scripts) so stack traces point back to your original source files.
|
||||
|
||||
<Cards>
|
||||
<Card title="What are source maps?" href="https://web.dev/articles/source-maps" description="web.dev" />
|
||||
|
||||
<Card title="Upload source maps for web" href="https://posthog.com/docs/error-tracking/upload-source-maps/web" description="posthog.com" />
|
||||
</Cards>
|
||||
@@ -0,0 +1,149 @@
|
||||
---
|
||||
title: Sentry
|
||||
description: Learn how to setup Sentry as your browser extension monitoring provider.
|
||||
url: /docs/extension/monitoring/sentry
|
||||
---
|
||||
|
||||
# Sentry
|
||||
|
||||
[Sentry](https://sentry.io/) is a popular error monitoring and performance tracking platform. It helps you catch and debug issues by collecting exceptions, stack traces, and helpful context from production.
|
||||
|
||||
For browser extensions, that context matters even more: errors can happen in multiple runtimes (popup/options UI, background/service worker, and content scripts). Sentry makes it easier to see what failed and where it happened so you can ship fixes with confidence.
|
||||
|
||||
<Callout type="warn" title="Prerequisite: Sentry account">
|
||||
To use Sentry, create an account and a project first. You can sign up [here](https://sentry.io/signup).
|
||||
</Callout>
|
||||
|
||||

|
||||
|
||||
## Configuration
|
||||
|
||||
This section walks you through enabling Sentry for your extension and verifying that errors from the popup, background/service worker, and content scripts are captured reliably.
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
### Create a project
|
||||
|
||||
Create a Sentry [project](https://docs.sentry.io/product/projects/) for the extension (JavaScript / browser). You can do this from the Sentry [projects dashboard](https://sentry.io/settings/account/projects/) via the *Create Project* flow.
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Activate Sentry as your monitoring provider
|
||||
|
||||
TurboStarter picks the extension monitoring provider via exports in the monitoring package. To enable Sentry, export the Sentry implementation from the extension monitoring entrypoint:
|
||||
|
||||
```ts title="index.ts"
|
||||
// [!code word:sentry]
|
||||
export * from "./sentry";
|
||||
export * from "./sentry/env";
|
||||
```
|
||||
|
||||
If you need to customize behavior, the provider implementation lives under `packages/monitoring/extension/src/providers/sentry`.
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Set environment variables
|
||||
|
||||
From your Sentry project settings, add the DSN and environment to your extension env file (and to any [CI/build step](/docs/extension/publishing/checklist#build-your-app) that produces your extension bundles):
|
||||
|
||||
```dotenv title="apps/extension/.env.local"
|
||||
VITE_SENTRY_DSN="your-sentry-dsn"
|
||||
VITE_SENTRY_ENVIRONMENT="your-project-environment"
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
That's it — load the extension, trigger a test error from the popup/background/content script, and confirm it shows up in your [Sentry dashboard](https://sentry.io/settings/account/projects/).
|
||||
|
||||

|
||||
|
||||
For advanced options (sampling, releases, extra context), refer to [Sentry's JavaScript docs](https://docs.sentry.io/platforms/javascript/).
|
||||
|
||||
<Cards>
|
||||
<Card title="Quick Start" href="https://docs.sentry.io/platforms/javascript/" description="docs.sentry.io" />
|
||||
|
||||
<Card title="Manual Setup" href="https://docs.sentry.io/platforms/javascript/install/npm/" description="docs.sentry.io" />
|
||||
</Cards>
|
||||
|
||||
## Uploading source maps
|
||||
|
||||
**Source maps** map the bundled/minified JavaScript shipped with your extension back to your original source files. Without them, Sentry stack traces often point to compiled output, which makes debugging across popup/background/content-script runtimes much harder.
|
||||
|
||||
<Callout>
|
||||
Generating source maps can expose your source code if `.map` files are publicly accessible. Prefer hidden source maps and/or delete them after upload.
|
||||
</Callout>
|
||||
|
||||
Sentry can automatically provide readable stack traces for errors using source maps, requiring a [Sentry auth token](https://docs.sentry.io/account/auth-tokens/).
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
### Install the Sentry Vite plugin
|
||||
|
||||
Install the package `@sentry/vite-plugin` in `apps/extension/package.json` as a dev dependency.
|
||||
|
||||
```bash
|
||||
pnpm i @sentry/vite-plugin -D --filter extension
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Add an auth token for uploads
|
||||
|
||||
Create an [auth token in Sentry](https://docs.sentry.io/account/auth-tokens/) and provide it as an environment variable during builds (locally and in your build environment):
|
||||
|
||||
```dotenv
|
||||
SENTRY_AUTH_TOKEN="your-sentry-auth-token"
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Enable source maps and configure the plugin
|
||||
|
||||
Enable source map generation in your extension build and add `sentryVitePlugin` **after** your other Vite plugins:
|
||||
|
||||
```ts title="wxt.config.ts"
|
||||
import { defineConfig } from "wxt";
|
||||
import { sentryVitePlugin } from "@sentry/vite-plugin";
|
||||
|
||||
export default defineConfig({
|
||||
/* existing WXT configuration options */
|
||||
vite: () => ({
|
||||
build: {
|
||||
sourcemap: "hidden", // [!code ++] Source map generation must be turned on ("hidden", true, etc.)
|
||||
},
|
||||
plugins: [
|
||||
sentryVitePlugin({
|
||||
org: "your-sentry-org",
|
||||
project: "your-sentry-project",
|
||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||
|
||||
sourcemaps: {
|
||||
// As you're enabling client source maps, you probably want to delete them after they're uploaded to Sentry.
|
||||
// Set the appropriate glob pattern for your output folder - some glob examples below:
|
||||
filesToDeleteAfterUpload: [
|
||||
"./**/*.map",
|
||||
".*/**/public/**/*.map",
|
||||
"./dist/**/client/**/*.map",
|
||||
],
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step>
|
||||
### Verify uploads with a production build
|
||||
|
||||
The Sentry Vite plugin doesn't upload in dev/watch mode. Run a production build, then trigger a test error in the extension and confirm stack traces resolve to your original source.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
Once this is in place, errors from your extension's compiled bundles (popup/options UI, background/service worker, content scripts) should show **readable stack traces** in Sentry, without shipping source maps to end users.
|
||||
|
||||
<Cards>
|
||||
<Card title="What are source maps?" href="https://web.dev/articles/source-maps" description="web.dev" />
|
||||
|
||||
<Card title="Sentry Vite plugin" href="https://docs.sentry.io/platforms/javascript/sourcemaps/uploading/vite/" description="docs.sentry.io" />
|
||||
</Cards>
|
||||
Reference in New Issue
Block a user