Communitygithub.com

metapages/framejs.io

Comparte visualizaciones interactivas de JavaScript, gráficos, dashboards y aplicaciones en una URL, sin servidor, compilación ni cuenta. Genéralas con IA o escríbelas a mano.

¿Qué es framejs.io?

Este skill permite a un agente de IA (como Claude Code, Cursor o Codex) crear, modificar y compartir aplicaciones basadas en navegador escritas en JavaScript (módulos ES6) a través de URLs estables y editables en framejs.app. El agente puede generar visualizaciones, gráficos, dashboards o aplicaciones completas a partir de descripciones en lenguaje natural, actualizar aplicaciones existentes modificando su código en el lugar, o visualizar archivos locales del usuario subiéndolos como entradas. Soporta dos modos de entrega: modo automatización (cuando hay acceso a shell/Node), donde el agente genera el JS, lo envía a la API de framejs para crear o actualizar un frame, y devuelve su URL; y modo bloque de código (solo chat/API), donde responde únicamente con un bloque de código JavaScript que el usuario pega en el editor de framejs.io. El skill incluye un helper Node.js (scripts/framejs.mjs) que maneja la creación, actualización, captura de pantalla y metadatos Open Graph, y gestiona el estado sesión-por-sesión para mantener la misma URL del frame en actualizaciones posteriores.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add metapages/framejs.io

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

framejs

framejs ejecuta un módulo de JavaScript ES6 en el navegador. Un frame es la aplicación: vive en una URL estable y compartible framejs.app/j/<uuid> cuyo contenido es mutable — actualizas la aplicación en el lugar enviando sus parámetros hash mediante POST. Tu trabajo: convertir la petición del usuario en ese JavaScript de navegador y entregarlo de la manera correcta para tu entorno.

Elige tu modo de entrega

Elige basándote en lo que puedes hacer, no en la petición:

  • Modo automatización — puedes ejecutar un shell / node: genera el JavaScript, luego crea o actualiza el frame de framejs.app de la sesión, imprime su URL /j/<uuid> y ábrela en el navegador. Este es el valor predeterminado siempre que haya un shell disponible.
  • Modo bloque de código — solo chat / API, sin shell: responde solo con un único bloque de código JavaScript delimitado (ábrelo con una cadena de información javascript) y nada más — sin prosa adicional, sin archivos, sin URLs. El usuario lo pega en el editor de framejs.io.

En ambos modos, el JavaScript que escribes sigue las mismas reglas: lee references/coding-guide.md.

Cómo puede ser la petición

  1. Crear desde un prompt — "una animación de una pelota que rebota", "grafica y = sin(x)".
  2. Modificar una aplicación existente — la petición contiene una URL de frame. Puede ser una URL https://framejs.app/j/<uuid> o una URL https://framejs.io/j/<uuid>?token=... (la acción "Copiar frame para sesión de IA" copia el formulario de runtime de framejs.io), un id hexadecimal de 32 caracteres simple, o un id de instantánea heredado https://framejs.io/j/<sha256> / de 64 caracteres. Siempre que veas una URL de framejs, extrae el uuid de su ruta /j/<uuid> y apunta a ESE frame (pasa la URL directamente a --id — el helper dirige la actualización a la capa de la aplicación incluso para una URL de framejs.io). DEBES obtener primero el código existente y modificarlo — consulta references/short-url-api.md (§ Modificar). Si la URL lleva un parámetro de consulta ?token=<key> (de la acción "Copiar frame para sesión de IA" de la aplicación), pasa la URL completa a --id (o la clave a --token): el helper la almacena y la envía como credencial Bearer para que tus actualizaciones sigan funcionando incluso después de que el propietario haya reclamado el frame. Pasar la URL completa también apunta al backend que la URL nombra — así que una URL de frame de desarrollo o auto-alojado (ej. https://framejs-app.localhost:13747/j/<uuid>?token=<key>) actualiza su propia pila sin necesidad de configurar un entorno. --app-origin <url> / --io-origin <url> establecen el backend explícitamente. Consulta references/short-url-api.md (§ Orígenes locales / de desarrollo).
  3. Visualizar archivos locales — la petición hace referencia a rutas de archivo (./data.csv, /tmp/results.json). Súbelos y pásalos como entradas — consulta references/file-inputs.md.

Modo automatización — cómo entregar

Genera el código, luego usa el helper incluido (preferido) o el reemplazo inline-node en references/short-url-api.md:

cat << 'JSCODE' | node scripts/framejs.mjs create --state "${SCRATCHPAD}/framejs-frame.json" --title "<título corto>" --description "<resumen de una oración>" --screenshot
// tu JS de navegador generado aquí — $vars, backticks, todos los caracteres especiales están seguros dentro del heredoc
JSCODE

El helper imprime (en stdout) dos URLs — la URL de página principal https://framejs.app/j/<uuid> y una URL de instantánea inmutable snapshot: https://framejs.io/j/<sha256>. También imprime (en stderr) un aviso de ciclo de vida del enlace compartido que DEBES transmitir al usuario:

  • la página /j/<uuid> es editable y se actualiza en vivo, pero un frame anónimo (no reclamado) es temporal y expirará — dile al usuario que la abra y la reclame (cuenta gratuita) para mantenerla permanentemente;
  • la instantánea /j/<sha256> es una copia inmutable de la aplicación actual que expira ~30 días después de su última apertura — un buen enlace de respaldo/compartición estable, pero nunca refleja ediciones posteriores.

Añade --module <url> para scripts clásicos y --input name=value para entradas.

Un frame por sesión, actualizado en el lugar. Pasa siempre --state "<ruta en tu bloc de notas>/framejs-frame.json" (cualquier ruta de archivo escribible). El primer create acuña el frame; vuelve a ejecutar create con el mismo --state para ACTUALIZAR el mismo frame — la URL /j/<uuid> permanece constante y cualquier página abierta de framejs.app se actualiza en vivo, así que entrega la URL al usuario una sola vez. Solo cuando el usuario quiera una aplicación separada en la misma sesión, añade --new para iniciar un frame nuevo (las actualizaciones posteriores apuntarán a ese nuevo). Para actualizar un frame específico independientemente del estado, pasa --id <uuid>. En una actualización en el lugar, el helper traslada automáticamente los metadatos Open Graph existentes del frame cuando no pasas --og/--title/--description, así que una re-ejecución simple nunca elimina el título/descripción (y la og.image retenida evita una captura de pantalla redundante). Pasa --title/--description de nuevo solo para cambiar el texto de vista previa.

El navegador se abre automáticamente solo la primera vez que se acuña un frame (--no-open para omitir incluso eso). Una actualización posterior al mismo frame — mismo --state, o un --id explícito — NO reabre el navegador: la página ya abierta lo alcanza en vivo a través de la suscripción al mismo frame, así que volver a abrirlo solo generaría una pestaña redundante nueva.

Si hay un checkout de desarrollo local presente, el helper carga automáticamente su .env y apunta a las pilas de desarrollo (FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN) en lugar de producción — no se requiere acción de tu parte.

Si el helper imprime un aviso de actualización out of date (en stderr, como máximo cada hora), transmítelo al usuario textualmente una vez — su skill instalado está desactualizado y el aviso le indica el comando para actualizarlo.

Pasa siempre --screenshot: el helper renderiza la aplicación terminada y almacena la captura como vista previa og:image. Se autoprotege — captura SOLO cuando la aplicación aún no tiene og.image, por lo que nunca sobrescribe una imagen que una ejecución anterior (o el usuario) ya haya establecido, y falla silenciosamente a la URL sin imagen si no hay renderizador disponible. La captura prefiere Playwright cuando se puede importar (espera de red inactiva real — mejor para aplicaciones que obtienen entradas) y, de lo contrario, usa Chrome headless del sistema. Playwright es opcional: instálalo (npm i -g playwright && npx playwright install chromium) para la ruta más confiable, o apunta $FRAMEJS_PLAYWRIGHT a un directorio cuyo node_modules lo tenga. Ajusta con --screenshot-wait <ms> (predeterminado 6000 — auméntalo para aplicaciones que cargan lentamente) y --screenshot-size <w,h> (predeterminado 1200,630). Sobrescribe el binario de Chrome con $CHROME_PATH.

scripts/framejs.mjs se resuelve relativo al directorio de este skill, no a tu directorio de trabajo actual — ejecútalo desde la carpeta del skill, o usa su ruta absoluta (Claude Code expone ese directorio como ${CLAUDE_SKILL_DIR}, así que ${CLAUDE_SKILL_DIR}/scripts/framejs.mjs siempre funciona). Si no puedes localizar o ejecutar el helper incluido, usa el reemplazo inline-node en references/short-url-api.md — no necesita archivo de script.

Incluye siempre etiquetas de vista previa Open Graph para que el enlace se despliegue bien al compartirse — consulta las reglas OG en references/short-url-api.md:

  • Aplicación nueva: deriva texto nuevo con --title / --description, y pasa --screenshot para capturar la imagen de vista previa.
  • Modificar una aplicación existente: la aplicación obtenida ya lleva og (el comando fetch lo devuelve). NO lo recalcules — pasa el objeto obtenido directamente de vuelta con --og '<el JSON og obtenido>', lo que preserva cada campo (incluyendo image). Actualiza el MISMO frame con --id <uuid> (o el mismo --state). Solo establece un nuevo --title/--description si el usuario pidió explícitamente cambiar el texto de vista previa. Aún puedes pasar --screenshot: si el og obtenido ya tiene una image, se deja intacta; si no tiene ninguna, se añade una captura nueva.

Reglas absolutas (ambos modos)

  • Solo JavaScript de navegador — se ejecuta en un iframe, NO en Node.js.
  • DEBE usar sintaxis de módulo ES6: export function onInputs(inputs) {}.
  • NUNCA crees archivos HTML. NUNCA escribas archivos .js locales. NUNCA uses tus propias herramientas de visualización/renderización/widgets para renderizar el resultado.
  • NUNCA modifiques root.style.position, root.style.height o root.style.width.
  • IMPORTANTE: la visualización DEBE verse bien en móvil y adaptarse a ese tamaño de pantalla — usa dimensionamiento responsivo (lee las dimensiones de root / escucha cambios de tamaño), evita anchos fijos en píxeles que se desborden, mantén el texto y los objetivos táctiles legibles en pantallas pequeñas.
  • En modo automatización, NUNCA generes un bloque de código para que el usuario copie y NUNCA construyas manualmente una URL hash larga como entregable — siempre haz POST a través de la API de frame (el create del helper). Dale al usuario la URL de página /j/<uuid>.
  • En modo bloque de código, genera SOLO el único bloque de código JavaScript delimitado — nada más.

Referencias

  • references/coding-guide.md — globales, exportaciones, patrones, librerías CDN, errores comunes.
  • references/short-url-api.md — crear/actualizar un frame (POST /j/<uuid>.json), estado un-frame-por-sesión, etiquetas Open Graph, tokens API (seguir actualizando después de que un frame sea reclamado), reemplazos inline.
  • references/file-inputs.md — subir archivos locales y conectarlos como entradas.
  • scripts/framejs.mjs — helper de Node: create (stdin JS → frame de framejs.app), fetch <id>, upload <path>. Orígenes: FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN (cargado automáticamente desde un .env cercano en desarrollo local), o por ejecución mediante --app-origin/--io-origin o el origen de una URL de frame completa pasada a --id/fetch.

Skills relacionados