Communitygithub.com

metapages/framejs.io

Compartilhe visualizações JavaScript interativas, gráficos, painéis e aplicativos em uma URL — sem servidor, build ou conta. Gere com IA ou escreva manualmente.

O que é framejs.io?

O framejs permite executar módulos JavaScript ES6 diretamente no navegador, armazenando o aplicativo em uma URL estável e compartilhável no `framejs.app/j/<uuid>`. O conteúdo pode ser atualizado dinamicamente via POST com parâmetros hash — o que o torna ideal para agentes de IA que precisam criar, modificar e iterar visualizações interativas em tempo real, sem configurar infraestrutura. A skill oferece dois modos de entrega: no modo automação, o agente usa um script Node para criar ou atualizar um frame e retorna sua URL; no modo bloco de código, o agente responde apenas com um bloco de código JavaScript que o usuário cola no editor do framejs.io. Suporta criação a partir de prompts, modificação de aplicativos existentes (com suporte a tokens de autenticação) e visualização de arquivos locais. É compatível com assistentes de código como Claude Code, Cursor, Codex, e qualquer ambiente que possa executar JavaScript no navegador.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add metapages/framejs.io

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

framejs

O framejs executa um módulo JavaScript ES6 no navegador. Um frame é o aplicativo: ele reside em uma URL estável e compartilhável framejs.app/j/<uuid> cujo conteúdo é mutável — você atualiza o aplicativo no local enviando seus parâmetros hash via POST. Seu trabalho: transformar a solicitação do usuário nesse JavaScript de navegador e entregá-lo da maneira correta para seu ambiente.

Escolha seu modo de entrega

Escolha com base no que você pode fazer — não na solicitação:

  • Modo automação — você pode executar um shell / node: gere o JavaScript, depois crie-ou-atualize o frame framejs.app da sessão, imprima sua URL /j/<uuid> e abra no navegador. Este é o padrão sempre que um shell estiver disponível.
  • Modo bloco de código — apenas chat / API, sem shell: responda apenas com um único bloco de código JavaScript delimitado (abra com uma string de informação javascript) e nada mais — sem prosa ao redor, sem arquivos, sem URLs. O usuário cola no editor em framejs.io.

Em ambos os modos, o JavaScript que você escreve segue as mesmas regras — leia references/coding-guide.md.

O que a solicitação pode ser

  1. Criar a partir de um prompt — "uma animação de bola quicando", "plotar y = sin(x)".
  2. Modificar um aplicativo existente — a solicitação contém uma URL de frame. Pode ser uma URL https://framejs.app/j/<uuid> ou https://framejs.io/j/<uuid>?token=... (a ação "Copiar frame para sessão de IA" copia o formulário de runtime do framejs.io), um ID hexadecimal de 32 caracteres puro, ou uma URL https://framejs.io/j/<sha256> / ID de 64 caracteres legada. Sempre que você vir uma URL framejs, extraia o uuid do caminho /j/<uuid> e aponte para AQUELE frame (passe a URL diretamente para --id — o helper roteia a atualização para a camada do aplicativo mesmo para URLs framejs.io). Você DEVE buscar o código existente primeiro e modificá-lo — veja references/short-url-api.md (§ Modificar). Se a URL tiver um parâmetro de consulta ?token=<key> (da ação "Copiar frame para sessão de IA" do aplicativo), passe a URL inteira para --id (ou a chave para --token): o helper a armazena e a envia como credencial bearer para que suas atualizações continuem funcionando mesmo após o proprietário do frame tê-lo reivindicado. Passar a URL inteira também aponta para o backend que a URL nomeia — então uma URL de frame de desenvolvimento ou auto-hospedado (ex: https://framejs-app.localhost:13747/j/<uuid>?token=<key>) atualiza sua própria pilha sem nenhum ambiente pré-configurado. --app-origin <url> / --io-origin <url> definem o backend explicitamente. Veja references/short-url-api.md (§ Origens locais / dev).
  3. Visualizar arquivos locais — a solicitação referencia caminhos de arquivo (./data.csv, /tmp/results.json). Envie-os e passe como entradas — veja references/file-inputs.md.

Modo automação — como entregar

Gere o código, depois use o helper empacotado (preferido) ou o fallback inline-node em references/short-url-api.md:

cat << 'JSCODE' | node scripts/framejs.mjs create --state "${SCRATCHPAD}/framejs-frame.json" --title "<título curto>" --description "<resumo de uma frase>" --screenshot
// seu JavaScript de navegador gerado aqui — $vars, crases, todos os caracteres especiais estão seguros dentro do heredoc
JSCODE

O helper imprime (na saída padrão) duas URLs — a URL da página primária https://framejs.app/j/<uuid> e uma URL de snapshot imutável snapshot: https://framejs.io/j/<sha256>. Ele também imprime (na saída de erro) um aviso de ciclo de vida do link compartilhável que você DEVE repassar ao usuário:

  • a página /j/<uuid> é editável e atualizada ao vivo, mas um frame anônimo (não reivindicado) é temporário e expirará — diga ao usuário para abri-lo e reivindicá-lo (conta gratuita) para mantê-lo permanentemente;
  • o snapshot /j/<sha256> é uma cópia imutável do aplicativo atual que expira ~30 dias após a última abertura — um bom link estável de compartilhamento/backup, mas nunca reflete edições posteriores.

Adicione --module <url> para scripts clássicos e --input nome=valor para entradas.

Um frame por sessão, atualizado no local. Sempre passe --state "<caminho em sua área de rascunho>/framejs-frame.json" (qualquer caminho de arquivo gravável). O primeiro create cunha o frame; re-execute create com o mesmo --state para ATUALIZAR o mesmo frame — a URL /j/<uuid> permanece constante e qualquer página framejs.app aberta é atualizada ao vivo, então forneça a URL ao usuário uma vez. Somente quando o usuário quiser um aplicativo separado na mesma sessão, adicione --new para iniciar um novo frame (atualizações subsequentes então apontarão para esse novo). Para atualizar um frame específico independentemente do estado, passe --id <uuid>. Em tal atualização no local, o helper carrega automaticamente os dados Open Graph existentes do frame quando você não passa --og/--title/--description, então uma reexecução simples nunca remove o título/descrição (e o og.image retido evita uma recaptura de tela redundante). Passe --title/--description novamente apenas para alterar o texto de pré-visualização.

O navegador abre automaticamente apenas na primeira vez que um frame é cunhado (--no-open para pular até isso). Uma atualização posterior para o mesmo frame — mesmo --state, ou um --id explícito — NÃO reabre o navegador: a página já aberta o alcança ao vivo através da assinatura do mesmo frame, então abrir novamente apenas criaria uma nova aba redundante.

Se um checkout de desenvolvimento local estiver presente, o helper carrega automaticamente seu .env e aponta para as pilhas de desenvolvimento (FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN) em vez da produção — nenhuma ação necessária de sua parte.

Se o helper imprimir um aviso de atualização desatualizado (na saída de erro, no máximo a cada hora), repasse-o ao usuário textualmente uma vez — a skill instalada deles está desatualizada e o aviso informa o comando para atualizá-la.

Sempre passe --screenshot: o helper renderiza o aplicativo finalizado e armazena a captura como a pré-visualização og:image. É autoprotetor — captura APENAS quando o aplicativo ainda não tem og.image, então nunca sobrescreve uma imagem que uma execução anterior (ou o usuário) já definiu, e silenciosamente cai para a URL sem imagem se nenhum renderizador estiver disponível. A captura prefere Playwright quando pode ser importado (espera de rede ociosa verdadeira — melhor para aplicativos que buscam entradas), e caso contrário usa headless Chrome do sistema. Playwright é opcional: instale-o (npm i -g playwright && npx playwright install chromium) para o caminho mais confiável, ou aponte $FRAMEJS_PLAYWRIGHT para um diretório cujo node_modules o tenha. Ajuste com --screenshot-wait <ms> (padrão 6000 — aumente para aplicativos que carregam lentamente) e --screenshot-size <w,h> (padrão 1200,630). Substitua o binário do Chrome com $CHROME_PATH.

scripts/framejs.mjs é resolvido relativo ao diretório desta skill, não ao seu diretório de trabalho atual — execute-o da pasta da skill, ou use seu caminho absoluto (Claude Code expõe esse diretório como ${CLAUDE_SKILL_DIR}, então ${CLAUDE_SKILL_DIR}/scripts/framejs.mjs sempre funciona). Se você não conseguir localizar ou executar o helper empacotado, use o fallback inline-node em references/short-url-api.md — ele não precisa de arquivo de script.

Sempre inclua tags de pré-visualização Open Graph para que o link seja exibido corretamente ao ser compartilhado — veja as regras OG em references/short-url-api.md:

  • Novo aplicativo: derive texto novo com --title / --description, e passe --screenshot para capturar a imagem de pré-visualização.
  • Modificando um aplicativo existente: o aplicativo buscado já carrega og (o comando fetch o retorna). NÃO recalcule — passe o objeto buscado de volta diretamente com --og '<o JSON og buscado>', que preserva todos os campos (incluindo image). Atualize o MESMO frame com --id <uuid> (ou o mesmo --state). Defina novos --title/--description apenas se o usuário pediu explicitamente para alterar o texto de pré-visualização. Você ainda pode passar --screenshot: se o og buscado já tiver uma image, ela é deixada intacta; se não tiver nenhuma, uma nova captura é adicionada.

Regras absolutas (ambos os modos)

  • JavaScript de navegador apenas — ele executa em um iframe, NÃO Node.js.
  • DEVE usar sintaxe de módulo ES6: export function onInputs(inputs) {}.
  • NUNCA crie arquivos HTML. NUNCA escreva arquivos .js locais. NUNCA use suas próprias ferramentas de visualização/renderização/widget para renderizar o resultado.
  • NUNCA modifique root.style.position, root.style.height ou root.style.width.
  • IMPORTANTE: a visualização DEVE ter boa aparência em dispositivos móveis e se adaptar ao tamanho da tela — use dimensionamento responsivo (leia as dimensões de root / escute redimensionamento), evite larguras fixas em pixels que transbordem, mantenha texto e alvos de toque legíveis em telas pequenas.
  • No modo automação, NUNCA produza um bloco de código para o usuário copiar e NUNCA construa manualmente uma URL hash longa como resultado — sempre POST através da API de frame (o create do helper). Dê ao usuário a URL da página /j/<uuid>.
  • No modo bloco de código, produza APENAS o bloco de código JavaScript delimitado — nada mais.

Referências

  • references/coding-guide.md — globais, exportações, padrões, bibliotecas CDN, erros comuns.
  • references/short-url-api.md — criar/atualizar um frame (POST /j/<uuid>.json), estado de um frame por sessão, tags Open Graph, tokens de API (continuar atualizando após um frame ser reivindicado), fallbacks inline.
  • references/file-inputs.md — enviar arquivos locais e conectá-los como entradas.
  • scripts/framejs.mjs — helper Node: create (stdin JS → frame framejs.app), fetch <id>, upload <caminho>. Origens: FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN (carregado automaticamente de um .env próximo em desenvolvimento local), ou por execução via --app-origin/--io-origin ou a origem de uma URL de frame completa passada para --id/fetch.

Habilidades Relacionadas