Passa al contenuto principale

Guida rapida all'iframe

Questo è il modo più veloce per provare l'API per sviluppatori senza dover prima creare un backend.

In modalità iframe, la tua app comunica con il genitore Chastify tramite postMessage, e Chastify chiama le API del server per tuo conto.

Cosa trasmette Chastify al tuo iframe

All'apertura, Chastify inserisce un payload JSON in location.hash.
Campi importanti:

  • bridge.nonce: valore di firma della richiesta per i messaggi del bridge.
  • bridge.parentOrigin: origine di destinazione richiesta per postMessage.
  • sessionId: ID di sessione di estensione stabile per questo blocco.
  • lockId: ID del blocco attivo.
  • ui: valori del tema dalla pagina principale.
  • Opzionale: homeActionSlug, homeAction, intent, regularActionsSummary, mainToken.

Utilizzare le funzioni di supporto da apps/extension/src/lib/ChastifyBridge.ts:

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

Bootstrap React minimale

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>
);
}

Esempio di postMessage grezzo (senza classe di supporto)

Se non si utilizza ChastifyBridgeClient, inviare manualmente l'intera busta di richiesta:

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

window.parent.postMessage(req, parentOrigin);

Ascolta le risposte corrispondenti:

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);
});

Flusso di test da eseguire per primo

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

Ciò conferma l'autenticazione del bridge, le letture sicure e la gestione delle richieste/risposte. Le scritture di stato devono essere eseguite dal backend con le credenziali dell'API per sviluppatori.

Caricamento file tramite iframe

Se la tua estensione necessita di immagini o contenuti multimediali generati, utilizza gli helper per i file bridge. Chastify carica i file nello storage R2 gestito, restituisce un ID file stabile e fornisce un URL firmato di breve durata per il rendering.

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;
}

Memorizza uploaded.file.id, non l'URL firmato. Gli URL firmati scadono e devono essere aggiornati con files.get / client.filesGet(...) al successivo caricamento dell'iframe.

Supporto per il tema (ui + ZZQCODE1ZXQ)

Chastify passa un oggetto ui nell'hash dell'iframe.
themeVars(ui) lo converte in token di progettazione utilizzabili:

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

Utilizza questi valori come stile di base per la tua estensione, in modo che l'iframe si adatti al tema host.

Aggiornamenti del tema in tempo reale

Il genitore può inviare eventi chastify:ext:ui mentre il tuo iframe è aperto.
Se desideri la sincronizzazione del tema in tempo reale, mettiti in ascolto di quell'evento e aggiorna lo stato locale del tema.

Per informazioni dettagliate sulla gestione dei temi chiaro/scuro, esempi di contrasto e modelli Tailwind, consultare Temi Iframe.

Supporto per il ridimensionamento automatico

Utilizza startAutoResizeToParent(...) in modo che l'elemento padre possa ridimensionare l'iframe in base al tuo contenuto.

Perché è importante:

  • Previene le trappole di scorrimento all'interno dell'iframe.
  • Mantiene le dimensioni corrette delle finestre modali di configurazione e delle pagine delle estensioni.
  • Funziona bene per sezioni dinamiche che si espandono/si comprimono.

Errori comuni

  • Codice targetOrigin errato (deve corrispondere a bridge.parentOrigin).
  • Codice nonce mancante o obsoleto.
  • Non viene chiamata la funzione destroy() durante lo smontaggio di ChastifyBridgeClient.
  • Invio di azioni non supportate senza prima verificare le funzionalità di session.get.

File di riferimento

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