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.
autoShow{ announcements?, changelog? }Override auto-show (defaults: announcements on, changelog off).

Components

ComponentDescription
<MessagesWidget fab?>Floating launcher + modal with tabs for enabled modules. fab={{ placement?, offset?: { bottom?, side? }, label? }} positions the launcher.
<MessagesFAB label? placement? offset?>Just the launcher. Icon circle by default; label → pill. placement = "bottom-right" | "bottom-left", offset = { bottom?, side? }.
<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, status, 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.

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.
NextQuickstart