Getting started
From signup to your first event in five minutes.
1. Create an account
Sign up at glitchreplay.com/sign-up. You start on the Free plan — 10,000 events/month, 14-day retention, one project, one seat. No card required.
2. Create a project
From the dashboard, click New project. Pick a slug (used in URLs and webhook payloads) and a platform — the platform tag controls which SDK snippet the dashboard shows you on the setup screen, but it does not affect ingest. You can change it later.
After the project is created you'll see a DSN on theSetup tab. It looks like:
https://<public_key>@glitchreplay.com/0The path is /0, not your project ID. Sentry SDK 10'svalidateDsn requires the path to be all digits — non-numeric paths are rejected at the SDK boundary, silently disabling envelope POSTs. The envelope endpoint authenticates by the public key, so the path is informational; /0 is the conventional self-hosted placeholder.
The public key (the long hex string) is safe to ship in browser bundles — it's scoped to ingest only, and authenticates which project an event belongs to. It is not a secret. (Same trust model as the Sentry DSN.)
3. Install the SDK
For Next.js 15.3+ App Router (the canonical recipe — this is what we run on every site we instrument ourselves):
npm install --save \
@sentry/react \
@glitchreplay/a11y \
@glitchreplay/network-probe \
axe-coreUse @sentry/react, not @sentry/nextjs: the Next.js wrapper's Webpack plugin and Vercel build adapter conflict with @cloudflare/next-on-pages and @opennextjs/cloudflare. @sentry/react is a strict superset of @sentry/browser with Sentry.ErrorBoundary for React component-stack capture.
The two @glitchreplay/* packages are optional but cheap: accessibility scanning via axe-core, and ad-blocker-aware resource error verification.
4. Add instrumentation-client.ts
Create the file at the project root. Next 15.3+ runs it once on the client at startup, before any user code:
import * as Sentry from "@sentry/react";
import { axeIntegration } from "@glitchreplay/a11y";
import { networkProbeIntegration } from "@glitchreplay/network-probe";
const PROJECT_ID = "prj_..."; // from your dashboard URL
const PUBLIC_KEY = "..."; // hex string from the DSN
const DSN = `https://${PUBLIC_KEY}@glitchreplay.com/0`;
Sentry.init({
dsn: DSN,
release:
process.env.NEXT_PUBLIC_RELEASE ||
process.env.NEXT_PUBLIC_COMMIT_SHA ||
"dev",
// Always-on session replay: the rrweb recorder starts synchronously
// at SDK init so first-frame errors (React hydration #418, etc.) get
// a viewable replay. Sessions not linked to an error are pruned at
// 3 days; error-linked sessions follow the tier's retention window.
tracesSampleRate: 0,
replaysSessionSampleRate: 1.0,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.replayIntegration({
// "Balanced" — change in Settings → Replays → Privacy level.
maskAllText: false,
maskAllInputs: true,
blockAllMedia: true,
}),
axeIntegration({
runOn: ["development", "staging", "production"],
productionSampleRate: 0.05, // 5% of prod page loads
wcagLevel: "AA",
minImpact: "moderate",
}),
networkProbeIntegration({
verifyResourceErrors: [/imagedelivery\.net/i],
}),
],
});
fetch(`https://glitchreplay.com/api/${PROJECT_ID}/config?sentry_key=${PUBLIC_KEY}`, {
cache: "no-store",
})
.then((r) => (r.ok ? r.json() : null))
.then((cfg) => {
const replay = Sentry.getReplay();
if (!replay) return;
if (!cfg?.replay?.enabled) {
replay.stop();
return;
}
const sessionRate = Number(cfg.replay.sessionSampleRate ?? 1);
if (sessionRate < 1 && Math.random() >= sessionRate) replay.stop();
})
.catch(() => {});5. Mount the error boundary
The window.onerror path catches uncaught errors but loses the React component stack. Wrap your tree in Sentry.ErrorBoundary so render-time exceptions arrive with their stack intact:
// app/layout.tsx
import * as Sentry from "@sentry/react";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Sentry.ErrorBoundary fallback={<p>Something went wrong.</p>}>
{children}
</Sentry.ErrorBoundary>
</body>
</html>
);
}6. Trigger a test event
Run your dev server. In the browser console, run:
throw new Error("glitchreplay wiring test");Within a few seconds the event appears on your project's Issues page, grouped by fingerprint. Delete the test issue from the issue detail view once you've confirmed.
If you don't see it: check the browser console for a "Transport disabled" warning (DSN path isn't /0) or a 4xx in the network tab from glitchreplay.com/api/.../envelope/.
7. (Optional) Upload source maps
Without source maps, every stack frame shows the minified bundle (e.g. lt at index-DLrL68bZ.js:1:10383). Wire the upload script into your build to get original file paths back. See Source maps. We deliberately recommend a small scripts/upload-sourcemaps.mjs over Sentry's Webpack plugin auto-uploader — the plugin conflicts with @cloudflare/next-on-pages.
What about Next 14, Vite, plain JS?
- Next 14 — no
instrumentation-client.tshook (it landed in 15.3). Move the sameSentry.initbody into aSentryInit.tsxclient component called fromuseEffect; mount it in the root layout. - Vite SPA — call
Sentry.initat the top ofsrc/main.tsxbeforeReactDOM.createRoot().render(). - Plain JavaScript — same packages,
.jsfile extensions, drop the TypeScript annotations. - Astro / static HTML — load
@sentry/browserfrom a CDN and inline the init in a<script>tag.
The walkthrough at Wire GlitchReplay into your app in ten minutes covers each of these in more detail.
What's next
- Replay — full session DOM playback with rrweb-player: Session replay.
- Network probe — ad-blocker-aware resource error capture: Network probe integration.
- Alerts — get pinged on new issues, spikes, or new releases: Alerts & notifications.
- PII rules — strip emails, headers, or custom fields server-side before storage: PII scrubbing.
- API access — pull issues into your own dashboards or CI: REST API.