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
| Parameter | Type | Description |
|---|---|---|
jid | string | Destination — user JID or group JID |
htmlPayload | string | Full HTML string (include <style> and <script> inline) |
options.title | string | Title text shown above the game card |
options.subtitle | string | Optional subtitle / instructions text |
options.trustedSources | string[] | Allowed domains for the HTML sandbox |
options.responseId | string | UUID for the response_id field |
options.botResponseId | string | UUID for bot metadata identification |
options.botJid | string | The bot JID embedded in context info |
options.signature | string | Base64 verification signature |
options.certificateChain | string[] | 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 roundRectpolyfill 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:
- No external URLs — All assets must be inline (pure canvas or base64 data URIs)
- Use pointer events not mouse events — use
pointerdown,pointermove - Set
touch-action: noneon body to prevent scroll interference - Disable text selection —
*{-webkit-user-select:none;user-select:none} - Use
localStoragefor score persistence — works within the sandbox - Keep canvas width
\<= 560pxfor best mobile fit - 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
| File | Purpose |
|---|---|
src/Socket/messages-send.ts | sendHtmlGame function implementation |
bot/index.js | .dino and .snake bot command handlers |
baileys.wiki-site/docs/udmodz/send-html-game.md | This documentation |