Aller au contenu principal

Démarrage rapide de l'iframe

C'est la méthode la plus rapide pour tester l'API développeur sans avoir à créer au préalable un backend.

En mode iframe, votre application communique avec le parent Chastify via postMessage, et Chastify appelle les API du serveur en votre nom.

Ce que Chastify transmet à votre iframe

À l'ouverture, Chastify place une charge utile JSON dans location.hash.
Champs importants :

  • bridge.nonce : valeur de signature de la demande pour les messages du pont.
  • bridge.parentOrigin : origine cible requise pour postMessage.
  • sessionId : identifiant de session d’extension stable pour ce verrou.
  • lockId : identifiant de verrouillage actif.
  • ui : valeurs du thème provenant de la page parente.
  • Facultatif : homeActionSlug, homeAction, intent, regularActionsSummary, mainToken.

Utilisez les fonctions d'assistance de apps/extension/src/lib/ChastifyBridge.ts :

  • parseHashPayload()
  • ChastifyBridgeClient
  • startAutoResizeToParent(...)
  • themeVars(...)

Bootstrap React minimal

import { useEffect, useMemo, useState } from "react";
import {
parseHashPayload,
ChastifyBridgeClient,
startAutoResizeToParent,
themeVars,
} from "../lib/ChastifyBridge";

const payload = parseHashPayload();
if (!payload?.bridge?.nonce || !payload?.bridge?.parentOrigin) {
throw new Error("Missing bridge payload in iframe hash");
}

export function App() {
const [client, setClient] = useState<ChastifyBridgeClient | null>(null);
const [session, setSession] = useState<any>(null);
const [stateDoc, setStateDoc] = useState<any>(null);
const vars = useMemo(() => themeVars(payload.ui ?? null), []);

useEffect(() => {
const c = new ChastifyBridgeClient({
nonce: payload.bridge!.nonce,
targetOrigin: payload.bridge!.parentOrigin,
});
setClient(c);
return () => c.destroy();
}, []);

useEffect(() => {
if (!client) return;
(async () => {
const s = await client.request("session.get", {});
setSession(s);

const st = await client.request("state.get", {});
setStateDoc(st);
})().catch(console.error);
}, [client]);

useEffect(() => {
return startAutoResizeToParent({
nonce: payload.bridge!.nonce,
targetOrigin: payload.bridge!.parentOrigin,
extraPx: 12,
});
}, []);

return (
<div style={{ background: vars.pageBg, color: vars.text, minHeight: "100%" }}>
<h2>Extension Quickstart</h2>
<pre>{JSON.stringify(session, null, 2)}</pre>
<pre>{JSON.stringify(stateDoc, null, 2)}</pre>
</div>
);
}

Exemple brut postMessage (sans classe d'assistance)

Si vous n'utilisez pas ChastifyBridgeClient, veuillez envoyer manuellement l'enveloppe de demande complète :

const req = {
type: "chastify:ext:req",
v: 1,
id: crypto.randomUUID(),
nonce,
action: "session.get",
payload: {},
};

window.parent.postMessage(req, parentOrigin);

Soyez attentif aux réponses correspondantes :

window.addEventListener("message", (event) => {
if (event.origin !== parentOrigin) return;
const msg = event.data;
if (!msg || msg.type !== "chastify:ext:resp" || msg.v !== 1) return;
if (msg.id !== req.id) return;

if (msg.ok) console.log("Bridge success:", msg.data);
else console.error("Bridge error:", msg.error);
});

Flux de tests à exécuter en premier

  1. session.get
  2. state.get
  3. metadata.get
  4. regularActions.get

Ceci confirme l'authentification du pont, la sécurité des lectures et la gestion des requêtes/réponses. Les écritures d'état doivent être effectuées par votre serveur avec les identifiants de l'API développeur.

Téléchargement de fichiers depuis une iframe

Si votre extension nécessite des images ou des médias générés, utilisez les assistants de fichiers de pont. Chastify télécharge le fichier vers le stockage R2 géré, renvoie un identifiant de fichier stable et vous fournit une URL signée éphémère pour le rendu.

const capabilities = await client.filesCapabilities();
if (capabilities.enabled) {
const uploaded = await client.filesUpload({
file,
filename: file.name,
purpose: "puzzle-image",
});

// Send uploaded.file.id to your backend if it should be stored in session state.

const refreshed = await client.filesGet(uploaded.file.id);
image.src = refreshed.file.signedUrl;
}

Stockez uploaded.file.id, et non l'URL signée. Les URL signées expirent et doivent être actualisées avec files.get / client.filesGet(...) lors du prochain chargement de l'iframe.

Prise en charge des thèmes (ui + themeVars)

Chastify transmet un objet ui dans le hachage de l'iframe.
themeVars(ui) le convertit en jetons de conception utilisables :

  • pageBg
  • text
  • panel
  • border
  • muted
  • inputBg

Utilisez ces valeurs comme style de base de votre extension afin que votre iframe corresponde au thème hôte.

Mises à jour en direct du thème

Le parent peut envoyer des événements chastify:ext:ui pendant que votre iframe est ouvert.
Pour une synchronisation en direct du thème, écoutez cet événement et mettez à jour l'état local du thème.

Pour une gestion détaillée des thèmes clair/sombre, des exemples de contraste et des modèles Tailwind, voir Iframe Theming.

Prise en charge du redimensionnement automatique

Utilisez startAutoResizeToParent(...) pour que le parent puisse redimensionner l'iframe en fonction de votre contenu.

Pourquoi c'est important :

  • Empêche les blocages de défilement à l'intérieur de l'iframe.
  • Permet de maintenir la taille correcte des fenêtres modales de configuration et des pages d'extension.
  • Fonctionne bien pour les sections dynamiques qui s'étendent/se réduisent.

Erreurs courantes

  • Code targetOrigin incorrect (doit correspondre à bridge.parentOrigin).
  • nonce manquant ou obsolète.
  • Ne pas appeler destroy() lors du démontage pour ChastifyBridgeClient.
  • Envoi d'actions non prises en charge sans vérification préalable des capacités session.get.

Fichiers de référence

  • apps/extension/src/lib/ChastifyBridge.ts
  • apps/extension/src/pages/MainPage.tsx
  • apps/extension/src/pages/SetupPage.tsx