Skip to content
You are reading the docs for Backstory 0.2 (private beta). Behavior may change before general availability; the changelog lists every change.

Framework wrappers

All wrappers are subpath exports of the same package and add no dependencies. Each dedupes route-change tracking against the SDK’s own History API patch, so you never get duplicate navigation events.

import { BackstoryProvider, useBackstory } from "@backstory/browser/react";
export function App() {
return (
<BackstoryProvider config={{ projectKey: import.meta.env.VITE_BACKSTORY_KEY }}>
<Routes />
</BackstoryProvider>
);
}
function Checkout() {
const rw = useBackstory();
return <button onClick={() => rw.track("checkout_started")}>Pay</button>;
}

If you use React Router, call useBackstoryRoute(location.pathname) once in your layout so route patterns are attached to navigation events.

app/layout.tsx
import { BackstoryNext } from "@backstory/browser/next";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html><body>
<BackstoryNext config={{ projectKey: process.env.NEXT_PUBLIC_BACKSTORY_KEY! }} />
{children}
</body></html>
);
}

withBackstory(nextConfig) is a no-op helper that documents where release injection for source maps goes; the SDK reads release from config.

import { createApp } from "vue";
import { BackstoryVue } from "@backstory/browser/vue";
createApp(App).use(BackstoryVue, { projectKey: "pk_live_…" }).mount("#app");

The plugin tracks router.afterEach when a Vue Router instance is present.

import { provideBackstory, trackAngularRouter } from "@backstory/browser/angular";
bootstrapApplication(AppComponent, { providers: [provideBackstory({ projectKey: "pk_live_…" })] });
// in a root component:
trackAngularRouter(this.router.events);
+layout.ts
import { initBackstory, trackSvelteKitPage } from "@backstory/browser/svelte";
import { browser } from "$app/environment";
import { page } from "$app/stores";
if (browser) {
initBackstory({ projectKey: import.meta.env.VITE_BACKSTORY_KEY });
page.subscribe((p) => trackSvelteKitPage(p.url.pathname));
}

Call Backstory.init() once after first paint. The SDK patches history.pushState/replaceState and listens to popstate and hashchange, so most SPA routers need nothing more.