Skip to content

Channel Plugins ​

What it does ​

A channel plugin replaces the entire chat area in a channel. While active, the plugin covers the message list, message input, and sidebar. It has the full width and height of the chat viewport.

When to use this context ​

Use channel plugins for:

  • Rich experiences that need the full screen: polls, event cards, game dashboards, tournament brackets
  • Apps that replace the chat: leaderboards, task managers, collaborative whiteboards
  • Data-heavy visualizations: charts, analytics, activity logs

Channel plugins are powerful but intrusive. If you're building a small widget, use sidebar plugins instead.

Minimal example ​

html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="https://app.dissent.chat/sdk/v1/dissent-plugin-sdk.iife.js"></script>
  <style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: system-ui, sans-serif;
      background: var(--bg, #0a0a12);
      color: rgba(255,255,255,0.85);
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    .card {
      background: rgba(255,255,255,0.04);
      border: 1px solid rgba(255,255,255,0.1);
      border-radius: 16px;
      padding: 32px;
      max-width: 480px;
      width: 100%;
      text-align: center;
    }
    h1 { font-size: 24px; font-weight: 800; margin-bottom: 8px; }
    p  { font-size: 14px; color: rgba(255,255,255,0.5); }
  </style>
</head>
<body>
  <div class="card">
    <h1 id="title">Loading…</h1>
    <p id="server"></p>
  </div>
  <script>
    async function main() {
      const ctx = await Dissent.init({
        onFallback: () => console.warn('Running outside Dissent — no context available'),
      });

      // Apply theme colours from the host app
      for (const [k, v] of Object.entries(ctx.theme)) {
        document.documentElement.style.setProperty(k, v);
      }

      document.getElementById('title').textContent = ctx.config.title ?? 'Channel Plugin';
      document.getElementById('server').textContent = ctx.server.name;

      // Theme updates when the user switches themes
      Dissent.on('theme:change', (theme) => {
        for (const [k, v] of Object.entries(theme)) {
          document.documentElement.style.setProperty(k, v);
        }
      });
    }

    main().catch(err => console.error(err));
  </script>
</body>
</html>

Channel messages are off limits ​

A plugin cannot read the channel's messages — neither history nor new messages as they arrive. There is no getMessages() and no message:new event; the channel:read permission that once allowed it was removed on 2026-08-15. To share live state between members looking at your plugin, publish realtime events to your own install and listen with Dissent.on() (requires realtime; see postMessage Protocol).

Posting as the bot ​

With bot:post declared and granted, you can post messages to the channel:

javascript
await Dissent.postMessage('The event has started!');

Requires bot:post; the user is asked to grant it on the consent card.

Gotchas ​

  • The consent card follows your permissions. Declare none and the plugin loads straight away; declare any and each user is asked first. The tier is only a label.
  • ctx.channel is always available. ctx.channel.id and ctx.channel.name are safe to use in channel context.
  • The channel's chat is hidden while your plugin is shown. If members still need to talk alongside it, a sidebar plugin may be the better fit.
  • Admin config is optional. ctx.config may be empty. Always provide sensible defaults: ctx.config.title ?? 'Default Title'.