Skip to content

Concepts ​

What is a plugin? ​

A Dissent plugin is an HTML page that runs inside a sandboxed <iframe> within the Dissent client. The plugin communicates with the host application exclusively through the SDK — there is no direct DOM or network access to the surrounding app. The sandbox boundary is the security boundary.

The plugin contexts ​

ContextWhere it rendersTypical use
channelReplaces the entire chat areaRich apps: polls, event cards, game dashboards
sidebarCompact card in the right panelLive stats, countdowns, leaderboards
profileCard on a user's profileNow playing, game rank, activity graph
embedInline in the chat feed (ephemeral)Slash command results: /weather, /rank
personalA user's own My plugins page — and, on desktop, panels in the game overlayA game wiki, a run tracker, anything for yourself. See Personal Plugins

A plugin can support multiple contexts. The context field in manifest.json is an array.

The tier and permission model ​

A plugin lists the permissions it needs in declared_permissions; that list is all a user can grant. If it declares any, a channel or sidebar plugin shows a consent card before it loads: Join grants every declared permission, View Without Joining grants none.

The manifest tier is only a label — 1 Passive, 2 Interactive, 3 Activity. It grants nothing and does not decide whether the card appears. The full list of permissions is in Permissions.

ctx.permissions in your plugin always reflects exactly what the current user has granted. Check it before calling methods that require a permission.

The sandbox ​

Every plugin runs in:

html
<iframe sandbox="allow-scripts">

This means:

  • The plugin's origin is null — it cannot read cookies, localStorage, or make credentialed requests to any domain.
  • The plugin cannot access the Dissent session token, E2EE keys, or any data from the surrounding app.
  • All data flows through the SDK. Everything a plugin reads or sends — Dissent.fetch(), Dissent.getUser(), Dissent.storage — goes through the host, which checks the user's grants on every call. There is no way for a plugin to read channel messages.

Two ways to load the SDK ​

Script tag (no toolchain needed):

html
<script src="https://app.dissent.chat/sdk/v1/dissent-plugin-sdk.iife.js"></script>
<script>
  Dissent.init().then(ctx => { /* your plugin */ });
</script>

ES module:

html
<script type="module">
  import Dissent from 'https://app.dissent.chat/sdk/v1/dissent-plugin-sdk.js';
  const ctx = await Dissent.init();
</script>

Both are built from the same source and expose the identical API. There is no npm package; the SDK API Reference lists the TypeScript types to copy into your project.