---
description: Build custom plugins for RealtimeKit meetings.
title: Build your own plugins
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/realtime/llms.txt  
> Use this file to discover all available pages before exploring further.

# Build your own plugins

Last updated Aug 24, 2026|Copy as Markdown|[View as Markdown](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/custom-plugins/build-your-own-plugins/index.md)|[Agent setup](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/agent-setup/)

This guide explains how to build a custom plugin and run it inside a meeting using the Cloudflare RealtimeKit Core SDK.

A custom plugin is a DOM element that you register with the SDK. When a participant activates the plugin, RealtimeKit makes it active for everyone in the session and renders it in the meeting layout.

This page is not available for the **Mobile**platform.

WebMobile

ReactWeb ComponentsAngular

## Prerequisites

This page builds on the [Initialize SDK](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/core/) and [Plugins](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/core/plugins/) guides. Read those first.

The examples assume you have already imported the necessary packages and initialized the SDK.

## How a plugin works

A plugin has two parts:

* A **component**: a DOM element (`HTMLElement`) that holds your plugin's UI and logic.
* A **registration**: a configuration object you pass to the SDK so it can list, activate, and render the component.

RealtimeKit synchronizes activation state across the session. To share plugin data between participants, use [collaborative stores](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/collaborative-stores/).

## 1\. Build the plugin component

A plugin component must be an `HTMLElement`. Build it directly as a custom element, or create a container element and mount your framework component tree into it.

Define your plugin as a custom element, then create an instance to pass as the `component`.

```ts
class MyCounterPlugin extends HTMLElement {
	connectedCallback() {
		this.innerHTML = `
			<div class="counter">
				<button id="increment">This is a counter plugin</button>
				<span id="value">0</span>
			</div>
		`;
	}
}

customElements.define("my-counter-plugin", MyCounterPlugin);

const pluginElement = document.createElement("my-counter-plugin");
```

Create a container element and mount your component tree into it. Pass the container as the `component`.

```tsx
import { createRoot } from "react-dom/client";

function CounterPlugin() {
	return <div className="counter">This is a counter plugin</div>;
}

const pluginElement = document.createElement("div");
createRoot(pluginElement).render(<CounterPlugin />);
```

Create a container element and mount your component tree into it. Pass the container as the `component`.

```ts
import {
	createComponent,
	ApplicationRef,
	EnvironmentInjector,
} from "@angular/core";
import { CounterPluginComponent } from "./counter-plugin.component";

const pluginElement = document.createElement("div");

const componentRef = createComponent(CounterPluginComponent, {
	environmentInjector: this.injector,
	hostElement: pluginElement,
});

this.appRef.attachView(componentRef.hostView);
```

## 2\. Register and render the plugin

Register the plugins available in a session when you initialize the SDK. Pass an array of plugin configurations as `defaults.plugins`, using the `pluginElement` you created in step 1 as the `component`.

```ts
RealtimeKitClient.init({
	authToken: "<auth_token>",
	defaults: {
		plugins: [
			{
				id: "counter",
				name: "Counter",
				icon: "https://example.com/counter.png",
				permissions: {
					canActivate: true,
					canDeactivate: true,
				},
				component: pluginElement,
			},
		],
	},
});
```

For a description of every configuration field, refer to [Register a plugin](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/core/plugins/#register-a-plugin).

After registration, the plugin appears in `meeting.plugins.all`. Activate it to make it active for everyone in the session.

```js
const plugin = meeting.plugins.all.get(pluginId);
await plugin.activate();
```

```jsx
const plugins = useRealtimeKitSelector((m) => m.plugins);
const plugin = plugins.all.get(pluginId);
await plugin.activate();
```

Note

If you use the UI Kit, the plugin components handle activation and rendering for you.

## 3\. Respond to plugin events

A `Plugin` object emits events as its state changes. Use them to set up or tear down your component when it is activated or deactivated.

```js
const plugin = meeting.plugins.all.get(pluginId);

plugin.on("enabled", () => {
	// The plugin became active for the local participant
});

plugin.on("closed", () => {
	// The plugin was deactivated for the local participant
});
```

For the full list of plugin events, refer to [Listen to plugin events](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/core/plugins/#listen-to-plugin-events).

## 4\. Sync data across participants

Each participant runs their own copy of the plugin component, so you need a way to share state between them. RealtimeKit offers two built-in options for real-time communication:

* [Collaborative stores](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/collaborative-stores/) — a shared key-value store that syncs state across the session.
* [Message broadcasts](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/broadcast-apis/) — send custom events to every participant in a meeting.

For plugins with simple requirements, these built-in APIs are enough to handle your collaborative logic.

```js
// Create or get a store for your plugin
const store = meeting.stores.create("counter");

// Update a value for all participants
await store.set("value", 1);

// React to updates from any participant
store.subscribe("value", ({ value }) => {
	document.querySelector("#value").textContent = value;
});
```

For richer, full-featured collaboration, you can pair your plugin with a dedicated third-party framework:

| Framework                                        | Description                                                  | Notes       |
| ------------------------------------------------ | ------------------------------------------------------------ | ----------- |
| **[Collab-Kit ↗](https://docs.collab-kit.com/)** | Full-featured SDK for building collaborative apps.           | Beta        |
| **[Party-Kit ↗](https://docs.partykit.io/)**     | Low-level framework for building collaborative applications. | Open source |

## Next steps

* Review the [Plugins](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/core/plugins/) API for the complete `Plugin` and `Plugins` reference.
* Use [collaborative stores](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/realtime/realtimekit/collaborative-stores/) to build richer shared experiences.
* Get started with the [RealtimeKit plugins example ↗](https://github.com/cloudflare/realtimekit-web-examples/tree/main/react-examples/examples/plugins) for a working React implementation.

Was this helpful?

YesNo

## On this page

[![](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://docs-durable-objects-instance-replaced-errors.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/realtime/realtimekit/custom-plugins/build-your-own-plugins/#page","headline":"Build your own plugins · Cloudflare Realtime docs","description":"Build custom plugins for RealtimeKit meetings.","url":"https://developers.cloudflare.com/realtime/realtimekit/custom-plugins/build-your-own-plugins/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-08-24","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
