Install Dreamcode Chat Widget

Add the widget in minutes (Basic) or enable Secure mode for maximum protection.

This guide is for website owners who want to add the Dreamcode chat widget to their site. You can choose between Basic mode (fast setup) and Secure mode (recommended — protects against origin spoofing and local /etc/hosts tricks).

What you need from Dreamcode

  • Your API token (looks like a long hex string)
  • Your allowed domain list (example.com, www.example.com, etc.)
  • Optional: Telegram settings (Bot Token + Channel ID)

1) Basic mode (quick install)

Paste this snippet before </body> on your website:

<script src="https://dreamcode.am/widget/YOUR_API_TOKEN.js" async></script>

After deployment, open your website and send a test message. If you get 403 Widget is not authorized for this domain, your domain is not whitelisted in the Dreamcode Client settings.

2) Secure mode (recommended — 100% protection)

Secure mode prevents unauthorized use of the widget even if someone tries to spoof your domain locally. It requires a small backend endpoint on your website.

Step A — enable Secure mode in Dreamcode

  • Dreamcode enables Secure mode for your Client
  • Dreamcode provides a Server auth secret (store it only on your server as an environment variable)

Step B — add a token endpoint on your website

Create this endpoint on your site (same-origin):

GET /.well-known/dreamcode-chat/token?client_token=YOUR_API_TOKEN

Your backend endpoint must: (1) detect current domain from Host, (2) sign a request with HMAC using your Server auth secret, (3) call Dreamcode to issue a short-lived token, (4) return JSON to the browser.

Dreamcode endpoint to call from your backend

POST https://dreamcode.am/api/widget/issue-token/

Body JSON:
  {"domain": "example.com"}

Headers:
  X-Client-Token: YOUR_API_TOKEN
  X-Timestamp: unix_seconds
  X-Nonce: random_string
  X-Signature: base64url(hmac_sha256(secret, "token\ndomain\nts\nnonce"))  (no "=")

Step C — keep the same script tag

No changes are needed in your HTML script tag:

<script src="https://dreamcode.am/widget/YOUR_API_TOKEN.js" async></script>

Examples (React + Django)

React: load the widget script

Option 1 (recommended): put the script tag into your HTML (for example public/index.html).

<!-- public/index.html -->
<script src="https://dreamcode.am/widget/YOUR_API_TOKEN.js" async></script>

Option 2: inject the script from React (if you need it programmatically).

import { useEffect } from "react";

export function DreamcodeChatWidget() {
  useEffect(() => {
    const s = document.createElement("script");
    s.src = "https://dreamcode.am/widget/YOUR_API_TOKEN.js";
    s.async = true;
    document.body.appendChild(s);
    return () => {
      document.body.removeChild(s);
    };
  }, []);

  return null;
}

Django: implement the secure token endpoint

This is the endpoint your site must expose in Secure mode: GET /.well-known/dreamcode-chat/token?client_token=YOUR_API_TOKEN

# urls.py (on your website)
from django.urls import path
from .views import dreamcode_chat_token

urlpatterns = [
    path('.well-known/dreamcode-chat/token', dreamcode_chat_token),
]
# views.py (on your website)
import base64
import hashlib
import hmac
import os
import time
import requests

from django.http import JsonResponse
from django.views.decorators.http import require_GET


def _b64url_no_pad(b: bytes) -> str:
    return base64.urlsafe_b64encode(b).decode('ascii').rstrip('=')


@require_GET
def dreamcode_chat_token(request):
    # Validate client_token (optional but recommended)
    client_token = request.GET.get('client_token', '')
    if not client_token:
        return JsonResponse({'error': 'client_token is required'}, status=400)

    # Store these as environment variables on YOUR SERVER (never in JS)
    secret = os.environ.get('DREAMCODE_SERVER_AUTH_SECRET', '')
    if not secret:
        return JsonResponse({'error': 'Server auth secret not configured'}, status=500)

    # Use current request host as domain
    domain = (request.get_host() or '').split(':')[0]
    ts = str(int(time.time()))
    nonce = os.urandom(16).hex()

    msg = f"{client_token}\n{domain}\n{ts}\n{nonce}".encode('utf-8')
    sig = _b64url_no_pad(hmac.new(secret.encode('utf-8'), msg, hashlib.sha256).digest())

    r = requests.post(
        'https://dreamcode.am/api/widget/issue-token/',
        json={'domain': domain},
        headers={
            'X-Client-Token': client_token,
            'X-Timestamp': ts,
            'X-Nonce': nonce,
            'X-Signature': sig,
        },
        timeout=5,
    )

    # Proxy Dreamcode response back to the browser
    try:
        data = r.json()
    except Exception:
        data = {'error': 'Invalid response from Dreamcode'}

    return JsonResponse(data, status=r.status_code)

3) Troubleshooting

  • 403 Widget is not authorized for this domain → ask Dreamcode to add your domain to the allowed list.
  • Secure mode enabled… token endpoint is not configured → your site must implement /.well-known/dreamcode-chat/token.
  • Widget colors do not update → CDN cache may need purge (widget script is cached).