Saltar al contenido principal

Inicio rápido de Iframe

Esta es la forma más rápida de probar la API para desarrolladores sin tener que crear primero un backend.

En el modo iframe, tu aplicación se comunica con el elemento principal Chastify a través de postMessage, y Chastify llama a las API del servidor en tu nombre.

Lo que Chastify le pasa a su iframe.

Al abrirse, Chastify coloca una carga útil JSON en location.hash.
Campos importantes:

  • bridge.nonce: solicita valor de firma para mensajes de puente.
  • bridge.parentOrigin: origen de destino requerido para postMessage.
  • sessionId: ID de sesión de extensión estable para este bloqueo.
  • lockId: ID de bloqueo activo.
  • ui: valores del tema de la página principal.
  • Opcional: homeActionSlug, homeAction, intent, regularActionsSummary, mainToken.

Utilice las funciones auxiliares de apps/extension/src/lib/ChastifyBridge.ts:

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

Bootstrap minimalista de React

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

Ejemplo sin procesar postMessage (sin clase auxiliar)

Si no utiliza ChastifyBridgeClient, envíe el sobre de solicitud completo manualmente:

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

window.parent.postMessage(req, parentOrigin);

Escuche las respuestas coincidentes:

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

Flujo de prueba que debes ejecutar primero

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

Esto confirma la autenticación del puente, las lecturas seguras y el manejo de solicitudes y respuestas. Las escrituras de estado deben ser realizadas por su backend con credenciales de la API de desarrollador.

Carga de archivos desde un iframe

Si tu extensión necesita imágenes o contenido multimedia generado, usa los asistentes de archivos puente. Chastify carga los archivos al almacenamiento R2 administrado, devuelve un identificador de archivo estable y te proporciona una URL firmada de corta duración para su visualización.

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

Almacene uploaded.file.id, no la URL firmada. Las URL firmadas caducan y deben actualizarse con files.get / client.filesGet(...) cuando se vuelva a cargar el iframe.

Compatibilidad con temas (ui + themeVars)

Chastify pasa un objeto ui en el hash del iframe.
themeVars(ui) lo convierte en tokens de diseño utilizables:

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

Utilice estos valores como estilo base para su extensión, de modo que su iframe coincida con el tema del host.

Actualizaciones de temas en vivo

El padre puede enviar eventos chastify:ext:ui mientras su iframe esté abierto.
Si deseas sincronizar el tema en tiempo real, escucha ese evento y actualiza el estado local del tema.

Para obtener información detallada sobre el manejo de temas claros/oscuros, ejemplos de contraste y patrones de Tailwind, consulte Temas de Iframe.

Compatibilidad con redimensionamiento automático

Utilice startAutoResizeToParent(...) para que el elemento padre pueda redimensionar el iframe según su contenido.

Por qué esto es importante:

  • Evita que se produzcan trampas de desplazamiento dentro del iframe.
  • Mantiene el tamaño correcto de las ventanas modales de configuración y las páginas de extensión.
  • Funciona bien para secciones dinámicas que se expanden/contraen.

Errores comunes

  • Código targetOrigin incorrecto (debe coincidir con bridge.parentOrigin).
  • Falta o está obsoleto nonce.
  • No se llama a destroy() al desmontar ChastifyBridgeClient.
  • Enviar acciones no compatibles sin comprobar primero las capacidades de session.get.

Archivos de referencia

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