AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Framejs

skill-metapages-framejs-io-framejs · by metapages

Create, modify, and share interactive browser apps and visualizations from JavaScript via framejs.io. The app is encoded into a shareable URL that runs instantly — no build, server, or account. Use when the user wants a chart, graph, plot, dashboard, animation, simulation, creative coding sketch, data visualization, or small interactive web tool; when they reference a framejs.io short URL (/j/<sh…

No reviews yet
0 installs
6 views
0.0% view→install

Install

$ agentstack add skill-metapages-framejs-io-framejs

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-metapages-framejs-io-framejs)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
19d ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Framejs? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

framejs

framejs runs an ES6 JavaScript module in the browser. A frame is the app: it lives at a stable, shareable framejs.app/j/ URL whose content is mutable — you update the app in place by POSTing its hash params. Your job: turn the user's request into that browser JavaScript and deliver it the right way for your environment.

Pick your delivery mode

Choose based on what you can do — not on the request:

  • Automation mode — you can run a shell / node: generate the JavaScript,

then create-or-update the session's framejs.app frame, print its /j/ URL, and open it in the browser. This is the default whenever a shell is available.

  • Code-block mode — chat / API only, no shell: respond with only a

single fenced JavaScript code block (open it with a javascript info string) and nothing else — no surrounding prose, no files, no URLs. The user pastes it into the editor at framejs.io.

In both modes the JavaScript you write follows the same rules — read [references/coding-guide.md](references/coding-guide.md).

What the request can be

  1. Create from a prompt — "a bouncing ball animation", "plot y = sin(x)".
  2. Modify an existing app — the request contains a frame URL. It may be a

https://framejs.app/j/ or a https://framejs.io/j/?token=… URL (the "Copy frame for AI session" action copies the framejs.io runtime form), a bare 32-char hex id, or a legacy https://framejs.io/j/ / 64-char id snapshot. Whenever you see a framejs URL, extract the uuid from its /j/ path and target THAT frame (pass the URL straight to --id — the helper routes the update to the app layer even for a framejs.io URL). You MUST fetch the existing code first and modify it — see [references/short-url-api.md](references/short-url-api.md) (§ Modify). If the URL carries a ?token= query param (from the app's "Copy frame for AI session" action), pass the whole URL to --id (or the key to --token): the helper stores it and sends it as the bearer credential so your updates keep working even after the frame's owner has claimed it. Passing the whole URL also targets the backend the URL names — so a dev or self-hosted frame URL (e.g. https://framejs-app.localhost:13747/j/?token=) updates its own stack with no env preconfigured. --app-origin / --io-origin set the backend explicitly. See [references/short-url-api.md](references/short-url-api.md) (§ Local / dev origins).

  1. Visualize local files — the request references file paths (./data.csv,

/tmp/results.json). Upload them and pass as inputs — see [references/file-inputs.md](references/file-inputs.md).

Automation mode — how to deliver

Generate the code, then use the bundled helper (preferred) or the inline-node fallback in [references/short-url-api.md](references/short-url-api.md):

cat " --description "" --screenshot
// your generated browser JS here — $vars, backticks, all special chars are safe inside the heredoc
JSCODE

The helper prints (on stdout) two URLs — the primary https://framejs.app/j/ page URL and an immutable snapshot: https://framejs.io/j/ URL. It also prints (on stderr) a share-link lifecycle notice you MUST relay to the user:

  • the /j/ page is editable and live-updating, but an **anonymous

(unclaimed) frame is temporary and will expire — tell the user to open it and claim it** (free account) to keep it permanently;

  • the /j/ snapshot is an immutable copy of the current app

that expires ~30 days after it is last opened — a good stable share/backup link, but it never reflects later edits.

Add --module for classic scripts and --input name=value for inputs.

One frame per session, updated in place. Always pass --state "/framejs-frame.json" (any writable file path). The first create mints the frame; re-run create with the same --state to UPDATE the same frame — the /j/ URL stays constant and any open framejs.app page updates live, so give the URL to the user once. Only when the user wants a separate app in the same session, add --new to start a fresh frame (subsequent updates then target that new one). To update one specific frame regardless of state, pass --id . On such an in-place update the helper carries the frame's existing Open Graph data forward automatically when you pass no --og/--title/--description, so a bare re-run never drops the title/description (and the retained og.image skips a redundant re-screenshot). Pass --title/--description again only to change the preview copy.

The browser opens automatically only the first time a frame is minted (--no-open to skip even that). A later update to the same frame — same --state, or an explicit --id — does NOT reopen the browser: the page already open reaches it live through the same-frame subscription, so opening again would just spawn a redundant new tab.

If a local dev checkout is present, the helper auto-loads its .env and targets the dev stacks (FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN) instead of production — no action needed on your part.

If the helper prints an out of date update notice (on stderr, at most hourly), relay it to the user verbatim once — their installed skill is behind the latest and the notice tells them the one command to update it.

Always pass --screenshot: the helper renders the finished app and stores the capture as the og:image preview. It is self-guarding — it captures ONLY when the app has no og.image yet, so it never overwrites an image a previous run (or the user) already set, and it silently falls back to the image-less URL if no renderer is available. Capture prefers Playwright when it can be imported (true network-idle waiting — best for apps that fetch inputs), and otherwise uses system headless Chrome. Playwright is optional: install it (npm i -g playwright && npx playwright install chromium) for the more reliable path, or point $FRAMEJS_PLAYWRIGHT at a dir whose node_modules has it. Tune with --screenshot-wait (default 6000 — raise it for apps that load slowly) and --screenshot-size (default 1200,630). Override the Chrome binary with $CHROME_PATH.

scripts/framejs.mjs is resolved relative to this skill's directory, not your current working directory — run it from the skill folder, or use its absolute path (Claude Code exposes that directory as ${CLAUDE_SKILL_DIR}, so ${CLAUDE_SKILL_DIR}/scripts/framejs.mjs always works). If you cannot locate or run the bundled helper, use the inline-node fallback in [references/short-url-api.md](references/short-url-api.md) — it needs no script file.

Always include Open Graph preview tags so the link unfurls nicely when shared — see the OG rules in [references/short-url-api.md](references/short-url-api.md):

  • New app: derive fresh copy with --title / --description, and pass

--screenshot to capture the preview image.

  • Modifying an existing app: the fetched app already carries og (the

fetch command returns it). Do NOT recalculate it — pass the fetched object straight back through with --og '', which preserves every field (including image). Update the SAME frame with --id (or the same --state). Only set new --title/--description if the user explicitly asked to change the preview copy. You can still pass --screenshot: if the fetched og already has an image it is left untouched; if it has none, a fresh capture is added.

Absolute rules (both modes)

  • Browser JavaScript only — it runs in an iframe, NOT Node.js.
  • MUST use ES6 module syntax: export function onInputs(inputs) {}.
  • NEVER create HTML files. NEVER write local .js files. NEVER use your own

visualization/rendering/widget tools to render the result.

  • NEVER modify root.style.position, root.style.height, or

root.style.width.

  • **IMPORTANT: the visualization MUST look good on mobile and adapt to that

screen size** — use responsive sizing (read root's dimensions / listen for resize), avoid fixed pixel widths that overflow, keep text and touch targets legible on small screens.

  • In automation mode, NEVER output a code block for the user to copy and NEVER

hand-build a long hash URL as the deliverable — always POST through the frame API (the helper's create). Give the user the /j/ page URL.

  • In code-block mode, output ONLY the single fenced JavaScript code block —

nothing else.

References

  • [references/coding-guide.md](references/coding-guide.md) — globals, exports,

patterns, CDN libraries, common mistakes.

  • [references/short-url-api.md](references/short-url-api.md) — create/update a

frame (POST /j/.json), one-frame-per-session state, Open Graph tags, API tokens (keep updating after a frame is claimed), inline fallbacks.

  • [references/file-inputs.md](references/file-inputs.md) — upload local files

and wire them in as inputs.

  • scripts/framejs.mjs — Node helper: create (stdin JS → framejs.app frame),

fetch , upload . Origins: FRAMEJS_APP_ORIGIN / FRAMEJS_IO_ORIGIN (auto-loaded from a nearby .env in local dev), or per-run via --app-origin/--io-origin or the origin of a full frame URL passed to --id/fetch.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.