Widget

Configuration

Every initInstaFix option, with its real default and behavior.

All options of initInstaFix(config). Only projectName plus one of endpoint / store are required.

Connection

InstaFixConfig is a discriminated union over the two transport modes — endpoint or store, never both, never neither. TypeScript rejects the invalid combinations at compile time instead of leaving you to discover them at runtime:

initInstaFix({ endpoint: "/api/instafix", store, projectName: "x" }); // ✗ both modes
initInstaFix({ store, apiKey: "sk-…", projectName: "x" });           // ✗ HTTP-only option in store mode
initInstaFix({ projectName: "x" });                                   // ✗ no transport
OptionTypeDefaultWhat it does
endpointstringHTTP mode. URL of your InstaFix API (e.g. /api/instafix)
storeInstaFixStoreStore mode. Write to a store in the browser instead of HTTP — excludes endpoint, apiKey and headers
projectNamestringRequired in both modes. Scopes everything the widget reads and writes
apiKeystringHTTP mode only. Sent as Authorization: Bearer <key> on every request
headersobject or functionHTTP mode only. Extra headers, static or computed per request (sync or async). Merged last, so an explicit Authorization here beats apiKey

The two halves are exported as InstaFixHttpConfig and InstaFixStoreConfig, which is what you want when a wrapper component takes the config as a prop and only supports one mode:

import type { InstaFixHttpConfig } from "@instafix/widget";

function mountFeedback(config: InstaFixHttpConfig) { /* endpoint guaranteed */ }

apiKey ships in your client bundle — every visitor can read it. Use it for internal tools already behind a login; on public sites prefer headers with a function that returns a short-lived token.

Visibility

OptionTypeDefaultWhat it does
forceShowbooleanfalseBypasses the production and viewport guards (never the SSR guard)
minViewportWidthnumber768Below this width the widget skips with onSkip("mobile"). Use 0 to allow any width
position"bottom-right" | "bottom-left""bottom-right"Corner for the floating button
showAnnotationsTogglebooleantrueSet false to remove the marker-visibility toggle from the action toolbar

Appearance

OptionTypeDefaultWhat it does
accentColorstring"#0066ff"Hex only (#RGB, #RRGGBB, #RRGGBBAA). Named colors, rgb(), hsl() etc. log a warning and fall back to the default
theme"light" | "dark" | "auto""light"auto reads the system preference once at init — an OS theme change mid-session doesn't re-theme the widget
localestring"ko"Any BCP-47 tag; see Languages

Features

OptionTypeDefaultWhat it does
enableScreenshotbooleanfalseCapture a JPEG of the annotated area on submit — see Screenshots
captureDiagnosticsboolean or objectfalseAttach recent console entries (max 50) and network requests (max 20) to each feedback. true enables both; an object picks channels and limits
deepLinkboolean or { param?: string }falseOn first load, focus the feedback referenced by ?instafix=<id> (or your custom param). Initial load only — for route changes, call focusFeedback()
identity{ name, email }Pre-fill the author (SSO apps): skips the identity modal entirely, never persisted to localStorage

Page scoping

OptionTypeDefaultWhat it does
scopeAnnotationsByUrlbooleantrueOnly show markers created on the current page. Filtered both server-side and client-side, so annotations can't leak across pages
getPageScope() => { url, urlPattern }pathnameCustomize what "the current page" means — return a stable url (and optionally a template like /products/:id as urlPattern) so dynamic routes share their feedback
watchNavigationbooleantrueRe-fetch feedbacks on SPA navigation (History API patch + popstate/hashchange). Data only — it never scrolls or refocuses. Set false and call refresh() yourself to opt out

The default page scope is window.location.pathname — by construction it contains no query string, so tokens or search params in the URL never reach the server. If you provide getPageScope, keep that property: return a path or a template, not location.href.

Callbacks

OptionSignatureFires when
onFeedbackSent(feedback) => voidA feedback was successfully created
onError(error) => voidA submission or fetch failed — see error handling
onOpen / onClose() => voidThe panel opened / closed
onAnnotationStart / onAnnotationEnd() => voidAn annotation session began / ended — pause chat bubbles or analytics overlays here
onSkip(reason) => voidThe widget decided not to render: "ssr", "production", or "mobile". Invalid config logs a console.error instead

Debug

OptionTypeDefaultWhat it does
debugbooleanfalseVerbose [instafix] lifecycle logging via console.debug
Edit on GitHub

On this page