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

@zowieteam/chat-react-native-sdk

v1.6.0

Published

Zowie chat React Native SDK

Readme

@zowieteam/chat-react-native-sdk

Zowie chat as a React Native component. Drop <ZowieChat> into your app, give it your baseUrl and instanceId, and it renders the full Zowie chat experience — messaging, voice, file upload/download, visual aids and CSAT — with configuration and session handling built in.

Features

  • Full feature parity with the Zowie web widget (text + voice, file upload, transcript download, visual aids, CSAT).
  • Automatic configuration fetching and session persistence.
  • Imperative API (send messages, start/end chat, update user attributes) via a ref.
  • Rich event callbacks (messages, lifecycle, unread count, downloads, links).
  • Declares no device permissions on your behalf — you add only what you use.

Requirements

  • React Native 0.78+ with the New Architecture enabled.
  • iOS deployment target 15.6+.
  • Peer dependencies your app must have installed: react, react-native, and react-native-webview (>= 13).

The SDK also pulls in react-native-blob-util (file download) and react-native-keychain (session storage) as autolinked native modules — run pod install after installing.

Installation

npm install @zowieteam/chat-react-native-sdk
# or
yarn add @zowieteam/chat-react-native-sdk
cd ios && pod install

Quick start

import { ZowieChat } from "@zowieteam/chat-react-native-sdk"
import { SafeAreaView } from "react-native-safe-area-context"

export function ChatScreen() {
  return (
    <SafeAreaView style={{ flex: 1 }}>
      <ZowieChat
        baseUrl="https://<slug>.chat.getzowie.com"
        instanceId="<your-instance-id>"
        style={{ flex: 1 }}
      />
    </SafeAreaView>
  )
}

<ZowieChat> fetches its configuration, restores any persisted session, and starts the conversation automatically — baseUrl and instanceId are the only required props.

Props

Required

| Prop | Type | Description | | ------------ | -------- | ------------------------------------------------------------------------------ | | baseUrl | string | Base origin of your Zowie deployment, e.g. https://<slug>.chat.getzowie.com. | | instanceId | string | Zowie chat instance ID. |

Configuration

| Prop | Type | Description | | ------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | style | StyleProp<ViewStyle> | Layout/sizing for the chat. The chat has no intrinsic size — pass { flex: 1 } or an explicit height, otherwise it renders with zero height. | | metadata | Metadata | User attributes. metadata.locale also selects the bot's region. | | externalAccessToken | string | JWT for authenticated (logged-in) sessions; anonymous when omitted. | | context | string | Custom context string passed to the bot. | | resetSession | boolean | Clear any persisted session on init. | | initialConversationMode | 'text' \| 'voice' | Mode the chat opens in (default text). | | referral | string | Referral used for auto-start (default "start"). | | initialUserMessage | string | Initial user message sent with auto-start. |

Branding

| Prop | Type | Description | | ------------------------ | -------------------- | ----------------------------------------------- | | title | string | Header title. | | primaryColor | string | Primary color (applied to both light and dark). | | fontColor | 'white' \| 'black' | Font color (applied to both light and dark). | | logoUrl | string | Logo shown in the chat header. | | voiceExperienceEnabled | boolean | Enable voice conversation mode. | | headerVisible | boolean | Whether the chat header is visible (default false). | | voiceBlobColor | string | Color of the voice visualization. |

Events

| Prop | Signature | Fires when… | | -------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------- | | onLoaded | () => void | The chat finished loading. | | onStartChat | (conversationId: string) => void | A conversation started. | | onEndChat | () => void | The conversation ended. | | onMessageSent | (message: string) => void | The user sent a message. | | onMessageReceived | (payload: unknown) => void | A message was received. | | onSessionExpired | () => void | The session expired. | | onUnreadMessages | (count: number) => void | The unread message count changed. | | onMinimize | () => void | The user tapped the minimize control. | | onLinkPress | (url: string) => boolean | Override link opening — return true if handled. Also receives mailto: and tel:. | | onDownload | (file: ChatDownload) => boolean | Override download handling — return true if handled. See Download handling. | | onAndroidBackPress | () => boolean | Android hardware back — return true to consume. | | onConfigError | (error: unknown) => void | Loading the chat configuration failed. | | on | (eventName: string, params: string) => void | Generic backend event subscription (Decision Engine). |

Link handling

Every link the user taps in the chat goes through onLinkPress(url). Return true if your app handled the link, false (or omit the prop) to let the SDK open it with the OS.

onLinkPress receives every scheme, not just http/https. Links the chat renders as mailto: (email addresses in messages, support contacts) and tel: (phone numbers) are routed through it too. If you return true for those without handling them, nothing happens — the SDK skips its fallback and the mail client or dialer is never opened, with no error. A scheme guard avoids that:

<ZowieChat
  baseUrl="…"
  instanceId="…"
  onLinkPress={(url) => {
    // Let the SDK hand mailto:/tel: to the OS — an in-app browser cannot open them.
    if (!/^https?:/i.test(url)) return false
    openInAppBrowser(url)
    return true
  }}
/>

When you return false, the SDK calls Linking.openURL(url): http/https opens the system browser, mailto: the mail client, tel: the dialer. Failures there are silent, so a device with no app registered for a scheme does nothing visible.

Keyboard handling

The chat keeps itself above the on-screen keyboard on both platforms. It measures where it actually sits on screen and reserves exactly the height the keyboard covers, so you do not have to configure anything. In particular:

  • No AndroidManifest.xml change is required. android:windowSoftInputMode is ignored on Android 15+ for apps targeting SDK 35 or newer — edge-to-edge is enforced and the window no longer resizes — so the SDK does not depend on it.
  • You do not need your own KeyboardAvoidingView. Wrapping the chat in one that resizes its area (behavior="padding" or "height") is harmless, because the chat measures the space it is actually left with, but it is redundant.

Layout requirements

ZowieChat has no intrinsic size; it fills the box you give it.

  • Give it a bounded height — { flex: 1 } or an explicit height.
  • Do not wrap it in KeyboardAvoidingView with behavior="position". That behavior does not stretch its children, so the chat collapses to zero height and renders blank.
  • Do not put it inside a ScrollView. The chat scrolls its own message list, and an unbounded parent height leaves it nothing to fill.

Safe areas on Android

Apps targeting SDK 35 or newer are forced edge-to-edge on Android 15 and above: the window spans the whole screen and your app has to inset its own content. Watch out for SafeAreaView from react-native — it does nothing on Android, it is an iOS-only component. A chat wrapped in it draws under the status bar and under the gesture bar.

Use something that applies insets on both platforms — react-native-safe-area-context (React Navigation already depends on it), react-native-edge-to-edge, or your own handling:

import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context"
;<SafeAreaProvider>
  <SafeAreaView style={{ flex: 1 }}>
    <ZowieChat baseUrl="…" instanceId="…" style={{ flex: 1 }} />
  </SafeAreaView>
</SafeAreaProvider>

Under a navigation header the navigator usually applies the top inset for you, but the bottom is still yours — inset the screen with edges={['bottom']}.

The SDK does not apply insets on your behalf on purpose: it fills the box you give it, which is what lets you place it below a header, in a bottom sheet or in a modal.

Download handling

Transcripts and attachments the user downloads are saved and then opened with the OS. On Android the file goes to the device's shared Downloads folder through MediaStore, so the user can find it in Files or the Downloads app. On iOS it goes to the app's documents directory and is shown with the system document preview.

Files in the Android Downloads folder are visible to other apps and survive uninstalling your app. If that does not fit your privacy or storage requirements, take over with onDownload:

<ZowieChat
  baseUrl="…"
  instanceId="…"
  onDownload={(file) => {
    storeEncrypted(file)
    return true
  }}
/>

Return true when your app handled the download, false to let the SDK save it. To observe downloads without changing what happens to them, do your work and return false.

A download that fails is reported through the SDK's error logging rather than being silently dropped. Failing to open the saved file is not treated as a failure — the file is already saved, and a device may simply have no app for that file type.

Imperative API

Pass a ref to call methods on the chat directly:

import { useRef } from "react"
import {
  ZowieChat,
  type ZowieChatHandle,
} from "@zowieteam/chat-react-native-sdk"

function Example() {
  const chat = useRef<ZowieChatHandle>(null)

  // chat.current?.sendMessage('Hello');

  return <ZowieChat ref={chat} baseUrl="…" instanceId="…" style={{ flex: 1 }} />
}

| Method | Signature | Description | | ------------------- | ------------------------------ | ------------------------------------------------------------------ | | sendMessage | (message: string) => void | Send a message as the user. | | sendReferral | (referralId: string) => void | Send a referral / campaign ID to the conversation. | | updateMetadata | (metadata: Metadata) => void | Update the user attributes. | | setVisible | (visible: boolean) => void | Set whether the chat is visible. | | showCsat | (onCompleted?: () => void) => void | Show the CSAT survey. The optional callback fires when the user submits or dismisses it. | | startChat | () => void | Start a new conversation when none is active (no-op otherwise). | | endChat | () => void | Clear the stored session and current conversation (use on logout). | | getConversationId | () => string \| undefined | The active conversation's ID, or undefined when none is open. | | registerPushToken | (token: string) => void | Register a device token for push notifications. See Push Notifications. | | deregisterPushToken | () => void | Deregister the current push token. See Push Notifications. |

Push Notifications

The SDK can register a device token with the Zowie backend so that push notifications reach the device. Firebase/APNs setup is your app's responsibility — the SDK only forwards the token.

| Method | Signature | Description | | --------------------- | ---------------------------- | ------------------------------------------------------ | | registerPushToken | (token: string) => void | Register an FCM/APNs device token for push notifications. | | deregisterPushToken | () => void | Deregister the current token. Push notifications stop for this device. |

Both methods are on ZowieChatHandle (the imperative ref).

const chat = useRef<ZowieChatHandle>(null)

// When your push library returns a token:
const token = await firebase.messaging().getToken()
chat.current?.registerPushToken(token)

// On logout or when notifications should stop:
chat.current?.deregisterPushToken()

Behavior notes:

  • If the chat session is not yet authenticated, registerPushToken queues the token and flushes it automatically when authentication completes.
  • Multiple calls to registerPushToken with different tokens are safe — the latest token wins.
  • The token is automatically cleared when the chat ends or the session expires.

Types

The exported types referenced by the props and callbacks above:

Metadata

User attributes passed via the metadata prop or updateMetadata. All fields are optional.

| Field | Type | Description | | ------------- | ------------------------ | ---------------------------------------------------- | | firstName | string | User's first name. | | lastName | string | User's last name. | | name | string | Full display name. | | email | string | User's email address. | | phoneNumber | string | User's phone number. | | locale | string | Locale, e.g. en-US. Also selects the bot's region. | | timezone | string | IANA timezone, e.g. Europe/Warsaw. | | extraParams | Record<string, string> | Arbitrary custom attributes sent alongside the rest. |

ChatDownload

Passed to onDownload when a file download is triggered inside the chat. Exactly one of base64 or url is set.

| Field | Type | Description | | ---------- | -------- | -------------------------------------------------------------- | | filename | string | Suggested file name. | | mimeType | string | MIME type, when known. | | base64 | string | Base64 contents, for client-generated files (e.g. transcript). | | url | string | Direct download URL. |

Permissions

The SDK does not declare any device permissions on your behalf — so apps that don't use voice or photo upload aren't forced to request the microphone or camera (which would otherwise show up in store listings and review). If you enable those features, declare the permissions in your own app.

Voice (microphone)

Android — add to your AndroidManifest.xml:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

Both are required for voice. RECORD_AUDIO is a runtime permission and is requested automatically on first use.

iOS — add to your Info.plist (required for microphone access):

<key>NSMicrophoneUsageDescription</key>
<string>The microphone is used for voice conversations in the chat.</string>

Photo upload (camera)

Only needed if users take photos via the in-chat file picker.

iOSInfo.plist:

<key>NSCameraUsageDescription</key>
<string>The camera is used to take and send photos in the chat.</string>

(Choosing existing photos uses the system picker and needs no permission. On Android the system file/camera picker handles its own permissions.)

License

MIT