Quickstart
Get Wherd running in your app in ~5 minutes.
1. Get a public key
Sign in to the Wherd dashboard → create a project → Settings → API keys →
copy the pk_… key. That's the only credential the SDK needs.
2. Install
React (web)
pnpm add @wherdkit/reactExpo
pnpm dlx expo install @wherdkit/react-native @react-native-async-storage/async-storage
pnpm dlx expo install expo-sensors # optional — enables shake-to-open
pnpm dlx expo install @lodev09/react-native-true-sheet # optional — native bottom-sheet
pnpm dlx expo install react-native-sse # optional — live updates (SSE)Bare React Native (no Expo)
pnpm add @wherdkit/react-native @react-native-async-storage/async-storage
cd ios && pod install && cd .. # iOS native deps for AsyncStorageThe SDK is Expo-agnostic — it works in plain React Native with just AsyncStorage. Two peers are optional:
expo-sensorspowers shake-to-open; without it, shake is a no-op and the FAB / programmatic triggers work exactly the same.@lodev09/react-native-true-sheetpresents the panel as a native bottom-sheet (correct safe-area insets + keyboard handling, no Android clipping). Without it, the panel falls back to a React Native<Modal>.react-native-sseenables live updates (Server-Sent Events). Without it, the SDK stays pull-only — data still refreshes when the panel opens and when the app returns to the foreground. (Web uses the built-inEventSource, so no extra install is needed there.)
3. Mount the provider + widget
import { WherdProvider, MessagesWidget } from "@wherdkit/react"; // or @wherdkit/react-native
<WherdProvider publicKey="pk_…">
<App />
<MessagesWidget />
</WherdProvider>
A floating launcher appears. Open it → send a message → it shows up in your dashboard inbox, where you can reply. Done.
4. Identify your users (optional)
Anonymous works out of the box (threads are tied to the device). To make replies follow a user across devices and reinstalls, attach identity + traits:
<WherdProvider
publicKey="pk_…"
user={{ id: "user_123", email: "[email protected]", name: "Ada", traits: { plan: "pro" } }}
>
Once you identify a user at all — passing the user prop (any field; the id
is enough) or calling identify() — the composer hides its "Email (optional)"
field automatically, since replies route through that identity. The field only
shows for anonymous users. Use <MessagesWidget collectEmail> to force it on,
or collectEmail={false} to always hide it.
Verified identity (recommended for production)
To prove a user is who they claim (so nobody can spoof another user's id),
compute an HMAC on your server with your project secret key and pass it
as userHash:
import { createHmac } from "node:crypto";
const userHash = createHmac("sha256", process.env.WHERD_SECRET_KEY)
.update(user.id)
.digest("hex");
// send userHash to the client, then:
// user={{ id: user.id, userHash }}
5. Show "What's New" anywhere
import { useWherd, useUnreadChangelog } from "@wherdkit/react";
function WhatsNewButton() {
const wherd = useWherd();
const unread = useUnreadChangelog();
return <button onClick={() => wherd.open("changelog")}>What's new {unread ? `(${unread})` : ""}</button>;
}
6. Toggle features remotely
Create a flag in the dashboard (Flags → Create flag), then read it anywhere under the provider:
import { useFlag } from "@wherdkit/react";
function Checkout() {
const newFlow = useFlag("new_checkout_flow"); // false until loaded or if off
return newFlow ? <NewCheckout /> : <ClassicCheckout />;
}
Flipping the toggle in the dashboard pushes to connected apps live — no deploy, no restart.
Next: Customization · API reference