# In-app chat

People write to you from inside your app. You answer from Apparent, on the web or on your phone, and they see the answer right there. It's in every plan.

Expo and React Native apps today (`apparent-expo` 0.3.1 or newer).

## Add the screen

The chat is one ready-made screen. It looks the same in every app; you pick the colour, the font and how round the corners are.

```tsx
// app/help.tsx (expo-router), or any screen in your navigation
import { ApparentChatScreen } from "apparent-expo/chat-screen";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { router } from "expo-router";

export default function Help() {
  const insets = useSafeAreaInsets();
  return (
    <ApparentChatScreen
      theme={{ accent: "#0F7B5F", font: "Inter" }}
      onClose={() => router.back()}
      topInset={insets.top}
      bottomInset={insets.bottom}
    />
  );
}
```

Then open it from your settings or help button. Call `Apparent.identify(userId)` at sign-in, as you already do: each account gets its own chat.

## Change the look

| `theme` | What it does |
|---|---|
| `accent` | Your app's main colour: their messages and the send button. Text on it is dark or white, whichever reads better. |
| `font`, `fontBold` | Your app's font family. |
| `radius` | Corner roundness, 0 to 24 (default 18). |
| `dark` | Force dark or light. By default it follows the phone. |
| `background` | Only if your screens aren't plain white or near black. |

Nothing else changes, on purpose: the chat works the same everywhere, at any text size and in right-to-left languages.

## Your words, your language

Every word can be replaced with `words`. Anything you leave out stays English.

```tsx
<ApparentChatScreen words={{ title: "Hilfe", placeholder: "Nachricht schreiben", emptyTitle: "Frag uns alles" }} />
```

## Photos

Pass `pickImage` and a photo button shows. With expo-image-picker:

```tsx
import * as ImagePicker from "expo-image-picker";

const pickImage = async () => {
  const r = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ["images"], base64: true, quality: 0.6 });
  const a = r.canceled ? null : r.assets[0];
  return a?.base64 ? { base64: a.base64, uri: a.uri } : null;
};

<ApparentChatScreen pickImage={pickImage} />
```

## A badge for new answers

```tsx
import { useChatUnread } from "apparent-expo/chat-screen";

const unread = useChatUnread(); // answers they haven't seen yet; 0 when they never wrote
```

## Answering

Every message comes to **Chats** in Apparent: on the web (the chat button at the top, or apparent.fyi/chats) and in the phone app, with a push. You see who wrote, their phone and app version, and what they did in the app right before writing. Answer there; they see it the next time the chat is open.

AI answers are coming next.

## Your own chat screen

Prefer to draw it yourself? The same chat is there without a screen:

```ts
const off = Apparent.chat.subscribe((messages) => setMessages(messages)); // checks every few seconds while open
await Apparent.chat.send("Is there a dark mode?");                         // or send(text, { base64 })
Apparent.chat.markRead();                                                  // the answers were shown
const n = await Apparent.chat.unread();                                    // for a badge
await Apparent.chat.forget();                                              // the account was deleted
```

## Privacy

Only the phone that wrote can read its chat: the SDK keeps a random chat key on the phone, and the app's key alone reads nothing. When someone deletes their account, call `Apparent.chat.forget()` and the chat is gone. Messages are kept with your other Apparent data and count toward your plan's chat messages a month.
