Skip to main content

sendHtmlGame — HTML Interactive Game/Widget

Overview

conn.sendHtmlGame(jid, htmlPayload, options?) is a Baileys socket function that embeds arbitrary HTML + CSS + JS inside a WhatsApp AI-rich bubble message using the GenAIaeacdsnwHtmlPrimitive message primitive. It uses the same botForwardedMessage + richResponseMessage transport internally as the .dino command.

The HTML payload runs sandboxed inside WhatsApp's in-app browser and has access to:

  • <canvas> 2D rendering
  • Touch & pointer events
  • localStorage / sessionStorage / cookies (for score persistence)
  • requestAnimationFrame / setInterval
  • All standard DOM APIs

Function Signature

conn.sendHtmlGame(
jid: string,
htmlPayload: string,
options?: {
title?: string // Label shown in card header (default: "UDMODZ")
subtitle?: string // Subtitle below title (default: "")
trustedSources?: string[] // Trusted domain list (default: ["udmodz.dev"])
responseId?: string // UUID for rich response (auto-generated)
botResponseId?: string // UUID for bot metadata (auto-generated)
botJid?: string // Bot JID (default: "867051314767696@bot")
signature?: string // Base64 verification sig (has built-in default)
certificateChain?: string[] // Base64 cert chain (has built-in default)
}
): Promise<string> // Returns the relayed message ID

Parameters

ParameterTypeDescription
jidstringDestination — user JID or group JID
htmlPayloadstringFull HTML string (include <style> and <script> inline)
options.titlestringTitle text shown above the game card
options.subtitlestringOptional subtitle / instructions text
options.trustedSourcesstring[]Allowed domains for the HTML sandbox
options.responseIdstringUUID for the response_id field
options.botResponseIdstringUUID for bot metadata identification
options.botJidstringThe bot JID embedded in context info
options.signaturestringBase64 verification signature
options.certificateChainstring[]Array of base64 certificate strings

Basic Usage

// Minimal — just pass jid + html
await conn.sendHtmlGame(from, '<body><h1>Hello World</h1></body>');

// With options
await conn.sendHtmlGame(from, myGameHtml, {
title: 'My Game',
subtitle: 'Tap to play!',
trustedSources: ['udmodz.dev']
});

Built-in Commands

Two commands are registered in bot/index.js that use this transport:

.dino — Dino Runner

A pixel-art running game using relayMessage directly. Tap the screen to jump over cacti. Score increases as speed rises.

.snake — Snake Game

A full Snake game using conn.sendHtmlGame(). Control with the on-screen D-pad.

Features:

  • 18x14 grid canvas with ambient dot-grid background
  • Glowing pulsing food with shadow effect
  • Gradient-colored snake body + directional eye
  • Particle burst when food is eaten
  • Score persistence via localStorage
  • roundRect polyfill for older WebViews
  • Game-over overlay with tap-to-restart
if (cmd === '.snake') {
const snakeHtml = `...`; // full HTML string
await conn.sendHtmlGame(from, snakeHtml, {
title: 'UDMODZ Snake',
subtitle: "Swipe to eat Don't hit the walls!",
trustedSources: ['udmodz.dev']
});
}

How It Works (Internals)

conn.sendHtmlGame(jid, html, opts)

├── Builds sections[] array:
│ ├── [0] FOATextPrimitive → Title
│ ├── [1] GenAIMarkdownTextUXPrimitive → Subtitle (if provided)
│ └── [2] GenAIaeacdsnwHtmlPrimitive → HTML payload + trusted_sources

├── Wraps in richResponseMessage:
│ └── unifiedResponse.data = Buffer.from(JSON.stringify({ response_id, sections }))

├── Adds botForwardedMessage with:
│ └── contextInfo.forwardedAiBotMessageInfo.botJid

└── Adds messageContextInfo.botMetadata with:
└── verificationMetadata.proofs[0] → { signature, certificateChain }

└── Calls relayMessage(jid, msg, {})

Writing Custom HTML Games

Rules for best compatibility inside WhatsApp's sandboxed browser:

  1. No external URLs — All assets must be inline (pure canvas or base64 data URIs)
  2. Use pointer events not mouse events — use pointerdown, pointermove
  3. Set touch-action: none on body to prevent scroll interference
  4. Disable text selection*{-webkit-user-select:none;user-select:none}
  5. Use localStorage for score persistence — works within the sandbox
  6. Keep canvas width \<= 560px for best mobile fit
  7. Avoid alert() — use canvas overlays instead

Example: Minimal Custom Game

const myGameHtml = `
<style>*{user-select:none;touch-action:none}body{margin:0;background:transparent}</style>
<canvas id="c" width="360" height="280"></canvas>
<script>
const c = document.getElementById('c');
const ctx = c.getContext('2d');
// Your game logic here...
ctx.fillStyle = '#00e678';
ctx.fillRect(50, 50, 80, 80);
</script>`;

await conn.sendHtmlGame(from, myGameHtml, {
title: 'My Custom Game',
subtitle: 'Tap to play!'
});

File Locations

FilePurpose
src/Socket/messages-send.tssendHtmlGame function implementation
bot/index.js.dino and .snake bot command handlers
baileys.wiki-site/docs/udmodz/send-html-game.mdThis documentation