Appearance
SDK app V2 — choisir le bon contrat
Une installation conserve les préférences et les stockages de l’appli sur un channel. Une exécution possède une mémoire JavaScript temporaire : relancer l’appli ne restaure pas sa partie. Pour travailler avec le DEV HUB, compiler ou prévisualiser, partir du workflow de développement.
Concevoir : où placer chaque donnée
Recommandations à adapter au besoin, pas des règles :
| Nature | Support conseillé | À retenir |
|---|---|---|
| Réglage réutilisé d’une session à l’autre | Préférence | Persistant mais modifiable : par le streamer, ou par l’appli via set() quand c’est bien un réglage (y compris à la demande du plugin streamer). |
| Commande de session : démarrer, manche suivante, choisir un média | Plugin streamer (emitWithReply), commande chat, trigger | L’appli valide puis exécute ; l’envoi n’est pas l’exécution. |
| État de partie : phase, participants, score courant | Mémoire de l’exécution, exposée aux plugins par un instantané | L’appli est la source de vérité ; perdu au redémarrage. |
| Progression à reprendre, données par viewer | dataStorageV2, userDataStorageV2 | Sauvegarder pendant l’exécution, pas seulement dans un hook final. |
| Historique | logsStorageV2 | Ajout seul. |
| Lire une variable du channel choisie par le streamer | kapp.variables.getFromPreference(path) | Lecture seule de la sélection ; voir variables. |
| Résultat pour un appelant | finish(result) | Voir app-to-app. |
Répondre aux plugins et aux services par une enveloppe {ok, reason} plutôt que par une exception ; identifier le viewer par le SDK, jamais par data.
Appli ou widget ? Un widget suffit pour réagir à un événement du channel avec médias, annonce ou code court. Préférences, stockages propres, pages plugins, publication au catalogue ou partie longue avec état demandent une appli.
Démarrage et sortie
Conserve le bootstrap : index.html écoute AppliLoaded sur document avant de charger le SDK, puis charge le script métier. Dans ce script, kapp existe déjà ; aucune fonction window.executeAppFunction n’est à déclarer. L’exemple mini-jeu précise les fichiers à conserver et remplacer.
kapp.display() affiche ; kapp.undisplay() masque sans arrêter. await kapp.finish(result?) envoie les récompenses accumulées puis termine ; await kapp.abort(reason) interrompt sans les distribuer. La fin du script ne ferme pas l’appli. Verrouille la sortie avant le premier await, nettoie tes abonnements et timers et sauvegarde les étapes importantes pendant l’exécution. Les hooks ne sont pas garantis lors d’un crash. Contrat complet : cycle de vie.
Quel contexte ?
| Page | Objets et contrat |
|---|---|
| Iframe principale de l’appli | kapp / k : instance SDK immuable. prefs : arbre courant des préférences. text(key, args?) : traduction dans la langue du channel. wait(ms), $ / jQuery sont aussi disponibles. |
| Plugin viewers ou streamer | Helper V3 KappappsHost ; initialisation indépendante, voir client plugin. Ne pas y supposer les globaux de l’appli. |
| Panneau HTML de préférences | Pont window.KappappsPrefs, voir panneaux personnalisés. |
Le SDK remplace prefs au rafraîchissement : applique les préférences une première fois, puis relis-les dans kapp.preferences.EVENTS.UPDATED. Une valeur conservée auparavant ne se met pas à jour seule.
Je veux…
| Besoin | Lire avant de coder |
|---|---|
| Préparer un projet et ses fichiers livrés | Bootstrap, projet compilé complet, livraison. |
| Choisir un média, un viewer, une zone ou un avatar | Composants visuels, Phaser, sélecteur plugin. |
| Boucler un fichier ou composer une animation image + son | Compositions média : playClip, playComposition et finished. |
| Déclarer l’affichage, les scopes, les entrées et le manifeste | Manifeste, affichage et déclencheurs. Pour distinguer overlay OBS et popout interactive : kapp.overlay.isExternal(). |
| Créer un formulaire, une condition, une collection ou une migration | Préférences, point d’entrée vers les neuf fiches ; exemple préférences + i18n. |
| Conserver des données globales, par viewer ou un historique | Stockages V2 : dataStorageV2, userDataStorageV2, logsStorageV2 ; exemple compteur. |
| Déclarer gagnants/perdants, terminer et traiter un échec | Récompenses et cycle de vie. |
| Échanger avec un plugin, confirmer une action, resynchroniser un viewer | Transports → service plugin, helper V3, protocole et reprise ; exemple quiz viewers. |
| Réagir à une préférence trigger ou créer un trigger temporaire | Triggers persistants, dynamiques ; exemple trigger configuré. |
| Lancer une appli ou un widget et récupérer son résultat | Lanceur partagé, configuration d’appli. |
| Exposer des actions pilotables par la plateforme | Déclarer un service, implémenter et appeler. |
| Vérifier un refus, un scope ou une autorisation Twitch | Permissions par contexte. |
| Lire une variable du channel choisie par le streamer ou convertir les arguments reçus | variables.getFromPreference(path) via une préférence channelVariable, scope variables:read ; variables, arguments. |
| Lire/écrire le chat, gérer des commandes et des viewers | Chat, users, badges et emotes. |
| Diffuser une annonce, un média ou une voix | Annonces, médias, TTS ; configuration : annonces, médias. |
| Parcourir le dossier local du streamer et lire ses fichiers | kapp.localFiles ; contrat du dossier HUB. Sans adresse configurée : liste vide ou null. |
| Utiliser Twitch, sondages/prédictions ou IA | Twitch, polls, IA. |
Lire le channel, ses teams (teams.get() puis team.getChannels(), scope teams:read), le live, les statuts ou les items ; YouTube, Discord, dashboard, Streamlabs, RCON | Channel, teams et live, intégrations. |
| Adapter l’affichage, les événements et les ressources | Layout partagé, vertical et formats, overlay, DOM, events, atlas, QR code. |
| Traduire l’appli | Textset et i18n. |
| Mettre à niveau une ancienne appli | Changements, migration des stockages et exemple de migration. Migrer ensemble écritures V2 et helper V3. |
Garde-fous
Attends les méthodes qui renvoient une Promise ; les getters synchrones, l’affichage et l’inscription aux événements ne sont pas tous asynchrones. Vérifie les signatures dans app-sdk.d.ts.
Une réponse HTTP n’est pas une confirmation métier ; un timeout peut laisser le résultat incertain. Ne renvoie pas automatiquement une récompense ou une mutation. Un événement perdu ne sera pas forcément rejoué : prévoir un état récupérable si le besoin l’exige.
dataStorageV2.set() remplace la valeur complète. Les stockages V1 et V2 ne restent pas synchronisés après la copie initiale.
Avant livraison : pièges des applis, pièges partagés et recette du workflow. Pour une API absente de ce mémo, rechercher sa fiche ou consulter la référence SDK ; l’absence de fiche ne vaut pas garantie de disponibilité.