framejs
framejs exécute un module JavaScript ES6 dans le navigateur. Une frame est l'application : elle vit à une URL stable et partageable framejs.app/j/<uuid> dont le contenu est mutable — vous mettez à jour l'application sur place en POSTant ses paramètres de hachage. Votre travail : transformer la demande de l'utilisateur en ce JavaScript navigateur et le délivrer de la bonne manière pour votre environnement.
Choisissez votre mode de livraison
Choisissez en fonction de ce que vous pouvez faire — pas en fonction de la demande :
- Mode automatisation — vous pouvez exécuter un shell /
node: générez le JavaScript, puis créez ou mettez à jour la frame framejs.app de la session, affichez son URL/j/<uuid>et ouvrez-la dans le navigateur. C'est le comportement par défaut lorsqu'un shell est disponible. - Mode bloc de code — chat / API uniquement, pas de shell : répondez uniquement avec un seul bloc de code JavaScript délimité (ouvrez-le avec une chaîne d'information
javascript) et rien d'autre — pas de prose environnante, pas de fichiers, pas d'URL. L'utilisateur le colle dans l'éditeur sur framejs.io.
Dans les deux modes, le JavaScript que vous écrivez suit les mêmes règles — lisez references/coding-guide.md.
Ce que peut être la demande
- Créer à partir d'une invite — "une animation de balle rebondissante", "tracer y = sin(x)".
- Modifier une application existante — la demande contient une URL de frame. Il peut s'agir d'une URL
https://framejs.app/j/<uuid>ouhttps://framejs.io/j/<uuid>?token=…(l'action "Copier la frame pour session IA" copie le formulaire d'exécution framejs.io), d'un identifiant hexadécimal brut de 32 caractères, ou d'une URL héritéehttps://framejs.io/j/<sha256>/ identifiant de 64 caractères. Chaque fois que vous voyez une URL framejs, extrayez l'uuid de son chemin/j/<uuid>et ciblez CETTE frame (passez l'URL directement à--id— le helper route la mise à jour vers la couche application même pour une URL framejs.io). Vous DEVEZ d'abord récupérer le code existant et le modifier — voir references/short-url-api.md (§ Modifier). Si l'URL porte un paramètre de requête?token=<key>(de l'action "Copier la frame pour session IA" de l'application), passez l'URL entière à--id(ou la clé à--token) : le helper la stocke et l'envoie comme identifiant bearer afin que vos mises à jour continuent de fonctionner même après que le propriétaire de la frame l'a réclamée. Passer l'URL entière cible également le backend nommé par l'URL — donc une URL de frame de développement ou auto-hébergée (par exemplehttps://framejs-app.localhost:13747/j/<uuid>?token=<key>) met à jour sa propre pile sans environnement préconfiguré.--app-origin <url>/--io-origin <url>définissent explicitement le backend. Voir references/short-url-api.md (§ Origines locales / de développement). - Visualiser des fichiers locaux — la demande fait référence à des chemins de fichiers (
./data.csv,/tmp/results.json). Téléchargez-les et passez-les comme entrées — voir references/file-inputs.md.
Mode automatisation — comment délivrer
Générez le code, puis utilisez le helper fourni (recommandé) ou la solution de repli inline-node dans references/short-url-api.md :
cat << 'JSCODE' | node scripts/framejs.mjs create --state "${SCRATCHPAD}/framejs-frame.json" --title "<titre court>" --description "<résumé en une phrase>" --screenshot
// votre code JavaScript généré ici — $vars, backticks, tous les caractères spéciaux sont sûrs à l'intérieur du heredoc
JSCODE
Le helper affiche (sur stdout) deux URL — l'URL de la page principale https://framejs.app/j/<uuid> et une URL snapshot: immuable https://framejs.io/j/<sha256>. Il affiche également (sur stderr) un avis de cycle de vie du lien de partage que vous DEVEZ transmettre à l'utilisateur :
- la page
/j/<uuid>est modifiable et se met à jour en direct, mais une frame anonyme (non réclamée) est temporaire et expirera — dites à l'utilisateur de l'ouvrir et de la réclamer (compte gratuit) pour la conserver définitivement ; - l'instantané
/j/<sha256>est une copie immuable de l'application actuelle qui expire environ 30 jours après sa dernière ouverture — un bon lien de partage/sauvegarde stable, mais il ne reflète jamais les modifications ultérieures.
Ajoutez --module <url> pour les scripts classiques et --input nom=valeur pour les entrées.
Une frame par session, mise à jour sur place. Passez toujours --state "<chemin dans votre bloc-notes>/framejs-frame.json" (n'importe quel chemin de fichier inscriptible). Le premier create crée la frame ; ré-exécutez create avec le même --state pour METTRE À JOUR la même frame — l'URL /j/<uuid> reste constante et toute page framejs.app ouverte se met à jour en direct, donc donnez l'URL à l'utilisateur une seule fois. Uniquement lorsque l'utilisateur souhaite une application séparée dans la même session, ajoutez --new pour démarrer une nouvelle frame (les mises à jour ultérieures ciblent alors cette nouvelle). Pour mettre à jour une frame spécifique indépendamment de l'état, passez --id <uuid>. Lors d'une telle mise à jour sur place, le helper reporte automatiquement les données Open Graph existantes de la frame lorsque vous ne passez pas --og/--title/--description, donc une simple ré-exécution ne supprime jamais le titre/la description (et l'og.image conservé évite une nouvelle capture d'écran redondante). Ne repassez --title/--description que pour changer le texte de l'aperçu.
Le navigateur ne s'ouvre automatiquement que la première fois qu'une frame est créée (--no-open pour sauter même cela). Une mise à jour ultérieure de la même frame — même --state, ou un --id explicite — NE rouvre PAS le navigateur : la page déjà ouverte la reçoit en direct via l'abonnement à la même frame, donc une réouverture ne ferait que créer un nouvel onglet redondant.
Si un checkout de développement local est présent, le helper charge automatiquement son .env et cible les piles de développement (FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN) au lieu de la production — aucune action requise de votre part.
Si le helper affiche un avis de mise à jour obsolète (sur stderr, au maximum toutes les heures), transmettez-le textuellement à l'utilisateur une fois — son skill installé est en retard sur la dernière version et l'avis lui indique la commande pour le mettre à jour.
Passez toujours --screenshot : le helper rend l'application terminée et stocke la capture comme aperçu og:image. Il est auto-protégé — il ne capture QUE lorsque l'application n'a pas encore d'og.image, donc il n'écrase jamais une image déjà définie par une exécution précédente (ou par l'utilisateur), et il revient silencieusement à l'URL sans image si aucun rendu n'est disponible. La capture préfère Playwright lorsqu'il peut être importé (attente réseau-idle réelle — idéal pour les applications qui récupèrent des entrées), et utilise sinon Chrome headless système. Playwright est optionnel : installez-le (npm i -g playwright && npx playwright install chromium) pour le chemin le plus fiable, ou pointez $FRAMEJS_PLAYWRIGHT vers un répertoire dont node_modules le contient. Ajustez avec --screenshot-wait <ms> (par défaut 6000 — augmentez pour les applications qui chargent lentement) et --screenshot-size <w,h> (par défaut 1200,630). Remplacez le binaire Chrome avec $CHROME_PATH.
scripts/framejs.mjs est résolu par rapport au répertoire de ce skill, pas votre répertoire de travail actuel — exécutez-le depuis le dossier du skill, ou utilisez son chemin absolu (Claude Code expose ce répertoire comme ${CLAUDE_SKILL_DIR}, donc ${CLAUDE_SKILL_DIR}/scripts/framejs.mjs fonctionne toujours). Si vous ne pouvez pas localiser ou exécuter le helper fourni, utilisez la solution de repli inline-node dans references/short-url-api.md — elle n'a besoin d'aucun fichier de script.
Incluez toujours les balises d'aperçu Open Graph pour que le lien se déploie agréablement lors du partage — voir les règles OG dans references/short-url-api.md :
- Nouvelle application : dérivez une nouvelle copie avec
--title/--description, et passez--screenshotpour capturer l'image d'aperçu. - Modification d'une application existante : l'application récupérée porte déjà
og(la commandefetchle retourne). Ne le recalculez PAS — repassez l'objet récupéré directement avec--og '<le JSON og récupéré>', ce qui préserve tous les champs (y comprisimage). Mettez à jour la MÊME frame avec--id <uuid>(ou le même--state). Ne définissez un nouveau--title/--descriptionque si l'utilisateur a explicitement demandé de changer le texte de l'aperçu. Vous pouvez toujours passer--screenshot: si l'ogrécupéré a déjà uneimage, elle est laissée intacte ; s'il n'en a pas, une nouvelle capture est ajoutée.
Règles absolues (les deux modes)
- JavaScript navigateur uniquement — il s'exécute dans une iframe, PAS Node.js.
- DOIT utiliser la syntaxe de module ES6 :
export function onInputs(inputs) {}. - NE JAMAIS créer de fichiers HTML. NE JAMAIS écrire de fichiers
.jslocaux. NE JAMAIS utiliser vos propres outils de visualisation/rendu/widget pour afficher le résultat. - NE JAMAIS modifier
root.style.position,root.style.heightouroot.style.width. - IMPORTANT : la visualisation DOIT être belle sur mobile et s'adapter à cette taille d'écran — utilisez un dimensionnement réactif (lisez les dimensions de
root/ écoutez le redimensionnement), évitez les largeurs de pixels fixes qui débordent, gardez le texte et les cibles tactiles lisibles sur les petits écrans. - En mode automatisation, NE JAMAIS produire de bloc de code pour que l'utilisateur le copie et NE JAMAIS construire manuellement une longue URL de hachage comme livrable — passez toujours par l'API de frame (le
createdu helper). Donnez à l'utilisateur l'URL de la page/j/<uuid>. - En mode bloc de code, produisez UNIQUEMENT le seul bloc de code JavaScript délimité — rien d'autre.
Références
- references/coding-guide.md — globales, exports, motifs, bibliothèques CDN, erreurs courantes.
- references/short-url-api.md — créer/mettre à jour une frame (
POST /j/<uuid>.json), état une-frame-par-session, balises Open Graph, jetons API (continuer les mises à jour après qu'une frame est réclamée), solutions de repli inline. - references/file-inputs.md — télécharger des fichiers locaux et les connecter comme entrées.
scripts/framejs.mjs— helper Node :create(stdin JS → frame framejs.app),fetch <id>,upload <path>. Origines :FRAMEJS_APP_ORIGIN/FRAMEJS_IO_ORIGIN(chargé automatiquement depuis un.envvoisin en développement local), ou par exécution via--app-origin/--io-originou l'origine d'une URL de frame complète passée à--id/fetch.