Wherddocs
HomeDashboard
Reference

API reference

Everything below is exported from both @wherdkit/react and @wherdkit/react-native (and from @wherdkit/core for the hooks/types).

<WherdProvider>

PropTypeNotes
publicKeystringRequired. Your pk_… key.
userWherdUserOptional identity. { id, email?, name?, userHash?, traits? }
themeThemeTokensOptional theme override (see Customization).
activation{ fab?, shake? }RN only. Override server activation config.
shakeThresholdnumberRN only. Acceleration (g) required to register a shake. Higher = stronger shake needed. Defaults to 1.8.
autoShow{ announcements?, changelog?, messages? }Override auto-show (defaults: announcements on, changelog & messages off). messages auto-opens the panel to a thread when a new unread admin reply arrives — checked on launch and (RN) on app foreground.

Components

ComponentDescription
<MessagesWidget fab? collectEmail?>Floating launcher + sliding panel with tabs for enabled modules. On React Native the panel renders as a native bottom-sheet when @lodev09/react-native-true-sheet is installed (correct safe-area + keyboard handling), falling back to a <Modal> otherwise. fab={{ placement?, offset?: { bottom?, side? }, label? }} positions the launcher. collectEmail forces the composer's email field on/off; by default it's hidden when the user is already identified (you passed user / called identify) and shown otherwise.
<MessagesFAB label? placement? offset? force?>Just the launcher. Icon circle by default; label → pill. placement = "bottom-right" | "bottom-left", offset = { bottom?, side? }. force renders it regardless of the server activation.fab toggle — an escape hatch for placing the FAB on a specific screen (e.g. Settings) while keeping it off elsewhere.
<FeatureBoard />Feature requests list + create + upvote.
<WhatsNew />Changelog feed; marks entries read on view.

Hooks

Every prebuilt component is built on these hooks, so building a fully custom UI gives you exact parity. All of them must be called inside <WherdProvider>.

useWherd()

The primary hook — reactive widget state plus imperative controls. Use it to open the widget from your own button, read live config, or identify a user.

const wherd = useWherd();
wherd.open("ideas");          // open straight to a tab

Returns:

FieldTypeDescription
readybooleanTrue once the SDK has loaded config + identity.
isOpenbooleanWhether the widget panel is open.
viewWherdViewActive tab: "messages" | "featureRequests" | "changelog".
configWidgetConfig | nullLive server-driven config (theme, enabled modules, copy, activation).
userWherdUser | nullThe identified user, if any.
verifiedbooleanTrue when the user's identity was HMAC-verified.
changelogUnreadnumberUnread changelog count (for badges).
messagesUnreadnumberUnread admin replies across the user's threads.
open(view?)(v?: WherdView) => voidOpen the widget, optionally to a tab.
close()() => voidClose the widget.
setView(view)(v: WherdView) => voidSwitch tab without opening/closing.
identify(user)(u: WherdUser) => Promise<void>Attach identity + traits at runtime.
start({ body, metadata? })=> Promise<SubmitResult>Start a new message thread imperatively.

useComposer()

Drop-in state for starting a new message thread — wire it to an input + button.

const { body, setBody, submit, submitting, submitted, error } = useComposer();
FieldTypeDescription
bodystringCurrent draft text.
setBody(v)(v: string) => voidUpdate the draft.
type / setType(t)MessageTypeCategory chip: "idea" | "issue" | "other".
email / setEmail(v)stringOptional contact email.
submit()() => Promise<SubmitResult>Send it. Validates non-empty first.
submittingbooleanIn-flight flag for disabling the button.
submittedbooleanTrue after a successful send (show a thank-you).
queuedbooleanTrue when saved offline; auto-retries later.
errorstring | nullValidation / network error message.
reset()() => voidClear draft + submitted/error state.

submit() resolves to SubmitResult = { ok: boolean; queued: boolean; id?: string; error?: string }.

useMessages()

The user's own message threads, with replies and unread counts. Powers the Messages tab; build a custom inbox/conversation UI on it.

const { threads, unreadTotal, loading, reply, markRead } = useMessages();
FieldTypeDescription
threadsMessageThread[]{ id, body, createdAt, unread, replies: MessageReply[] }, newest first.
unreadTotalnumberUnread admin replies across all threads.
loadingbooleanInitial fetch flag.
refresh()() => Promise<void>Re-fetch threads.
reply(id, body)(id, body) => Promise<boolean>Add the user's reply to a thread.
markRead(id)(id) => Promise<void>Mark a thread's admin replies read.

useUnreadMessages()

const unread = useUnreadMessages(); // number — reactive

useAnnouncements()

Active, non-dismissed announcement banners.

const { announcements, dismiss } = useAnnouncements();
// announcements: Announcement[] = { id, title, body, severity, publishedAt }
dismiss(id);

useFeatureRequests()

Read, vote on, and create roadmap ideas. Voting is optimistic — the UI updates instantly and reconciles with the server's authoritative count.

const { requests, loading, vote, create } = useFeatureRequests();
// requests: FeatureRequest[] sorted by votes
vote(id, true);                 // upvote
vote(id, false);                // remove vote
create({ title: "Dark mode" }); // suggest a new idea
FieldTypeDescription
requestsFeatureRequest[]{ id, title, body, status, voteCount, hasVoted, createdAt }, vote-sorted.
loadingbooleanInitial fetch flag.
refresh()() => Promise<void>Re-fetch the list.
vote(id, next)(id: string, next: boolean) => Promise<void>Toggle the caller's vote.
create(input)({ title, body? }) => Promise<FeatureRequest | null>Suggest a new idea.

useChangelog()

Render release notes anywhere and track read state.

const { entries, loading, markAllRead } = useChangelog();
// entries: ChangelogEntry[] = { id, title, body, publishedAt, read }
FieldTypeDescription
entriesChangelogEntry[]Published entries, newest first, each with a read flag.
loadingbooleanInitial fetch flag.
refresh()() => Promise<void>Re-fetch entries + unread count.
markRead(id)(id: string) => Promise<void>Mark one entry read.
markAllRead()() => Promise<void>Mark every entry read (clears the badge).

useUnreadChangelog()

const unread = useUnreadChangelog(); // number — reactive

A cheap, reactive unread count — perfect for a nav bell/badge without mounting the whole changelog.

useFlag(key, defaultValue?)

const enabled = useFlag("new_checkout_flow");        // boolean — reactive
const enabled = useFlag("new_checkout_flow", true);  // custom fallback

Reads a boolean feature flag by key (create flags in the dashboard under Flags). Fails closed: returns defaultValue (default false) until flags have loaded or when the key doesn't exist. Flags refresh on launch, on app foreground (RN), and live over SSE when you toggle them in the dashboard — so a flip reaches running apps in seconds without a deploy.

useResolvedTheme(systemColorScheme?)

const theme = useResolvedTheme("dark");
// theme.colors.primary, theme.radius, theme.fontFamily, theme.colorScheme

Returns concrete ResolvedTheme tokens after merging defaults ← server config ← theme prop. Use it so your custom UI matches the active widget theme. Pass the platform's current scheme ("light"/"dark") for "system" mode.

Types

WherdUser, WherdView ("messages" | "featureRequests" | "changelog"), MessageType, MessageThread, MessageReply, Announcement, ThemeTokens, ResolvedTheme, WidgetConfig, FeatureRequest, ChangelogEntry — all exported.

Behavior notes

  • Anonymous by default — a persisted anonymousId is generated; calling identify() promotes that record in place.
  • Offline queue — messages submitted while offline are persisted and retried automatically on the next app launch.
  • Server-driven config — theme, modules, copy, and activation are fetched from your dashboard settings at startup, so you can change them without shipping an app update.
  • Live flags — feature-flag toggles push to connected clients over the same SSE stream as messages and announcements; offline clients keep their last-known values and catch up on the next launch or foreground.
NextQuickstart