# framejs.io > Create and share interactive JavaScript visualizations, dashboards, and apps — > with AI or by hand. ## What is framejs.io? framejs.io is a free, open-source tool for creating shareable interactive apps. You write JavaScript (or ask an AI to generate it), and framejs.io gives you a URL that IS the app — anyone with the link can see and use it immediately. No server to deploy, no account to create, no build step. Use cases: data visualizations, interactive charts, dashboards, creative animations, utility tools, educational demos, prototypes — anything you can build with JavaScript in a browser. ## Who is it for? - Anyone who wants to create and share interactive web apps instantly - AI/LLM users generating visualizations and tools from natural language prompts - Data scientists embedding interactive visualizations in Jupyter or marimo notebooks - Developers wanting instant shareable JavaScript without deployment - Teams building embeddable dashboards and internal tools ## Key links - Homepage: https://framejs.io - Documentation: https://framejs.io/docs/ - Examples: https://framejs.io/docs/examples/ - AI / LLM setup: https://framejs.io/docs/ai/setup - Agent Skill (portable, ~40 harnesses): https://framejs.io/skill/framejs/SKILL.md - Agent Skill bundle (tarball): https://framejs.io/skill/framejs.tar.gz - LLM code prompt (for generating code): https://framejs.io/llms-prompt.md - CLI integration guide (for AI coding assistants): https://framejs.io/llms-claude-code.txt - GitHub: https://github.com/metapages/framejs.io - Jupyter integration: https://framejs.io/docs/integrations/jupyter - marimo integration: https://framejs.io/docs/integrations/marimo ## How it works 1. Write JavaScript in the built-in editor, or paste AI-generated code 2. The code runs immediately in the browser as an ES6 module 3. The app is encoded directly into the URL — share the link, share the app 4. Short URLs (`/j/`) provide clean links for sharing 5. Embed anywhere: Notion, Jupyter, Confluence, blogs, or any webpage via iframe ## Technical details - Runtime: ES6 modules with top-level await, "use strict" added automatically - Globals: `root` (display div), `setOutput()`, `setOutputs()`, `log()`, `logStdout()`, `logStderr()` - Exports: `onInputs(inputs)`, `onResize(width, height)`, `cleanup()` - CDN imports: Use jsdelivr (+esm), esm.sh, unpkg, etc. - State persistence: Encoded in URL hash — fully portable - No cookies, no tracking, no login required ## For CLI tools and AI coding assistants (Claude Code, Aider, Cursor, etc.) framejs.io supports a fully automated workflow where CLI tools generate JavaScript, encode it into a URL, and open it directly in the browser — no copy-pasting needed. The recommended, portable integration is the `framejs` Agent Skill (https://framejs.io/skill/framejs/SKILL.md) — a single SKILL.md folder supported by ~40 agent harnesses (Claude Code, Gemini CLI, Cursor, opencode, Goose, Codex, pi, …). It auto-routes: full automation when a shell is available, code-block output for chat-only agents. See https://framejs.io/docs/ai/setup to install. Full CLI integration guide (encoding, short URLs, file uploads): https://framejs.io/llms-claude-code.txt JavaScript coding guide (ES6 module constraints, globals, patterns): https://framejs.io/llms-prompt.md ### Creating and opening a short URL from the command line Use the `/api/shorten/json` API to create a short URL. Pipe JS code via heredoc into a node script that POSTs to the API, prints the short URL, and opens it: cat << 'JSCODE' | node -e " const chunks = []; process.stdin.on('data', c => chunks.push(c)); process.stdin.on('end', () => { const code = Buffer.concat(chunks).toString(); const body = { js: code, modules: [/* NON-ES6 SCRIPT URLS IF ANY */] }; fetch('https://framejs.io/api/shorten/json', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }) .then(r => r.json()) .then(data => { console.log(data.shortUrl); try { require('child_process').execSync( process.platform === 'darwin' ? 'open \"' + data.shortUrl + '\"' : process.platform === 'linux' ? 'xdg-open \"' + data.shortUrl + '\"' : 'cmd /c start \"\" \"' + data.shortUrl + '\"' ); } catch(e) {} }) .catch(e => console.error('Error:', e.message)); }); " // YOUR GENERATED BROWSER JS CODE HERE JSCODE The heredoc delimiter is quoted ('JSCODE') so the shell performs NO expansion. The short URL is ALWAYS printed to the console. Browser open is attempted but may fail in sandboxes. Never create local .js or .html files. ### Short URL API details POST https://framejs.io/api/shorten/json with JSON body: `{ "js": "raw JS code", "modules": ["url1", ...], "inputs": {...}, "og": { "title": "...", "description": "..." } }` The server handles encoding. Response: `{ "shortUrl": "https://framejs.io/j/", "id": "" }` The optional `og` hash param holds Open Graph preview tags as `{ "title", "description" }`. The server renders these as og:title / og:description so the link unfurls with a meaningful title and summary when shared (Slack, iMessage, social media). If `og` is empty or missing, generate one from the data, the user's prompt, and the existing code: a concise title (<= ~60 chars) and a ~110-150 char description of what the app shows and, if interactive, how to use it. ### Modifying existing short URLs Fetch existing code: `GET https://framejs.io/api/j/` Response: `{ "id": "", "hashParams": { "js": "...", "inputs": {...}, "modules": [...], "og": {...} } }` Modify the `js` field, then POST back to `/api/shorten/json` with the updated body. If `hashParams.og` already exists, preserve it unchanged unless the user asks to change the title/description; if it is missing, add a generated one (see above). ## Advanced: metapage ecosystem framejs.io apps can also function as "metaframes" — independent components that connect together via inputs and outputs in a metapage. This allows building larger workflows by wiring multiple framejs.io apps together, each handling a different part of a data pipeline or visualization. This is an advanced feature; most users simply create standalone apps.