Skip to content

Modes de lancement & manifeste (infos.json)

infos.json est le manifeste de l'appli : il décrit comment elle se lance, ses permissions, ses pages et ses ressources.

launch-mode

  • oneshot — l'appli est lancée, fait son travail, puis se termine (kapp.finish()). Ex. mini-jeu instantané, tirage au sort.
  • backtask — tourne en arrière-plan, sans UI obligatoire. Ex. bot de modération, compteur, agrégateur d'événements.
  • external — doit obligatoirement s'ouvrir dans une fenêtre popout interactive dédiée (séparée de l'overlay OBS). Elle ne peut pas être lancée en mode overlay classique. Ex. tableau de bord, interface debug.

externable: true ajoute le mode popout interactif en plus du mode classique. Par exemple, launch-mode: oneshot + externable: true peut être lancé soit sur l'overlay OBS, soit dans la popout. Le flag est redondant et ignoré avec launch-mode: external, puisque la popout y est déjà obligatoire.

ManifesteOverlay OBSPopout interactive
launch-mode: oneshot, externable: falseouinon
launch-mode: oneshot, externable: trueouioui
launch-mode: backtask, externable: falseouinon
launch-mode: backtask, externable: trueouioui
launch-mode: externalnonoui, obligatoire

Savoir dans quel contexte l'exécution tourne

Le manifeste indique les contextes autorisés. Pour connaître le contexte réel de l'exécution courante, utilise :

js
if (kapp.overlay.isExternal()) {
    // UI interactive de la popout
} else {
    // rendu destiné à l'overlay OBS
}

kapp.overlay.isExternal() est l'API recommandée. La propriété brute kapp.overlay.displayMode vaut toujours overlay ou external. overlay correspond au rendu OBS non cliquable ; external à la popout qui reçoit les interactions souris/clavier. Ne déduis pas ce contexte de kapp.overlay.type.

Attention aux deux « oneshot » : launch-mode: oneshot décrit le cycle de vie de l'appli (elle finit avec kapp.finish()). La valeur historique kapp.overlay.type === 'oneshot' désigne le runtime de la page popup qui héberge l'exécution. Ces notions sont indépendantes : une app oneshot peut tourner sur l'overlay OBS, et une app launch-mode: external est actuellement hébergée par le runtime overlay oneshot.

Champs clés

jsonc
{
  "textset": "textset.js",
  "launch-mode": "oneshot",       // oneshot | backtask | external
  "externable": false,
  "app-index": "index.html",
  "scopes": ["chat:read", "chat:write"],   // permissions Twitch requises
  "services": [],                  // services exposés par l'appli (cf. common/reference/services.md)
  "run-output": null,              // format de sortie pour apps.run (cf. reference/app-to-app.md)
  "kind": null,                    // contrat standard apps.run, ex. "pick-string"
  "overlay-formats": ["16:9"],
  "viewers-plugin": null,          // page viewers (cf. reference/plugins.md)
  "streamer-plugin": null,         // page streamer
  "viewers-readme": null,
  "viewers-optout": false,         // le viewer peut se retirer lui-même de l'appli
  "streamer-readme": null,
  "public-assets": null,
  "required": []
}

overlay-formats n'ajoute aucun format implicitement lorsqu'il est déclaré ; ["9:16"] seul est valide. L'iframe occupe tout le cadre du format choisi ; l'app place son contenu à l'intérieur, éventuellement via une préférence containerArea. window est accepté mais ignoré. La popout démarre dans le premier format déclaré. Voir reference/vertical.md pour les valeurs par défaut et la recette.

viewers-optout

À passer à true si ton appli peut cibler un viewer sans qu'il l'ait demandé (tirage au sort d'un adversaire, désignation d'une victime, etc.). Le viewer voit alors, sur sa page d'appli (/v/{channel}/{slug}), un bouton « ne plus me faire participer ».

Un viewer retiré devient invisible pour ton appli : kapp.users.get() ne le trouve plus, il n'apparaît plus dans kapp.chat.getActiveUsers(), tu ne reçois plus ses messages ni ses events (follow, sub, raid…), il ne peut plus lancer l'appli et ne peut plus être passé en argument de trigger. Écris donc ton code comme si ce viewer n'existait pas — c'est déjà le cas pour toi.

Le flag ne gouverne que le droit du viewer : le streamer, lui, peut interdire n'importe quelle appli à n'importe quel viewer depuis son dashboard, que le flag soit présent ou non.

Pièges

  • Choisis le launch-mode selon l'usage : une appli backtask n'appelle pas forcément display(), une oneshot doit penser à finish().
  • N'utilise jamais kapp.overlay.type === 'oneshot' pour détecter une popout interactive ; utilise kapp.overlay.isExternal().
  • scopes doit couvrir les actions Twitch utilisées (ex. chat:write pour kapp.chat.say).
  • Déclare dans services uniquement si d'autres briques doivent piloter ton appli (voir common/reference/services.md).
  • viewers-optout : une liste de viewers peut revenir plus courte que demandée (kapp.users.get([...])) ou un getActiveUsers() vide — gère le cas au lieu de supposer que la cible existe.