npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@clariodesk/react-native

v0.1.1

Published

ClarioDesk React Native SDK — in-app customer support chat, bug reporting, and feedback. Headless client plus a prebuilt UI (./ui). Works in bare RN and Expo (dev build + Expo Go).

Downloads

266

Readme

@clariodesk/react-native

In-app support for React Native — embed support conversations in your app with a few method calls, or drop in the prebuilt chat UI. Mirrors the Flutter SDK 1:1: device-is-identity auth (no JWTs/refresh tokens), live updates over Centrifugo/SSE, presence, read receipts, typing, push, attachments, and CSAT.

Two integration modes, one install:

  • Headless (primary) — promise-based methods + live subscriptions/hooks; you render the UI.
  • Prebuilt UI (@clariodesk/react-native/ui) — a themeable drop-in chat you present with one call.

Integrating with an AI agent? (Claude Code, Cursor, Codex) Paste the install prompt and it does this whole README for you — detect, ask, install, verify. Machine-readable docs: llms.txt · rules for AI agents.

Compatibility

Works across the widest surface — no fork crashes; every fork can chat.

| Capability | Bare RN (old + New Arch) | Expo dev build / EAS | Expo Go | |---|---|---|---| | Device key | ✅ Secure Enclave / Keystore | ✅ (via config plugin) | ⚠️ software P-256 fallback | | Secure storage | ✅ react-native-keychain | ✅ expo-secure-store | ✅ expo-secure-store | | Realtime (Centrifugo + SSE) | ✅ | ✅ | ✅ | | Push | ✅ (host Firebase) | ✅ | ⛔ remote push N/A in Go | | Attachments | ✅ | ✅ | ✅ (Expo pickers) | | Prebuilt UI | ✅ | ✅ | ✅ |

The hardware key needs a dev build (Expo Go can't load native modules); the SDK transparently falls back to a software ECDSA P-256 key so you can evaluate the whole flow in Expo Go and ship hardware-backed with no code change. The backend records the attestation (secure_enclave/tee/strongbox/software) either way.

Install

npm install @clariodesk/react-native
# secure RNG — required; import once at app entry (see below)
npm install react-native-get-random-values

Pick the peers for your stack:

# secure storage
npx expo install expo-secure-store        # Expo
npm install react-native-keychain         # bare RN

# attachments (optional — only if you attach files)
npx expo install expo-image-picker expo-document-picker expo-image-manipulator   # Expo
npm install react-native-image-picker @react-native-documents/picker             # bare RN

# connectivity-reactive reconnect (optional)
npm install @react-native-community/netinfo

Expo — add the config plugin, then make a dev build (or run in Expo Go for the software tier):

{ "expo": { "plugins": ["@clariodesk/react-native"] } }
// parameterize: ["@clariodesk/react-native", { "enableCamera": false, "enablePush": true }]
npx expo prebuild && npx expo run:ios

Bare RN — autolinking handles the native module. Run npx install-expo-modules@latest once, then cd ios && pod install.

Headless quick start

// At the very top of index.js — before anything else:
import 'react-native-get-random-values';

import { ClarioDesk } from '@clariodesk/react-native';

// 1. Once at app start. First launch generates the device key + registers; later
//    launches reuse it. Realtime defaults to Centrifugo, falling back to SSE.
await ClarioDesk.init({ apiKey: 'pk_live_…' });

// 2. After your own auth knows the user (metadata only — the device key is the
//    real identity, so this grants no access).
await ClarioDesk.identify({ externalId: user.id, email: user.email });

// 3. Writes are imperative + optimistic.
const { ticket } = await ClarioDesk.createTicket({ subject: '', body: 'Upload is broken' });
await ClarioDesk.sendMessage(ticket.id, 'Still happening on 1.4.2');

// 4. Reads are live. subscribe* returns an unsubscribe function.
const off = ClarioDesk.subscribeMessages(ticket.id, (messages) => render(messages));

// 5. On sign-out / user switch.
await ClarioDesk.reset();

React hooks

Idiomatic state binding (not UI) in a separate entry so the core has no React dep:

import {
  useTickets, useMessages, useTyping, useAgentPresence,
  useConnection, useSync, usePushOpened,
} from '@clariodesk/react-native/hooks';

const { tickets, loading } = useTickets();
const { messages } = useMessages(ticketId);
const supportTyping = useTyping(ticketId);
const agentOnline = useAgentPresence();
const conn = useConnection();           // 'connecting' | 'connected' | 'reconnecting' | 'disconnected' | 'fatal'

A message with pending: true is optimistic ("sending…"); failed: true means the send was rejected — render tap-to-retry: ClarioDesk.retryMessage(m). An offline send stays pending and auto-flushes on reconnect (durable outbox).

Prebuilt UI

import { ClarioDeskProvider, openInbox } from '@clariodesk/react-native/ui';

// Wrap your app once:
<ClarioDeskProvider theme={{ primary: brand.accent, cornerRadius: 18, mode: 'system' }}>
  <App />
</ClarioDeskProvider>;

// Open from anywhere (e.g. a support button):
openInbox();            // also: openTicket(id), openNewConversation(), openBugReport()

It presents its own screens in a self-owned modal (no react-navigation), derives light/dark from your theme, and exposes ~50 overridable strings. To enable the attach button, pass a picker to the provider. Zero native deps beyond the core.

Push

Push is a separate package so Firebase's native code never autolinks into a headless host. The host owns the messaging plugin; the SDK gets tokens through a PushTokenProvider seam.

npm install @clariodesk/react-native-push @react-native-firebase/app @react-native-firebase/messaging
import { FirebaseTokenProvider } from '@clariodesk/react-native-push';
await ClarioDesk.init({ apiKey: 'pk_live_…', pushTokenProvider: new FirebaseTokenProvider() });

In your shared background/foreground handler, route ClarioDesk messages so they don't collide with your app's own:

messaging().setBackgroundMessageHandler(async (msg) => {
  if (ClarioDesk.isClarioMessage(msg.data ?? {})) return; // ours
  /* your app's handling */
});

On a notification tap call ClarioDesk.openTicketFromPush(data) (or the usePushOpened hook) to navigate. Registering the background handler in index.js at startup is the #1 push setup-failure cause — make sure it runs.

Attachments

await ClarioDesk.sendMessage(ticketId, 'see screenshot', {
  attachments: [{ uri, mime: 'image/jpeg', kind: 'image' }],
});

Pass a MediaPicker / ImageNormalizer via init({ attachments: { picker, normalizer } }) (or upload OutgoingAttachments you built yourself). The SDK signs → normalizes images to JPEG → uploads (R2 / Cloudflare Stream) → binds the ids at send, with per-tile progress (attachmentUploadProgress(stubId)). ≤4/msg, 10 MB image / 50 MB video·file.

API surface

init · identify · createTicket · sendMessage · retryMessage · markRead · setTyping · submitCsat · fetchTickets · fetchTicket · reset · isInitialized · isIdentified, the reactive subscribeTickets/Messages/Typing/AgentPresence/ Connection/Sync/State/PushOpened, push (registerPushToken · isClarioMessage · parsePushPayload · openTicketFromPush · get/setNotificationPreferences), and attachments (attachmentUploadProgress · refreshAttachmentUrl). Hooks mirror the subscriptions. All types (Ticket, Message, Attachment, readStateOf, ClarioDeskError, …) are exported.

How auth works

Device-is-identity. On first launch the SDK creates a non-extractable ECDSA P-256 keypair and registers it via challenge-response; every request is signed with that key (X-ClarioDesk-* headers) — no JWTs/refresh tokens. The publishable pk_* key only authorizes device registration; it can't read tickets or impersonate users.

License

MIT