INTEGRITY Cloudflare Docs

Build your own plugins

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 Mobileplatform.

Prerequisites

This page builds on the Initialize SDK and 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:

RealtimeKit synchronizes activation state across the session. To share plugin data between participants, use 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.

my-counter-plugin.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.

counter-plugin.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.

counter-plugin.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.

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.

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

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

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.

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.

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:

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

// 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 Full-featured SDK for building collaborative apps. Beta
Party-Kit Low-level framework for building collaborative applications. Open source

Next steps