API reference
@fixback/expo reference
@fixback/expo. For a narrative walkthrough, see the Expo & React Native guide.Exports
import { FixbackProvider, useFixback, Fixback } from "@fixback/expo";// in a component:const { present, trackScreen } = useFixback();// or module-level, anywhere:Fixback.present();| Export | Description |
|---|---|
<FixbackProvider options={…}> | Wrap your app once. Takes the options below. |
useFixback() | Hook returning status, canSubmit(), present(), trackScreen(name), and signIn() / signOut() / identity() / onIdentity(fn). |
Fixback | Module-level object: the same members as the hook (status reads live from the mounted provider) — call from anywhere. |
Provider options
| Option | Default | What it does |
|---|---|---|
key | — | The Project's publishable key (required). |
origin | — | Optional. The origin sent on every request. A native app sends no Origin header and ingest demands none, so omit it unless you want mobile reports to carry an origin — then allowlist the same value on the Project. |
apiUrl | https://api.fixback.dev | Self-hosted Fixback API base. |
enabled | true | Master switch — false arms nothing and captures nothing. |
release | — | The build identifier stamped on every capture and shown on the Issue. Not yet symbolicated on this platform — a React Native bundle map is not discovered by the uploader, and Hermes frames need handling the symbolicator does not do yet. Web and Node are unaffected. |
environment | — | The deploy environment (production, staging, …) stamped on every report. |
returnUrl | — | Where a Connect returns — a custom scheme (myapp://fixback-connect) or a universal link your app handles. Its origin must be on the Project's allowed origins (add it under App link); a development build's exp:// URL is a separate origin and needs its own entry. It is also how a claimed invite reaches the app: with it set, the SDK redeems the code off the link your app was opened with. Without it, signIn is a no-op and inbound links are ignored. |
hostIdentity | — | A server-minted Host identity JWT — tier the user from your own backend without Connect. |
anonymousId | a persisted per-install id | A stable id for an anonymous reporter, if you would rather supply your own. |
capture | server config | { console?, network?, replay? } per-stream toggles. Console and network arm when the provider mounts, before the boot answer lands, so startup logging is in the trace; a stream the Project turns off is then uninstrumented and what it recorded is dropped. replay is the exception — it is off unless you set it (see below). |
autoCapture | true | Automatic uncaught-error reports. |
screenshots | true | Capture a screenshot when the composer opens. |
replay | off | Session-replay tuning — { fps?, maxEdge?, frameQuality? }. Passing it also turns replay on; see below. |
beforeSend | — | Reshape or drop (null) any report before transport. |
scrub | true | The built-in URL / PII scrubbers. |
beforeBreadcrumb | — | Filter / edit trace entries at the source. |
shake | on | The shake gesture — see below. |
shake options
Passed as shake: { … }. Set enabled: false to turn the gesture off entirely.
| Key | What it does |
|---|---|
enabled | Turn the shake gesture on or off. |
thresholdG | The acceleration (in g) that counts as a shake peak. |
minPeaks | How many peaks make a deliberate shake. |
windowMs | The window the peaks must fall within. |
minGapMs | Minimum gap between counted peaks. |
cooldownMs | How long to wait before another shake can fire. |
sampleIntervalMs | Accelerometer sampling interval. |
useFixback()
| Member | Description |
|---|---|
status | The live lifecycle state — idle, starting, ready, disabled. ready only once boot said a submission would be accepted. |
canSubmit() | Whether a submission would be accepted right now — the server's answer, so a gated Project needs no Gate logic in app code. |
present() | Open the feedback composer programmatically. |
trackScreen(name) | Record a navigation crumb; the active screen names the report's URL. |
signIn() | Start a Connect — open the platform's connect page in an in-app auth session and bind the Account. Resolves to the resulting identity. |
signOut() | Clear the Reporter session — revoke it and forget the token. |
identity() | The current identity — anonymous, or a connected Account with its tier. |
onIdentity(fn) | Subscribe to identity changes (boot, sign in, sign out); returns an unsubscribe. What keeps a settings row current, since signing in does not always change status. |
Connect — reporting as an account
A Reporter is a Fixback Account. The composer's identity row shows “Anonymous · Sign in”; tapping it opens Fixback's connect page in an in-app auth
session (Google, GitHub, Sign in with Apple, magic link) and returns through the returnUrl you declare in
the provider options. The SDK stores the resulting Reporter session in Expo
SecureStore and the composer then shows the Account and tier. A Member of the owning Org reports at
the internal tier. On an Invited- or Internal-gated Project the shake gesture stays
disarmed until a Connect makes the Account eligible — enter it with Fixback.signIn() from your own UI.
A Connect can also start outside the app. Someone invited to the Project claims
the invite in their email, on Fixback's claim page, and is sent back through the same returnUrl carrying a one-time code. The SDK reads that code off the link the app was
opened with — or one delivered while it is running — and signs them in as they arrive, so an
invited tester needs no separate signIn(). It only ever acts on links whose origin
matches your returnUrl, and redeems a given code once.
// Connect the signed-in Account (e.g. from a settings row):await Fixback.signIn(); // opens the platform's connect page in an auth sessionFixback.identity(); // { status: "anonymous" } | { status: "connected", name, email, tier }Fixback.canSubmit(); // whether reporting is live for this Reporter, per bootawait Fixback.signOut(); // revokes the session and clears SecureStoreSession replay
Mobile replay is a buffered window of your app's screen — 30–60 seconds at one frame a
second — encoded into a single H.264/MP4 when a report is sent, and played back in the Issue's Replay tab beside the merged console / network timeline. The encoder ships
with the SDK as @fixback/expo-replay-encoder; you never install or call it
yourself.
Two things are required, and both are deliberate:
- You opt in, in code. Pass
capture: { replay: true }, or simply areplaytuning object. The recording is not masked — it is the screen as your app drew it — so updating the SDK never starts one. - The Project enables replay in its capture settings. That toggle is the kill switch: with it off, nothing is recorded whatever your code asks for.
It also needs a development build. The encoder is native code, which Expo Go
cannot load: run npx expo prebuild and build with EAS or locally. In Expo Go the
SDK logs why and reports without replay — nothing breaks.
<FixbackProvider options={{ key: "pk_…", // Opt in — and enable replay for the Project in its capture settings. capture: { replay: true }, // Optional tuning; passing this object is itself an opt-in. replay: { fps: 1, maxEdge: 960 }, }}> <App /></FixbackProvider>| Key | Default | What it does |
|---|---|---|
fps | 1 | Frames per second. Each step up multiplies both the per-second cost on the JS thread and the payload. |
maxEdge | 960 | Longest edge of the encoded video in pixels. A smaller window is never scaled up. |
frameQuality | 0.6 | JPEG quality of each captured frame, 0–1. The frames are an intermediate the encoder discards, so this trades capture cost against detail surviving into the video. |