TokElementsDOCS
WIDGET SDK / V1
01

Başlarken

1
Markup ve stil yaz

HTML ve CSS sekmeleri widget’ını çizer. Kutu şeffaftır ve videonun üstünde durur; asla tam, opak bir arka plan boyama.

2
Olaylara tepki ver

JS sekmesinde TE.on('gift', fn) ile abone ol. window.TE zaten yüklü: import yok, kurulum yok.

3
Test et ve ekle

Çevrimdışı önizlemek için Simulate veya Fire butonlarını kullan, sonra Overlay’e ekle. Ya da Claude MCP üzerinden yapsın.

İlk widget’ın: bir hediye teşekkürü· JS’i düzenle, önizleme canlı tepki verir
var box = document.getElementById('box');
TE.on('gift', function (ev) {
  box.textContent = ev.user.name + ' sent ' + ev.gift.name + '!';
  box.classList.remove('pop'); void box.offsetWidth; box.classList.add('pop');
});
Canlı önizleme
02

Claude’u bağla (MCP)

Bu widget’ları doğrudan Claude Desktop veya Claude Code’dan oluştur ve düzenle. Bir token üret, bağlayıcıyı ekle; Claude hesabında şu araçları çağırabilir:

get_docsTam yazım rehberi + tüm tetikleyiciler ve aksiyonlar (Claude önce bunu okur).
list_widgetsKayıtlı widget’larını id’leriyle listeler.
get_widgetBir widget’ın html / css / js’ini getirir.
create_widgetAd + html/css/js ile yeni bir HTML widget’ı oluşturur.
update_widgetMevcut bir widget’ı düzenler.
delete_widgetBir widget’ı id ile siler.
list_templatesKopyalanabilecek yerleşik şablonları listeler.
get_templateBir şablonun html/css/js’ini okur.
create_from_templateBir şablonu yeni bir widget’a kopyalar.
list_community_templatesTopluluğun yayınladığı widget’lara göz atar.
install_community_templateBir topluluk şablonunun özel, düzenlenebilir bir kopyasını kurar.
Yükleniyor…
03

TE SDK

Bir widget’ın yaptığı her şey global window.TE nesnesi üzerinden geçer.

TE.on(type, fn)

Bir canlı olaya abone ol. `type` aşağıdaki tetikleyicilerden herhangi biri; `fn(ev)` olay her gerçekleştiğinde çalışır.

TE.on('*', fn)

Tüm olayları yakala. `fn(ev, type)` payload’ı ve olay adını alır.

TE.off(type, fn)

Daha önce kaydedilmiş bir handler’ı kaldırır.

TE.onGift(name, fn)

Yalnızca adı eşleşen hediyelerde tetiklenir (büyük/küçük harf duyarsız alt dize). Her hediyeyi yakalamak için `name`’i boş bırak.

TE.onSticker(idOrUrl, fn)

Yalnızca belirli bir abone emote’u / çıkartması için tetiklenir; TikTok id’si, görsel URL’si veya kaynağıyla eşleştirilir.

TE.rules.allowUser / allowGift

Roller, izin/engel listeleri, hediye adı ve minimum coin değeri için yeniden kullanılabilir uygunluk filtreleri.

TE.metrics

En güncel yayın anlık görüntüsü nesnesi (viewers, likes, coins, followers, topGifters…). TE.on('metrics', fn) ile de gelir.

TE.demo

Widget’ın sergilendiği yerlerde (galeri, önizleme kutuları, oluşturucunun Demo anahtarı) true. Canlı overlay’de ve oluşturucuda ya da overlay editöründe test ederken false; orada yalnızca senin tetiklediklerin veya canlı gelenler görünür. Her widget orada kendini gösterir: gerçek olaylara benzeyen örnekleri (gerçek hediye görselleri, isimler, avatarlar) widget’ın gerçek kod yolundan geçecek şekilde bir if (TE.demo) bloğuna koy. Böyle bir bloğu olan widget host’tan önizleme olayı almaz, yani hiçbir şey iki kez tetiklenmez.

TE.defineSettings([...])

Yayıncının ayarlayabileceği kontrolleri tanımlar; mevcut değerleri döndürür (varsayılanlar + yayıncının seçimleri).

TE.settings

Mevcut ayar değerleri nesnesi (defineSettings’in döndürdüğüyle aynı yapı).

TE.on('settings', fn)

Yayıncı bir ayarı canlı değiştirdiğinde çalışır; yeni değerlerle yeniden çiz.

TE.state.get/set/increment

Toplamlar ve paylaşılan oyun durumu için Promise tabanlı atomik değerler.

TE.collection.*

Sunucuda tutulan, bir kez katılınan katılımcı ve skor tabloları: join, increment, list, count, remove ve clear.

TE.queue.*

Medya, istekler ve izleyicinin tetiklediği aksiyonlar için sunucuda tutulan, sınırlı FIFO kuyrukları.

TE.shared.*

Birden fazla widget’ı tek bir adlandırılmış kanal durumu alanına dahil et; ilgisiz widget’lar izole kalır.

TE.random.draw(name, opts)

Bir koleksiyondan güvenli şekilde bir veya daha fazla kazanan çek ve sonucu kaydet.

TE.cooldown.claim(scope, user, ms)

Global veya kullanıcı başına bir bekleme süresini atomik olarak al; claimed ve retryAfterMs döndürür.

TE.timer.*

Yeniden yüklemelerden etkilenmeyen, kalıcı bir gerçek zamanlı sayacı başlat, duraklat, sıfırla ve oku.

TE.points.trySpend(user, amount, reason)

Puanları tek bir işlemde kontrol et ve düş; ücretli bir etkileşimi çalıştırmadan önce her zaman result.ok’a bak.

04

Tetikleyiciler

Dinleyebileceğin canlı olaylar. Her user şunu içerir: { id, name, username, avatar, roles }.

TE.on('gift')

Bir izleyici hediye gönderdi. coins = kombonun toplamı; streakEnd kombonun bittiğini gösterir.

{ user, gift: { name, image|null, coins, repeat, combo, streakEnd } }
TE.on('follow')

Bir izleyici hesabı takip etti.

{ user }
TE.on('subscribe')

Bir izleyici abone oldu. months = art arda kaç ay.

{ user, months }
TE.on('share')

Bir izleyici yayını paylaştı.

{ user }
TE.on('chat')

Bir sohbet mesajı. emotes = bu mesajdaki satır içi abone emote görsellerinin URL’leri.

{ user, comment, emotes:[url,…] }
TE.on('like')

Bir izleyici beğeni gönderdi. count = bu seri; total = güncel toplam.

{ user, count, total }
TE.on('join')

Bir izleyici odaya girdi. isTop = en çok hediye gönderenlerden biri katıldı.

{ user, isTop }
TE.on('sticker')

Canlıda gönderilen bir abone emote’u veya ekran çıkartması. url = emote görseli; id = TikTok id’si.

{ user|null, id|null, url, source }
TE.on('metrics')

En güncel yayın anlık görüntüsü. TE.metrics bunu tutar; güncellendiğinde olay tetiklenir. hostNick ve hostAvatar yayıncının kendi adı ve profil fotoğrafıdır.

{ live, viewers, likes, followers, coins, hostNick, hostAvatar, topGifters:[…], … }
TE.on('milestone')

Yuvarlak bir dönüm noktası aşıldı (beğeni, coin, takipçi, abone).

{ metric, value, label }
TE.on('poll')

TikTok’un kendi canlı anketi: gerçek oylar, baştan sona.

{ state:'start'|'update'|'end', title, options:[{text,votes}], endsAt }
TE.on('battle')

LinkMic battle güncellemeleri: battle kartları, fan biletleri, ordu büyüklükleri.

{ card|null, tickets|null, armies|null, battleId|null }
TE.on('rank')

Saatlik sıralama konumu ve sıralama yükselme anları.

{ rank|null, from|null, to|null, countdown|null }
TE.on('envelope')

Canlıya kırmızı zarf / hazine sandığı bırakıldı.

{ }
TE.on('pinned')

Yayıncı bir yorumu sabitledi.

{ text }
TE.on('deleted')

Bir moderatör bir sohbet mesajını kaldırdı (id, önceki chat olayıyla eşleşir).

{ id }
TE.on('streamState')

Yayın canlıya geçti veya kapandı.

{ live }
TE.on('apiEvent')

Event API üzerinden gönderilen özel bir olay. apiEvent’i veya doğrudan özel adını dinle.

{ name, data }
TE.on('nowPlaying')

Yayıncının şu an çalan Spotify şarkısı VE sıradaki kuyruk. Bağlanınca ve şarkı, çalma durumu, ilerleme veya kuyruk her değiştiğinde tetiklenir. Hiçbir şey çalmıyorsa playback null olur; queue sıradaki şarkılardır.

{ connected, playback: { isPlaying, progressMs, durationMs, title, artists:[…], album, artwork|null } | null, queue:[{ title, artist, artwork|null, durationMs }] }
Yalnızca belirli bir hediye veya emote
TE.onGift('Rose', function (ev) { /* … */ });
TE.onSticker('<sticker id>', function (ev) { /* … */ });

Kanalının emote’ları widget oluşturucuda: Simulate events’i aç, Sticker’ı seç ve birini seç. Test olayı gerçek id’sini ve görsel URL’sini taşır; yani ikisinden birine bağlı bir handler gerçeğiyle test edilir.

05

Aksiyonlar

Widget’ının karşılık olarak neler yapabileceği: düz tarayıcı API’leri, yapıştırmaya hazır.

Görsel göster

Ekranda bir görsel patlat: hediye/emote görseli, yüklenmiş bir dosya ya da herhangi bir URL. Birkaç saniye sonra kendiliğinden kalkar.

// Show an image, then fade it out
TE.on('gift', function (ev) {
  var img = document.createElement('img');
  img.src = ev.gift.image;                 // ← any image URL works
  img.style.cssText = 'position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);max-width:60%';
  document.body.appendChild(img);
  setTimeout(function () { img.remove(); }, 4000);   // ← how long it stays
});
Ses çal

Bir olayda ses çal. Bir ses ayarı sun, yayıncı kendi dosyasını seçsin; kod düzenlemek yok.

// Play a sound the streamer chose in settings
var s = TE.defineSettings([{ key: 'sfx', label: 'Alert sound', type: 'sound', default: '' }]);
TE.on('settings', function (ns) { s = ns; });
TE.on('gift', function (ev) {
  if (s.sfx) { var a = new Audio(s.sfx); a.volume = 0.8; a.play(); }
});
Metin göster / canlandır

Dinamik metin yaz ve bir class’ı açıp kapatarak CSS animasyonunu yeniden tetikle.

// Announce the event with a CSS pop animation
var box = document.getElementById('box');   // your element in the HTML tab
TE.on('follow', function (ev) {
  box.textContent = ev.user.name + ' followed!';
  box.classList.remove('pop'); void box.offsetWidth; box.classList.add('pop');
});
Canlı istatistik göster

Ekrandaki bir sayıyı canlı bir metriğe bağla: izleyici, beğeni, coin, takipçi. Otomatik güncellenir.

// Keep a number in sync with the live stream
TE.on('metrics', function (m) {
  document.getElementById('count').textContent = m.viewers.toLocaleString();
});
Sesli oku (TTS)

Bir olayı tarayıcının metin okuma özelliğiyle seslendir. Hediye veya takip teşekkürleri için harika.

// Text-to-speech shout-out
TE.on('gift', function (ev) {
  var u = new SpeechSynthesisUtterance(ev.user.name + ' sent ' + ev.gift.name);
  speechSynthesis.speak(u);
});
Önizleme (TE.demo)

Her widget galeride ve oluşturucuda kendini gösterir: gerçek olaylara benzeyen örnekler, gerçek hediye görselleri, isimler ve avatarlarla. Canlıda TE.demo false olur ve yalnızca gerçek olaylar görünür.

// Preview samples through the real code path. Never on a live overlay.
if (TE.demo) {
  var GIFTS = [
    { name: 'Rose', coins: 1, image: 'https://p16-webcast.tiktokcdn.com/img/maliva/webcast-va/eba3a9bb85c33e017f3648eaf88d7189~tplv-obj.png' },
    { name: 'Perfume', coins: 20, image: 'https://p16-webcast.tiktokcdn.com/img/maliva/webcast-va/20b8f61246c7b6032777bb81bf4ee055~tplv-obj.png' }
  ];
  var NAMES = ['lunaa', 'nightowl_gaming_official'], n = 0;
  function sample() {
    n++;
    onGift({ user: { name: NAMES[n % 2], avatar: window.__TE_AVATAR }, gift: GIFTS[n % 2] });
  }
  sample();
  setInterval(sample, 6000);
}
Bir şeyleri hatırla (TE.store)

Görsel durum için basit, senkron kalıcılık. Katılımcılar, satın almalar ve paylaşılan skorlar için işlemsel runtime’ı kullan.

// Persistent state: survives OBS reloads
var total = TE.store.get('total', 0);          // read (with default)
TE.on('gift', function (ev) {
  total += ev.gift.coins;
  TE.store.set('total', total);                 // write (auto-saved)
  render();
});
Sohbet komutlarına tepki ver

Birebir eşleşen sohbet komutları ve atomik koleksiyonlar sayesinde güvenli katılımlar, oylamalar ve çark çevirmeler mümkün.

// One server-authoritative entry per viewer.
// A function keyword reads s.command on every message, so the
// streamer can change the command in settings without a reload.
TE.onCommand(function () { return s.command || '!join'; }, function (c) {
  TE.collection.join('entrants', c.user.id, c.user).then(function (result) {
    if (result.joined) renderCount(result.count);
  });
});
Yayın aksiyonlarını tetikle (TE.act)

Overlay bildirimlerini, sesleri, TTS’i, sayaçları, subathon süresini veya OBS sahne geçişlerini doğrudan bir widget’tan iste.

// One call, one stream action
TE.act({ id: 'tts', message: 'New high score!' });
TE.act({ id: 'points', user: ev.user, amount: 50 });
İzleyici puanı ver

Sadakat puanlarını işlemsel olarak kontrol et, harca veya ver, ortaya çıkan bakiyeyi al.

// Only spin after the points were really debited
TE.onCommand(function () { return s.command || '!spin'; }, function (ev) {
  TE.points.trySpend(ev.user, 50, 'Wheel spin').then(function (result) {
    if (result.ok) spin();
    else showMissing(result.missing);
  });
});
Adil oyunlar yap

Atomik durum, koleksiyonlar, güvenli rastgele çekilişler, bekleme süreleri ve kalıcı sayaçlar; kopya tarayıcı kaynaklarında bile güvenli.

// Fair draw from a server-owned entrant collection
TE.random.draw('entrants', { count: 1 }).then(function (result) {
  if (result.ok) reveal(result.winners[0].value);
});
Yayıncı kontrolleri ekle

Metin, renk, sayı, açma/kapama anahtarları sun; yayıncı bunları overlay editöründe canlı ayarlar, kod gerekmez.

// No-code controls for whoever uses the widget
var s = TE.defineSettings([
  { key: 'title',  label: 'Title', type: 'text',  default: 'Goal' },
  { key: 'accent', label: 'Color', type: 'color', default: '#FF2E4D' },
]);
document.body.style.setProperty('--accent', s.accent);
TE.on('settings', function (ns) { s = ns; /* re-render with new values */ });
06

Yayıncı ayarları

Kontrolleri TE.defineSettings([...]) ile tanımla; widget’ı kullanan kişi onları overlay editöründe canlı ayarlar, kod yok. Her alan:

Bir veya daha fazla 'button' alanı olan yerleştirilmiş bir widget, bu aksiyonları Overlay Editörü içindeki ayarlarında sunar. Widget Oluşturucu, kod yazarken güvenli önizleme testi için aynı butonları gösterir.

türgörünümdeğer
'text'Tek satırlık metin alanıstring
'number'Sayı alanınumber
'color'Renk seçicihex string, ör. "#FF2E4D"
'select'Açılır liste (options: [...] gerekir)seçeneklerden biri
'toggle'Açma/kapama anahtarıboolean
'range'Kaydırıcı (min / max / step)number
'button'Bildirimsel aksiyon butonuincrement, set veya toggle; doğrulanmış JSON, asla panel kodu değil
'sound'Yayıncının yüklediği sesler için seçici + Yükleseçilen dosya URL’si ("" = yok)
'image'Yayıncının yüklediği görseller için seçici + Yükleseçilen dosya URL’si ("" = yok)
var s = TE.defineSettings([
  { key: 'title',  label: 'Title', type: 'text',   default: 'Follower goal' },
  { key: 'target', label: 'Goal',  type: 'number', default: 100 },
  { key: 'accent', label: 'Color', type: 'color',  default: '#FF2E4D' },
  { key: 'reset',  label: 'Reset', type: 'button', default: 0,
    action: { type: 'increment', step: 1 }, confirm: true, tone: 'danger' },
]);
// re-render when the streamer changes something live
var lastReset = s.reset;
TE.on('settings', function (ns) {
  s = ns;
  if (ns.reset !== lastReset) { lastReset = ns.reset; resetCounter(); }
  render();
});

Kontrol tanımları doğrulanmış veridir. Buton action yalnızca increment, set veya toggle kabul eder. HTML, callback kodu ve rastgele URL’ler panel tarafından reddedilir veya yok sayılır.

07

Sandbox ve sınırlar

Widget’lar katı bir içerik güvenliği politikasına (CSP) sahip izole bir iframe içinde çalışır; bu yüzden bozuk veya kötü niyetli bir widget asla hesabına ya da sayfanın geri kalanına dokunamaz.

İzin verilenler
  • Uzak görseller ve GIF’ler (TikTok hediye görselleri, avatarlar, herhangi bir URL)
  • Google Fonts + kendi @font-face’in
  • new Audio(url) ile ses
  • TokElements’in kendi API’lerine istekler (ör. /api/files/…)
  • CSS animasyonları, SVG, canvas, Web Audio
Engellenenler
  • Harici <script> etiketleri / CDN’ler
  • Başka sunuculara fetch / XHR / WebSocket
  • Çerezler, localStorage, üst sayfaya erişim
  • npm paketleri yüklemek
08

Örnekler

Eksiksiz, kopyala-yapıştır widget’lar. Her önizleme canlı: demo olayları tetiklenir, tepki verişini izleyebilirsin.

Emote tepkisi· sohbette gönderilen emote’u ekranda patlatır
var img = document.getElementById('emote');
// fires for every emote — use TE.onSticker('<id>', …) for one specific one
TE.on('sticker', function (ev) {
  img.src = ev.url;
  img.classList.remove('show'); void img.offsetWidth; img.classList.add('show');
});
Canlı önizleme
Takipçi hedef çubuğu· bir çubuğu canlı bir metriğe bağlar
var target = 200;                       // ← your goal
TE.on('metrics', function (m) {
  var pct = Math.min(100, m.follows / target * 100);
  document.getElementById('fill').style.width = pct + '%';
  document.getElementById('txt').textContent = m.follows + ' / ' + target;
});
Canlı önizleme