Communitygithub.com

metapages/framejs.io

在一個 URL 中分享互動式 JavaScript 視覺化圖表、儀表板和應用程式 — 無需伺服器、建置或帳號。可用 AI 生成或手動撰寫。

framejs.io 是什麼?

framejs 是一個能讓開發者與 AI 代理直接在瀏覽器中執行 ES6 JavaScript 模組的獨特工具。每個「frame」應用程式都存放在一個穩定、可分享的 `framejs.app/j/<uuid>` URL 中,其內容是可變的 — 你可以透過 POST 其雜湊參數來原地更新應用程式。這項技能支援兩種交付模式:自動化模式(當代理可執行 shell/Node 時)會生成 JavaScript、建立或更新 frame,然後輸出 URL 並在瀏覽器中打開;而純程式碼區塊模式則僅輸出一個可直接貼到 framejs.io 編輯器的 JavaScript 程式碼區塊。它相容於 Claude Code、Coder、Cursor、Codex 等平台,並能處理從提示詞建立、修改現有應用程式(包括從已聲明的 frame 載入現有程式碼),以及上傳本機 CSV/JSON 檔案作為輸入等三種請求類型。其主要優勢在於無需任何伺服器、建置流程或帳號即可快速迭代和分享互動式視覺化成果,讓 AI 代理能直接交付可立即使用的互動式內容。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add metapages/framejs.io

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

framejs

framejs 在瀏覽器中執行 ES6 JavaScript 模組。一個 frame 就是一個應用程式:它位於一個穩定、可分享的 framejs.app/j/<uuid> URL,其內容是可變的 — 你可以透過 POST 其雜湊參數來原地更新應用程式。你的任務是:將使用者的請求轉換成該瀏覽器 JavaScript,並以適合你環境的正確方式交付。

選擇你的交付模式

根據你能做什麼來選擇 — 而不是根據請求:

  • 自動化模式 — 你可以執行 shell / node: 生成 JavaScript,然後建立或更新該 session 的 framejs.app frame,印出它的 /j/<uuid> URL,並在瀏覽器中打開。每當有 shell 可用時,這是預設模式。
  • 程式碼區塊模式 — 僅限聊天 / API,沒有 shell: 僅回覆一個被圍欄的 JavaScript 程式碼區塊(使用 javascript 資訊字串開啟),沒有其他內容 — 無前後文,無檔案,無 URL。使用者將其貼到 framejs.io 的編輯器中。

兩種模式中你撰寫的 JavaScript 遵循相同的規則 — 請閱讀 references/coding-guide.md。

請求的類型

  1. 從提示詞建立 — 「一個彈跳球動畫」、「繪製 y = sin(x)」。
  2. 修改現有應用程式 — 請求包含一個 frame URL。它可能是 https://framejs.app/j/<uuid> 或者 一個 https://framejs.io/j/<uuid>?token=… URL(「複製 frame 供 AI 使用」動作會複製 framejs.io 執行時期表單)、一個裸的 32 字元十六進位 ID,或是舊式的 https://framejs.io/j/<sha256> / 64 字元 ID 快照。每當你看到一個 framejs URL,從其 /j/<uuid> 路徑中提取 uuid,並鎖定該 frame(將 URL 直接傳給 --id — 即使對於 framejs.io URL,輔助工具也會將更新路由到應用層)。你必須先擷取現有程式碼再修改 — 請見 references/short-url-api.md(§ 修改)。如果該 URL 帶有來自應用程式「複製 frame 供 AI 使用」動作的 ?token=<key> 查詢參數,請將整個 URL 傳給 --id(或將 key 傳給 --token):輔助工具會儲存它,並將其作為 bearer 憑證發送,這樣即使在 frame 的擁有者已聲明它之後,你的更新仍能繼續運作。傳遞完整 URL 也會鎖定該 URL 命名的後端 — 因此一個開發或自架 frame URL(例如 https://framejs-app.localhost:13747/j/<uuid>?token=<key>)會更新其自己的堆疊,無需預先配置任何環境變數。使用 --app-origin <url> / --io-origin <url> 明確設定後端。請見 references/short-url-api.md(§ 本機/開發來源)。
  3. 將本機檔案視覺化 — 請求引用了檔案路徑(./data.csv、/tmp/results.json)。上傳它們並作為輸入傳遞 — 請見 references/file-inputs.md。

自動化模式 — 如何交付

生成程式碼,然後使用捆綁的輔助工具(首選)或 references/short-url-api.md 中的 inline-node 備用方案:

cat << 'JSCODE' | node scripts/framejs.mjs create --state "${SCRATCHPAD}/framejs-frame.json" --title "<短標題>" --description "<一句話摘要>" --screenshot
// 你生成的瀏覽器 JS 在這裡 — $vars、反引號、所有特殊字元在 heredoc 內部都是安全的
JSCODE

輔助工具會在 stdout 上印出兩個 URL — 主要的 https://framejs.app/j/<uuid> 頁面 URL,以及一個不可變的 snapshot: https://framejs.io/j/<sha256> URL。它還會在 stderr 上印出一個你必須轉達給使用者的分享連結生命週期通知:

  • /j/<uuid> 頁面 是可編輯且即時更新的,但一個匿名(未聲明)的 frame 是暫時的,將會過期 — 告訴使用者打開它並聲明它(免費帳戶)以永久保留;
  • /j/<sha256> 快照 是目前應用程式的不可變副本,在最後一次被打開後約 30 天過期 — 這是一個穩定的分享/備份連結,但它永遠不會反映後續的編輯。

對於經典 script 加上 --module <url>,對於輸入加上 --input name=value。

每個 session 一個 frame,原地更新。 總是傳遞 --state "<你的 scratchpad 路徑>/framejs-frame.json"(任何可寫入的檔案路徑)。第一次 create 會鑄造 frame;使用相同的 --state 重新執行 create 會更新同一個 frame — /j/<uuid> URL 保持不變,任何已打開的 framejs.app 頁面都會即時更新,所以只需給使用者一次 URL。僅當使用者想在同一個 session 中有一個分開的應用程式時,才加上 --new 來啟動一個新的 frame(後續的更新將鎖定這個新 frame)。要更新一個特定的 frame(不論 state 為何),請傳遞 --id <uuid>。在這種原地更新中,當你沒有傳遞 --og/--title/--description 時,輔助工具會自動保留 frame 現有的 Open Graph 資料,因此一個裸的重新執行永遠不會丟失標題/描述(而保留的 og.image 則跳過多餘的重新截圖)。僅當你想變更預覽文案時才再次傳遞 --title/--description。

瀏覽器僅在 frame 首次被鑄造時自動打開(加上 --no-open 可連這也跳過)。後續對同一個 frame 的更新 — 相同的 --state,或明確的 --id — 不會重新打開瀏覽器:已打開的頁面透過同一個 frame 的訂閱即時獲取更新,再次打開只會產生一個多餘的新分頁。

如果存在本機開發 checkout,輔助工具會自動載入其 .env 並鎖定開發堆疊(FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN)而非生產環境 — 你無需採取任何行動。

如果輔助工具印出了一個 out of date 更新通知(在 stderr 上,最多每小時一次),請逐字轉達給使用者一次 — 他們安裝的技能已落後於最新版本,通知中會告訴他們更新所需的命令。

總是傳遞 --screenshot:輔助工具會渲染完成的應用程式,並將擷取畫面儲存為 og:image 預覽。它具有自我保護機制 — 僅在應用程式還沒有 og.image 時才擷取,因此絕不會覆蓋先前執行(或使用者)已設定的圖片,並且如果沒有可用的渲染器,它會靜默地回退到不含圖片的 URL。擷取偏好使用 Playwright(當可匯入時 — 真正的 network-idle 等待 — 最適合會擷取輸入的應用程式),否則使用系統無頭 Chrome。Playwright 是可選的:安裝它(npm i -g playwright && npx playwright install chromium)以獲得更可靠的路徑,或將 $FRAMEJS_PLAYWRIGHT 指向一個其 node_modules 中有它的目錄。使用 --screenshot-wait <ms>(預設 6000 — 對於載入緩慢的應用程式請調高)和 --screenshot-size <w,h>(預設 1200,630)進行調整。使用 $CHROME_PATH 覆蓋 Chrome 二進位檔。

scripts/framejs.mjs 是相對於此技能的目錄解析的,而非你當前的 working directory — 從技能資料夾執行它,或使用其絕對路徑(Claude Code 將該目錄暴露為 ${CLAUDE_SKILL_DIR},因此 ${CLAUDE_SKILL_DIR}/scripts/framejs.mjs 永遠有效)。如果你無法找到或執行捆綁的輔助工具,請使用 references/short-url-api.md 中的 inline-node 備用方案 — 它不需要任何 script 檔案。

總是包含 Open Graph 預覽標籤,以便連結在分享時能漂亮地展開 — 請見 references/short-url-api.md 中的 OG 規則:

  • 新應用程式: 使用 --title / --description 衍生新的文案,並傳遞 --screenshot 來擷取預覽圖片。
  • 修改現有應用程式: 擷取的應用程式已帶有 og(fetch 命令會回傳它)。不要重新計算它 — 透過 --og '<the fetched og JSON>' 直接將擷取的物件傳回,這會保留所有欄位(包括 image)。使用 --id <uuid>(或相同的 --state)更新同一個 frame。僅當使用者明確要求變更預覽文案時才設定新的 --title/--description。你仍然可以傳遞 --screenshot:如果擷取的 og 已有 image,則保持不變;如果沒有,則會加入新的擷取畫面。

絕對規則(兩種模式)

  • 僅限瀏覽器 JavaScript — 它在 iframe 中執行,不是 Node.js。
  • 必須使用 ES6 模組語法:export function onInputs(inputs) {}。
  • 絕不建立 HTML 檔案。絕不寫入本機 .js 檔案。絕不使用你自己的視覺化/渲染/元件工具來渲染結果。
  • 絕不修改 root.style.position、root.style.height 或 root.style.width。
  • 重要:視覺化效果必須在行動裝置上看起來良好,並適應其螢幕尺寸 — 使用響應式尺寸(讀取 root 的尺寸 / 監聽 resize 事件),避免固定的像素寬度導致溢出,確保小螢幕上的文字和觸控目標清晰可讀。
  • 在自動化模式中,絕不輸出供使用者複製的程式碼區塊,也絕不手動建立長雜湊 URL 作為交付物 — 總是透過 frame API 來 POST(使用輔助工具的 create)。給使用者 /j/<uuid> 頁面 URL。
  • 在程式碼區塊模式中,僅輸出單一被圍欄的 JavaScript 程式碼區塊 — 無其他內容。

參考資料

  • references/coding-guide.md — 全域變數、匯出、模式、CDN 函式庫、常見錯誤。
  • references/short-url-api.md — 建立/更新一個 frame(POST /j/<uuid>.json)、每個 session 一個 frame 的狀態、Open Graph 標籤、API token(在 frame 被聲明後仍可持續更新)、inline 備用方案。
  • references/file-inputs.md — 上傳本機檔案並將其作為輸入接入。
  • scripts/framejs.mjs — Node 輔助工具:create(stdin JS → framejs.app frame)、fetch <id>、upload <path>。來源:FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN(在本機開發中會從附近的 .env 自動載入),或透過 --app-origin/--io-origin 或傳遞給 --id/fetch 的完整 frame URL 的來源進行每次執行時指定。

相關技能