> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-platform-docs-release.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins

> The plugin system controls how messages are rendered, what options appear in context menus, and what preview text shows in conversations.

## What is a Plugin?

A plugin owns one or more message types. It tells the UI Kit:

* **How to render the message** as a bubble in the message list
* **What context menu options** to show when a user hovers/long-presses a message
* **What preview text** to display in the Conversations list subtitle

Every message that appears in the UI is rendered by a plugin. If no plugin matches a message type, the message is not displayed.

***

## Where Plugins Are Used

| Location               | Plugin Method                                    | What it does                                                   |
| ---------------------- | ------------------------------------------------ | -------------------------------------------------------------- |
| **Message List**       | `renderBubble()`                                 | Renders the bubble content (text, image grid, poll, etc.)      |
| **Message List**       | `getOptions()`                                   | Provides context menu items (reply, edit, delete, copy, react) |
| **Conversations List** | `getLastMessagePreview()`                        | Returns subtitle text ("📷 Photo", "You: Hello", "🎥 Video")   |
| **Message Bubble**     | `renderHeaderView()`, `renderFooterView()`, etc. | Customizes bubble regions beyond content                       |

***

## Default Plugins

These plugins are included automatically — no configuration needed:

| Plugin                                                                        | Message Type                     | What it renders                               |
| ----------------------------------------------------------------------------- | -------------------------------- | --------------------------------------------- |
| [Text](/ui-kit/react/v7/plugins/text)                                         | `text`                           | Formatted text with mentions, URLs, markdown  |
| [Image](/ui-kit/react/v7/plugins/image)                                       | `image`                          | Image grid with captions, click-to-fullscreen |
| [Video](/ui-kit/react/v7/plugins/video)                                       | `video`                          | Video player with thumbnail                   |
| [File](/ui-kit/react/v7/plugins/file)                                         | `file`                           | File card with download button                |
| [Audio](/ui-kit/react/v7/plugins/audio)                                       | `audio`                          | Waveform audio player                         |
| [Polls](/ui-kit/react/v7/plugins/polls)                                       | `extension_poll`                 | Poll creation + voting bubble                 |
| [Stickers](/ui-kit/react/v7/plugins/stickers)                                 | `extension_sticker`              | Sticker image bubble                          |
| [Collaborative Document](/ui-kit/react/v7/plugins/collaborative-document)     | `extension_document`             | Document collaboration link                   |
| [Collaborative Whiteboard](/ui-kit/react/v7/plugins/collaborative-whiteboard) | `extension_whiteboard`           | Whiteboard collaboration link                 |
| [Group Action](/ui-kit/react/v7/plugins/group-action)                         | `groupMember`                    | "User joined", "User left" system messages    |
| [Call Action](/ui-kit/react/v7/plugins/call-action)                           | `audio`, `video` (call category) | "Missed call", "Call ended" system messages   |
| [Delete](/ui-kit/react/v7/plugins/delete)                                     | Any (deleted)                    | "This message was deleted" placeholder        |

***

## How Plugin Resolution Works

When the UI Kit needs to render a message, it asks the **Plugin Registry** to find the right plugin:

1. If the message is deleted (`getDeletedAt() !== null`), the Delete plugin handles it
2. Otherwise, the registry finds the first plugin whose `messageTypes` includes the message's type AND whose `messageCategories` includes the message's category
3. First match wins — plugin order matters

```
Message { type: "image", category: "message" }
  → Registry scans plugins in order
  → CometChatImagePlugin matches (messageTypes: ["image"], messageCategories: ["message"])
  → ImagePlugin.renderBubble() is called
```

***

## Adding Plugins

Default plugins are always included. To add extra plugins (like AI), pass them via the `plugins` prop on `CometChatProvider`:

```tsx theme={null}
import { CometChatProvider } from "@cometchat/chat-uikit-react";
import { CometChatAIPlugin } from "@cometchat/chat-uikit-react/plugins/ai";

function App() {
  return (
    <CometChatProvider
      appId="YOUR_APP_ID"
      region="us"
      authKey="YOUR_AUTH_KEY"
      uid="cometchat-uid-1"
      plugins={[CometChatAIPlugin]}
    >
      <MyChatApp />
    </CometChatProvider>
  );
}
```

Your custom plugins are appended after the defaults. Since first match wins, default plugins take priority for their message types. To override a default plugin, you'd need to use the manual approach with a custom plugin array.

***

## Creating a Custom Plugin

Implement the `CometChatMessagePlugin` interface. Here's a minimal "location" message plugin:

```tsx theme={null}
import React from "react";
import type { CometChat } from "@cometchat/chat-sdk-javascript";
import type {
  CometChatMessagePlugin,
  CometChatMessagePluginContext,
  CometChatMessageOption,
} from "@cometchat/chat-uikit-react";

export const LocationPlugin: CometChatMessagePlugin = {
  id: "location",
  messageTypes: ["location"],
  messageCategories: ["custom"],

  renderBubble(message: CometChat.BaseMessage, context: CometChatMessagePluginContext) {
    const customMessage = message as CometChat.CustomMessage;
    const data = customMessage.getData() as { customData?: { latitude: number; longitude: number } };
    const { latitude, longitude } = data.customData ?? { latitude: 0, longitude: 0 };

    return React.createElement("div", { className: "location-bubble" },
      React.createElement("img", {
        src: `https://maps.googleapis.com/maps/api/staticmap?center=${latitude},${longitude}&zoom=15&size=300x200&key=YOUR_KEY`,
        alt: "Location",
        style: { borderRadius: 8, width: "100%" },
      }),
      React.createElement("p", { style: { margin: "8px 0 0", fontSize: 12 } },
        `${latitude.toFixed(4)}, ${longitude.toFixed(4)}`
      )
    );
  },

  getOptions(message: CometChat.BaseMessage, context: CometChatMessagePluginContext): CometChatMessageOption[] {
    // Minimal options — just delete for sender
    return [
      {
        id: "delete",
        title: context.getLocalizedString?.("delete") ?? "Delete",
        senderOnly: true,
        onClick: (msg) => context.onDeleteMessage?.(msg),
      },
    ];
  },

  getLastMessagePreview(): string {
    return "📍 Location";
  },
};
```

Register it:

```tsx theme={null}
<CometChatProvider
  appId="YOUR_APP_ID"
  region="us"
  authKey="YOUR_AUTH_KEY"
  uid="cometchat-uid-1"
  plugins={[LocationPlugin]}
>
  <MyChatApp />
</CometChatProvider>
```

For a complete tutorial with sending, receiving, and styling, see [Creating a Custom Plugin](/ui-kit/react/v7/plugins/custom-plugin).

***

## Plugin Interface Reference

```typescript theme={null}
interface CometChatMessagePlugin {
  /** Unique plugin identifier. */
  id: string;

  /** SDK message types this plugin handles (e.g., ["text"], ["image"]). */
  messageTypes: string[];

  /** SDK message categories this plugin handles (e.g., ["message"], ["custom"]). */
  messageCategories: string[];

  /** Render the bubble content for a message. */
  renderBubble(message: BaseMessage, context: PluginContext): ReactNode;

  /** Return context menu options for a message. */
  getOptions?(message: BaseMessage, context: PluginContext): MessageOption[];

  /** Return plain-text preview for the conversation list subtitle. */
  getLastMessagePreview?(message: BaseMessage, loggedInUser: User, t?: (key: string) => string): string;

  /** Return text formatters (only relevant for text plugin). */
  getTextFormatters?(): CometChatTextFormatter[];

  // --- View Slot Methods (optional) ---
  /** Custom leading view (avatar area). */
  renderLeadingView?(message: BaseMessage, context: PluginContext): ReactNode;
  /** Custom header view (sender name area). */
  renderHeaderView?(message: BaseMessage, context: PluginContext): ReactNode;
  /** Custom footer view (reactions area). */
  renderFooterView?(message: BaseMessage, context: PluginContext): ReactNode;
  /** Custom bottom view (moderation area). */
  renderBottomView?(message: BaseMessage, context: PluginContext): ReactNode;
  /** Custom status info view (timestamp + receipts). */
  renderStatusInfoView?(message: BaseMessage, context: PluginContext): ReactNode;
  /** Custom reply view (quoted message preview). */
  renderReplyView?(message: BaseMessage, context: PluginContext): ReactNode;
  /** Custom thread view (reply count indicator). */
  renderThreadView?(message: BaseMessage, context: PluginContext): ReactNode;
}
```

### Plugin Context

The `context` object passed to every plugin method:

| Field                | Type                            | Description                               |
| -------------------- | ------------------------------- | ----------------------------------------- |
| `loggedInUser`       | `CometChat.User`                | The currently logged-in user              |
| `group`              | `CometChat.Group \| undefined`  | The group (if group chat)                 |
| `alignment`          | `"left" \| "right" \| "center"` | Bubble alignment                          |
| `theme`              | `"light" \| "dark"`             | Current theme                             |
| `getLocalizedString` | `(key: string) => string`       | Localization function                     |
| `onDeleteMessage`    | `(msg) => void`                 | Delete a message                          |
| `onEditMessage`      | `(msg) => void`                 | Enter edit mode                           |
| `onReplyMessage`     | `(msg) => void`                 | Set reply-to target                       |
| `onThreadClick`      | `(msg) => void`                 | Open thread view                          |
| `onReactToMessage`   | `(msg) => void`                 | Open emoji picker                         |
| `onMessageInfo`      | `(msg) => void`                 | Open message info panel                   |
| `onMarkAsUnread`     | `(msg) => void`                 | Mark as unread                            |
| `onFlagMessage`      | `(msg) => void`                 | Open flag/report dialog                   |
| `showToast`          | `(text) => void`                | Show a toast notification                 |
| `getTextFormatters`  | `() => Formatter[]`             | Get text formatters for caption rendering |
| `publish`            | `(event) => void`               | Publish a UI event                        |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Text Plugin" icon="font" href="/ui-kit/react/v7/plugins/text">
    Text rendering, mentions, markdown, URLs
  </Card>

  <Card title="Image Plugin" icon="image" href="/ui-kit/react/v7/plugins/image">
    Image grid, captions, fullscreen viewer
  </Card>

  <Card title="Custom Plugin" icon="puzzle-piece" href="/ui-kit/react/v7/plugins/custom-plugin">
    Build your own plugin from scratch
  </Card>

  <Card title="Text Formatters" icon="wand-magic-sparkles" href="/ui-kit/react/v7/plugins/text-formatters">
    URL, mentions, markdown, and custom formatters
  </Card>
</CardGroup>
