Edit and run javascript code in the browser. Share and connect the self-contained websites with other chunks of code and visualization.
Copy and paste into AI such as Claude Code or ChatGPT and create shareable code that will always run.
-
Copy the AI prompt, paste into e.g. Claude Code or ChatGPT, the ask what you want

-
Copy the result back to the Javascript window. Now you have something to share or embed
- Visualize change network connections
- Use any visualization module
- Display any kind of table or tabular data
- Animation, shaders, 3D
- code is an es6 module
- top-level
await - export a function
onInputsto listen to inputs - send outputs with
setOutput/setOutputs(predefined functions available in your module) - export a function
onResizeto listen to window/div resizes - use es6 module imports, or add any css / npm modules to the page, they are embedded in the URL
Simply export a function (arrow function also good π) called onInputs:
// regular js function
export function onInputs(inputs) {
// do something here
// inputs is a plain object (key and values)
}
// OR arrow function
export const onInputs = (inputs) => {
// do something here
// inputs is a plain object (key and values)
}To send outputs, there are two functions in the scope setOutput and setOutputs:
// send a single JSON output
setOutput("outputname", 42);
// send an output object of keys+values
setOutputs({
outputname:true,
someOtherOutputName: "bar",
});Output values can be strings, JSON, objects, arrays, numbers, ArrayBuffers, typed arrays such as Uint8Array;
In Settings you can define inputs and outputs. This doesn't change how the code runs, but it allows much easier connecting upstream and downstream metaframes when editing metapages.
In this example, we defined an input: input.json and an output data.csv:
You will see these inputs and outputs automatically in the metapage editor.
The root display div is exposed in the script scope: the name is root and the id is also root:
console.log(root.id)
// logs "root"
// Add any custom dome elements into "root".You can also just get it with:
document.getElementById("root")To get the root element width/height:
const width = root.getBoundingClientRect().width;
const height = root.getBoundingClientRect().height;For automatically resizing: export a function (arrow function also good π) called onResize. This will be called when either the window resizes event and/or the local div element resizes:
// regular js function
export function onResize(width, height) {
// Your own code here, handling the resize of the root div
}
// OR arrow function
export const onResize = (width, height) => {
// Your own code here, handling the resize of the root div
}Often if you use (wheel) scroll events to interact with content, the event is also propagated to the parent window, scrolling the entire metapage, which is almost always undesired.
To prevent this, on the dom element you intercept wheel scroll events, add this code to prevent the event from propagating up. Replace myContainer with your dom element:
// prevent parent from scrolling when zooming
function maybeScroll(event) {
if (myContainer.contains(event.target)) {
event.preventDefault();
}
}
window.addEventListener('wheel', maybeScroll, {passive: false})When iterating with the code editor, the script is re-run. In some cases, this can cause problems as multiple listeners maybe responding to the same event.
This is not an issue when simply running the page once with code, only when develping iteratively.
To have your script cleaned up because of new script (when editing), declare a function cleanup, this will be called prior to the updated script re-running:
// regular js function
export function cleanup() {
console.log("internal scriptUnload call")
// do your cleanup here
}
// OR arrow function
export const cleanup = () => {
// do your cleanup here
}You don't need to wait for the load event: your script will not run until load event fires.
Some globally available functions for logging:
log("something here");
logStdout("something here");
logStderr("an error");These will be added to the root div (see below) so if your own code manipulates the root div, it could be overwritten. This is mostly useful for headless code.
"use strict"is automatically added to the top of the module code.
Run arbitrary user javascript modules embedded in the URL. Designed for metapages so you can connect inputs + outputs to other metaframe URLs. Similar to Codepen, JSFiddle, but completely self-contained and does not require an active server, these is a simple tiny static website.
graph LR
subgraph metapage
direction LR
left1(upstream metaframe) -->|inputs| M[This Metaframe]
M --> |outputs| right1(downstream metaframe)
end
This website is also a metaframe: connect metaframes together into apps/workflows/dashboards: metapages
- no state is stored on the server (all embedded in the URL)
- this imposes some limits but current URL lengths are large or not specifically limited
- The server simply serves a little
index.html - The client then runs the embedded javascript (the javascript code is not sent to the server)
The server runs on https://deno.com/deploy which is
- simple
- fast
- very performant
- deploys immediately with a simply push to the repository
- πππππ
