vitrinka.docs

React and web apps

@vitrinka/web mounts the journey recorder inside a React web app — no browser extension — so testers on phones and desktops record sessions straight from a dev or preview build.

Install

bun add @vitrinka/web rrweb

react, react-dom and rrweb are peer dependencies.

Mount it

Wrap your app once and drop the pill where it should float. Nothing is captured until a tester starts a session from the pill.

import { VitrinkaRecorderRoot, VitrinkaRecorderPill } from '@vitrinka/web/recorder';

<VitrinkaRecorderRoot url={process.env.NEXT_PUBLIC_VITRINKA_URL}>
  {children}
  <VitrinkaRecorderPill />
</VitrinkaRecorderRoot>

The recorder mounts only when url is set. Leave it unset in production and the root renders its children and nothing else.

Testers never type a token. Link recorder shows a short code, an Open vitrinka button and — on a desktop — a QR code:

  1. On the same device, tap Open vitrinka; on a desktop, scan the QR with a phone that is signed in to vitrinka.
  2. Approve the code — pick the workspace when you belong to several.
  3. The recorder receives a token that can only create and append to sessions in that workspace. It cannot read boards, tasks or other sessions, expires 30 days after its last use, and is listed and revocable under Settings → tokens.

The same page is reachable from the user menu as Link a device for typing a code by hand.

A linked recorder records only on a page whose host matches one of the workspace's project domain rules — the same rule that picks the session's project. A rule whose environment is production — production, prod, prd or live, any case — refuses it unless that rule opts in: switch on in-app recorder beside the domain under Settings → Projects → Routing, or set "inAppRecorder": true on the rule (the settings PUT replaces the whole domains list, so send every rule back). The browser extension and native apps are not affected, and a recorder key keeps its own origin list.

A refused page gets a 403 that names the rule to change; linking again does not help. Only a 401 — the token was revoked, expired, or belongs to another workspace — asks the tester to link again.

Move it out of the way

The recorder stays small: a 28px dot until someone records, then a dot and a timer that unfold into the controls when you hover, focus or tap them, and fold away again when you leave. Something wrong, such as being offline, always shows a line by itself.

Drag it to any corner or to the top or bottom centre — a quick flick lands where it is thrown. Push it past the left or right edge and it tucks into a thin tab; tap the tab to bring it back. Arrow keys on the focused recorder and Move to in its menu do the same without dragging. It remembers the spot on each site. On a phone, the note and link sheets open from the bottom of the screen, above the keyboard.

Unattended builds

CI and end-to-end suites cannot approve a code. An admin mints a recorder key under Settings → tokens — project-pinned and limited to the exact origins you list (* is refused), which double as the CORS allow-list — and the build sets it as NEXT_PUBLIC_VITRINKA_KEY.

// next.config.js
const { withVitrinkaRecorder } = require('@vitrinka/web/next');
module.exports = withVitrinkaRecorder(nextConfig);

withVitrinkaRecorder refuses a production build that carries a recorder key unless VITRINKA_RECORDER_LANE names an allowed lane (preview or development), so a key never ships to users.

What is captured

  • Replay — an rrweb DOM stream with inputs masked; the replay is the session's keyframe, no screenshots are taken. When the session ends, vitrinka replays the stream in its capture sidecar and renders a still at every click, navigation, note and annotation, so the session board looks like an extension session's. Images and fonts the page loaded from its own server are not fetched for the stills, so they show blank.
  • Clicks — the element's short selector, its rectangle and a redacted text snippet.
  • Navigation — every route change.
  • Console — errors and unhandled rejections.
  • Network — fetch and XMLHttpRequest, with headers, URLs and bodies passed through the same redaction rules as the Expo recorder; the recorder's own uploads are skipped.
  • Notes and annotations — what the tester types and marks, on an element or a dragged region.

The full contract is PROTOCOL.md in the vitrinka-kit repository.

Source-available under the Elastic License 2.0: read, use, modify and redistribute it — you may not offer it to third parties as a managed service.

On this page