Data sources
Endpoint, store, or fully custom — how the inbox talks to your data.
The inbox reads and writes through a small abstraction with three ways to supply it. Pick exactly one — source, store, or endpoint. They're mutually exclusive in the type, so there's no precedence to remember and no way to pass two and wonder which one won.
Endpoint mode (production default)
<InstaFixInbox projects="my-project" endpoint="/api/instafix" apiKey={KEY} />Talks to your adapter endpoint: GET for lists, PATCH for statuses, DELETE for removals, always with cache: "no-store". Errors arrive typed by code (AUTH for 401/403, VALIDATION for other 4xx, SERVER for 5xx, NETWORK for fetch failures). There are deliberately no retries — a triage UI should tell you immediately.
Store mode
<InstaFixInbox projects="my-demo" store={new LocalStorageStore()} />Runs against any InstaFixStore in-process — the same stores the widget's client-side mode uses. Demos and prototypes never need a server.
Custom source
For tRPC, GraphQL, or server actions, implement the three-method InboxSource contract and pass it as source:
import type { InboxSource } from "@instafix/dashboard";
const source: InboxSource = {
async list(query) {
// query: projectName, page, limit, status?, type?, search?, url?, urlPattern?
const { feedbacks, total } = await trpc.instafix.list.query(query);
// Important: createdAt / updatedAt / resolvedAt must be real Date objects
return { feedbacks: feedbacks.map(reviveDates), total };
},
async setStatus(id, projectName, status) {
return reviveDates(await trpc.instafix.setStatus.mutate({ id, projectName, status }));
},
async remove(id, projectName) {
await trpc.instafix.remove.mutate({ id, projectName });
},
};The two building blocks behind the built-in modes are exported too — createEndpointSource({ endpoint, apiKey, headers }) and createStoreSource(store) — so you can wrap, compose, or decorate them (e.g. add logging around the HTTP client) instead of starting from scratch.
Types without extra dependencies
@instafix/dashboard re-exports everything you need to type a wrapper around it, so you never install another package:
| What you're typing | Exports |
|---|---|
| Feedback data | FeedbackRecord, FeedbackStatus, FeedbackType, InstaFixStore, plus the FEEDBACK_STATUSES / FEEDBACK_TYPES constants and isClosedStatus() |
| Hook options | UseInstaFixInboxOptions and its three members — InboxEndpointOptions, InboxStoreOptions, InboxCustomSourceOptions — plus the shared InboxSharedOptions |
| Hook result | InboxState, InboxStatusFilter, InboxTypeFilter |
| Sources | InboxSource, EndpointSourceOptions (the argument of createEndpointSource) |
| Component props | InstaFixInboxProps, or InstaFixInboxPresentationProps for the presentation half alone |
| Theming | InboxTheme ("light" | "dark" | "auto") and ResolvedTheme ("light" | "dark" — what auto resolves to) |