{"id":19066004,"url":"https://github.com/metapages/metaframe-js","last_synced_at":"2026-04-18T03:32:40.786Z","repository":{"id":63682294,"uuid":"524262964","full_name":"metapages/metaframe-js","owner":"metapages","description":"Embed any JS module and custom code","archived":false,"fork":false,"pushed_at":"2024-10-24T02:03:54.000Z","size":3379,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-24T18:23:53.489Z","etag":null,"topics":["javascript","metaframe"],"latest_commit_sha":null,"homepage":"https://js.mtfm.io/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/metapages.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-13T00:56:54.000Z","updated_at":"2024-09-21T18:23:07.000Z","dependencies_parsed_at":"2023-12-26T03:25:30.612Z","dependency_job_id":"51ba0bff-9478-4b2e-8b43-6b0243e22997","html_url":"https://github.com/metapages/metaframe-js","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metapages%2Fmetaframe-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metapages%2Fmetaframe-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metapages%2Fmetaframe-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/metapages%2Fmetaframe-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/metapages","download_url":"https://codeload.github.com/metapages/metaframe-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240118421,"owners_count":19750491,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","metaframe"],"created_at":"2024-11-09T00:53:59.083Z","updated_at":"2026-04-18T03:32:40.746Z","avatar_url":"https://github.com/metapages.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Javascript embedded in the URL: run and edit \n\nRun code and edit javascript code in the browser. No server required.\n\n### Longer description\nRun arbitrary user javascript modules embedded in the URL. Designed for [metapages](https://metapage.io) so you can connect inputs + outputs to other metaframe URLs.\n\n## Javascript high level\n\n - code is an es6 module \n - top-level `await`\n - export a function `onInputs` to listen to inputs\n - send outputs with `setOutput`/`setOutputs` (predefined functions available in your module)\n - export a function `onResize` to listen to window/div resizes\n - use es6 module imports, or add any css / npm modules to the page, they are embedded in the URL\n\n## Useful code snippets\n\n### Handling Inputs and outputs in code\n\nSimply export a function (arrow function also good 👍) called `onInputs`:\n\n```javascript\n// regular js function\nexport function onInputs(inputs) {\n  // do something here\n  // inputs is a plain object (key and values)\n}\n//  OR arrow function\nexport const onInputs = (inputs) =\u003e {\n  // do something here\n  // inputs is a plain object (key and values)\n}\n```\n\nTo send outputs, there are two functions in the scope `setOutput` and `setOutputs`:\n\n```javascript\n// send a single JSON output\nsetOutput(\"outputname\", 42);\n\n// send an output object of keys+values\nsetOutputs({\n  outputname:true,\n  someOtherOutputName: \"bar\",\n});\n```\n\nOutput values can be strings, JSON, objects, arrays, numbers, ArrayBuffers, typed arrays such as `Uint8Array`;\n\n### Define Inputs and Outputs\n\nIn `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](https://metapage.io).\n\nIn this example, we defined an input: `input.json` and an output `data.csv`:\n\n![inputs](/editor/readme-images/io.png \"Inputs and outputs defined in Settings\")\n\nYou will see these inputs and outputs automatically in the metapage editor.\n\n### The root display div element is exposed in the scope\n\nThe root display div is exposed in the script scope: the name is `root` and the id is also `root`:\n\n```javascript\nconsole.log(root.id)\n// logs \"root\"\n// Add any custom dome elements into \"root\".\n```\n\nYou can also just get it with:\n```javascript\ndocument.getElementById(\"root\")\n```\n\n### Window resize\n\nSimply 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:\n\n```javascript\n// regular js function\nexport function onResize(width, height) {\n  // Your own code here, handling the resize of the root div\n}\n//  OR arrow function\nexport const onResize = (width, height) =\u003e {\n  // Your own code here, handling the resize of the root div\n}\n```\n\n### Unload/cleanup\n\nWhen 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.\n\nThis is not an issue when simply running the page once with code, only when develping iteratively.\n\nTo 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:\n\n```javascript\n// regular js function\nexport function cleanup() {\n\tconsole.log(\"internal scriptUnload call\")\n\t// do your cleanup here\n}\n// OR arrow function\nexport const cleanup = () =\u003e {\n  // do your cleanup here\n}\n```\n\n### Wait until page `load`\n\nYou don't need to wait for the `load` event: your script will not run until `load` event fires.\n\n### Logging to the display (instead of console)\n\nSome globally available functions for logging:\n\n```javascript\n\n  log(\"something here\");\n  logStdout(\"something here\");\n  logStderr(\"an error\");\n\n```\n\nThese 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.\n\n### Misc\n\n - `\"use strict\"` is automatically added to the top of the module code.\n\n## Connect upstream/downstream metaframes\n\n[![](https://mermaid.ink/svg/pako:eNqFkU9LxDAQxb9KiJcVuqC9KBG8uN7sRT1JL2MzaYP5RzJhle1-d9NWd1HBnVMm770fw8yOd14iF7yPEAb28Ng6VqozkNIGFbPhzhsfmdLGiLPrK3mhVJUo-jf81a63WtIg6vB-szBSfl2gFgkC9Lh8T2VQ0eUqh5JEsLNBRbB4ztbr21G7kCmNrFk9Dzqx5qAKIb7m-YmqT6OOgWYS2OgzLVLU_VCGkX7r_jBOpOr_Uuhk63jFLUYLWpYV7yah5TSgxZaL8pSoIBtqeev2xZqDBMJ7qclHLhSYhBWHTP7pw3VcUMz4bdpoKMu1B1cA9-L9sccZ0iy3nU-8_wSxOqSj)](https://mermaid-js.github.io/mermaid-live-editor/edit#pako:eNqFkU9LxDAQxb9KiJcVuqC9KBG8uN7sRT1JL2MzaYP5RzJhle1-d9NWd1HBnVMm770fw8yOd14iF7yPEAb28Ng6VqozkNIGFbPhzhsfmdLGiLPrK3mhVJUo-jf81a63WtIg6vB-szBSfl2gFgkC9Lh8T2VQ0eUqh5JEsLNBRbB4ztbr21G7kCmNrFk9Dzqx5qAKIb7m-YmqT6OOgWYS2OgzLVLU_VCGkX7r_jBOpOr_Uuhk63jFLUYLWpYV7yah5TSgxZaL8pSoIBtqeev2xZqDBMJ7qclHLhSYhBWHTP7pw3VcUMz4bdpoKMu1B1cA9-L9sccZ0iy3nU-8_wSxOqSj)\n\n\n## Examples\n\n  - [Rotate stick on canvas from incoming angles](https://app.metapages.org/#?definition=JTdCJTIybWV0YSUyMiUzQSU3QiUyMmxheW91dHMlMjIlM0ElN0IlMjJyZWFjdC1ncmlkLWxheW91dCUyMiUzQSU3QiUyMmRvY3MlMjIlM0ElMjJodHRwcyUzQSUyRiUyRnd3dy5ucG1qcy5jb20lMkZwYWNrYWdlJTJGcmVhY3QtZ3JpZC1sYXlvdXQlMjIlMkMlMjJsYXlvdXQlMjIlM0ElNUIlN0IlMjJoJTIyJTNBMyUyQyUyMmklMjIlM0ElMjJyYW5kb20tZGF0YSUyMiUyQyUyMm1vdmVkJTIyJTNBZmFsc2UlMkMlMjJzdGF0aWMlMjIlM0FmYWxzZSUyQyUyMnclMjIlM0E1JTJDJTIyeCUyMiUzQTAlMkMlMjJ5JTIyJTNBMCU3RCUyQyU3QiUyMmglMjIlM0EzJTJDJTIyaSUyMiUzQSUyMnN0aWNrJTIyJTJDJTIybW92ZWQlMjIlM0FmYWxzZSUyQyUyMnN0YXRpYyUyMiUzQWZhbHNlJTJDJTIydyUyMiUzQTclMkMlMjJ4JTIyJTNBNSUyQyUyMnklMjIlM0EwJTdEJTVEJTJDJTIycHJvcHMlMjIlM0ElN0IlMjJjb2xzJTIyJTNBMTIlMkMlMjJjb250YWluZXJQYWRkaW5nJTIyJTNBJTVCNSUyQzUlNUQlMkMlMjJtYXJnaW4lMjIlM0ElNUIxMCUyQzIwJTVEJTJDJTIycm93SGVpZ2h0JTIyJTNBMTAwJTdEJTdEJTdEJTdEJTJDJTIybWV0YWZyYW1lcyUyMiUzQSU3QiUyMnJhbmRvbS1kYXRhJTIyJTNBJTdCJTIydXJsJTIyJTNBJTIyaHR0cHMlM0ElMkYlMkZyYW5kb20ubXRmbS5pbyUyRiUyMyUzRmRpc3RyaWJ1dGlvbiUzRGV5SmthWE4wY21saWRYUnBiMjRpT2lKemFXNGlMQ0ptY21WeGRXVnVZM2tpT2pFd0xDSnZjSFJwYjI1eklqcDdJbWx1WTNKbGJXVnVkQ0k2TUM0eGZTd2ljMmh2ZDA5MWRIQjFkQ0k2Wm1Gc2MyVjklMjIlN0QlMkMlMjJzdGljayUyMiUzQSU3QiUyMmlucHV0cyUyMiUzQSU1QiU3QiUyMm1ldGFmcmFtZSUyMiUzQSUyMnJhbmRvbS1kYXRhJTIyJTJDJTIyc291cmNlJTIyJTNBJTIydiUyMiUyQyUyMnRhcmdldCUyMiUzQSUyMnklMjIlN0QlNUQlMkMlMjJ1cmwlMjIlM0ElMjJodHRwcyUzQSUyRiUyRmpzLm10Zm0uaW8lMkYlMjMlM0ZlZGl0JTNEMSUyNmpzJTNEWTI5dWMzUWxNakJrYVhOd2IzTmxjbk1sTWpBbE0wUWxNakFsTlVJbE5VUWxNMElsTUVGamIyNXpkQ1V5TUhKdmIzUWxNakFsTTBRbE1qQmtiMk4xYldWdWRDNW5aWFJGYkdWdFpXNTBRbmxKWkNnbE1qSnliMjkwSlRJeUtTVXpRaVV3UVNVd1FTVXlSaVV5UmlVeU1ISmxibVJsY2lVeU1IUm9aU1V5TUdGdVoyeGxKVEJCZG1GeUpUSXdZMkZ1ZG1GekpUSXdKVE5FSlRJd1pHOWpkVzFsYm5RdVkzSmxZWFJsUld4bGJXVnVkQ2dsTWpKallXNTJZWE1sTWpJcEpUTkNKVEJCWTJGdWRtRnpMbmRwWkhSb0pUSXdKVE5FSlRJd01qQXdKVE5DSlRCQlkyRnVkbUZ6TG1obGFXZG9kQ1V5TUNVelJDVXlNREl3TUNVelFpVXdRWEp2YjNRdVlYQndaVzVrUTJocGJHUW9ZMkZ1ZG1GektTVXpRaVV3UVNVd1FXTnZibk4wSlRJd1kzUjRKVEl3SlRORUpUSXdZMkZ1ZG1GekxtZGxkRU52Ym5SbGVIUW9KVEl5TW1RbE1qSXBKVE5DSlRCQlkyOXVjM1FsTWpBbE5VSjNKVEpESlRJd2FDVTFSQ1V5TUNVelJDVXlNQ1UxUWpJd0pUSkRKVEl3WTJGdWRtRnpMbWhsYVdkb2RDVTFSQ1V6UWlVd1FXTnZibk4wSlRJd0pUVkNlQ1V5UXlVeU1Ia2xOVVFsTWpBbE0wUWxNakFsTlVKallXNTJZWE11ZDJsa2RHZ2xNakFsTWtZbE1qQXlKVEpESlRJd1kyRnVkbUZ6TG1obGFXZG9kQ1V5TUNVeVJpVXlNRElsTlVRbE0wSWxNRUVsTUVGamIyNXpkQ1V5TUdSeVlYY2xNakFsTTBRbE1qQW9jbUZrS1NVeU1DVXpSQ1V6UlNVeU1DVTNRaVV3UVNVeU1DVXlNR04wZUM1amJHVmhjbEpsWTNRb01DVXlReVV5TURBbE1rTWxNakJqWVc1MllYTXVkMmxrZEdnbE1rTWxNakJqWVc1MllYTXVhR1ZwWjJoMEtTVXpRaVV3UVNVd1FTVXlNQ1V5TUNVeVJpVXlSaVV5TUdacGNuTjBKVEl3YzJGMlpTVXlNSFJvWlNVeU1IVnVkSEpoYm5Oc1lYUmxaQ1V5Um5WdWNtOTBZWFJsWkNVeU1HTnZiblJsZUhRbE1FRWxNakFsTWpCamRIZ3VjMkYyWlNncEpUTkNKVEJCSlRCQkpUSXdKVEl3WTNSNExtSmxaMmx1VUdGMGFDZ3BKVE5DSlRCQkpUSXdKVEl3SlRKR0pUSkdKVEl3Ylc5MlpTVXlNSFJvWlNVeU1ISnZkR0YwYVc5dUpUSXdjRzlwYm5RbE1qQjBieVV5TUhSb1pTVXlNR05sYm5SbGNpVXlNRzltSlRJd2RHaGxKVEl3Y21WamRDVXdRU1V5TUNVeU1HTjBlQzUwY21GdWMyeGhkR1VvZUNVeVF5VXlNR2dsTWpBbE1rWWxNakF5S1NVelFpVXdRU1V5TUNVeU1DVXlSaVV5UmlVeU1ISnZkR0YwWlNVeU1IUm9aU1V5TUhKbFkzUWxNRUVsTWpBbE1qQmpkSGd1Y205MFlYUmxLSEpoWkNrbE0wSWxNRUVsTUVFbE1qQWxNakFsTWtZbE1rWWxNakJrY21GM0pUSXdkR2hsSlRJd2NtVmpkQ1V5TUc5dUpUSXdkR2hsSlRJd2RISmhibk5tYjNKdFpXUWxNakJqYjI1MFpYaDBKVEJCSlRJd0pUSXdZM1I0TG5KbFkzUW9MWGNsTWpBbE1rWWxNakF5SlRKREpUSXdMV2dsTWpBbE1rWWxNakF5SlRKREpUSXdkeVV5UXlVeU1HZ3BKVE5DSlRCQkpUQkJKVEl3SlRJd1kzUjRMbVpwYkd4VGRIbHNaU1V5TUNVelJDVXlNQ1V5TW1keVpXVnVKVEl5SlROQ0pUQkJKVEl3SlRJd1kzUjRMbVpwYkd3b0tTVXpRaVV3UVNVd1FTVXlNQ1V5TUdOMGVDNXlaWE4wYjNKbEtDa2xNMElsTUVFbE4wUWxNMElsTUVFbE1FRWxNa1lsTWtZbE1qQk1hWE4wWlc0bE1qQjBieVV5TUdGdUpUSXdhVzV3ZFhRbE1FRmthWE53YjNObGNuTXVjSFZ6YUNnbE1FRWxNakFsTWpCdFpYUmhabkpoYldVdWIyNUpibkIxZEhNb0tHbHVjSFYwY3lrbE1qQWxNMFFsTTBVbE1qQWxOMElsTUVFbE1qQWxNakFsTWpBbE1qQnRaWFJoWm5KaGJXVXVjMlYwVDNWMGNIVjBjeWhwYm5CMWRITXBKVE5DSlRCQkpUSXdKVEl3SlRJd0pUSXdZMjl1YzNRbE1qQjVKVEl3SlRORUpUSXdhVzV3ZFhSekpUVkNKVEl5ZVNVeU1pVTFSQ1V6UWlVd1FTVXlNQ1V5TUNVeU1DVXlNR2xtSlRJd0tDRjVLU1V5TUNVM1FpVXdRU1V5TUNVeU1DVXlNQ1V5TUNVeU1DVXlNSEpsZEhWeWJpVXpRaVV3UVNVeU1DVXlNQ1V5TUNVeU1DVTNSQ1V3UVNVeU1DVXlNQ1V5TUNVeU1HUnlZWGNvZVNrbE0wSWxNRUVsTWpBbE1qQWxOMFFwSlRCQktTVXpRaVV3UVdSeVlYY29NQ2tsTTBJbE1FRWxNRUVsTWtZbE1rWWxNakJTWlhSMWNtNGxNakJoSlRJd1kyeGxZVzUxY0NVeU1HWjFibU4wYVc5dUpUQkJkMmx1Wkc5M0xuTmpjbWx3ZEZWdWJHOWhaQ1V5TUNVelJDVXlNQ2dwSlRJd0pUTkVKVE5GSlRJd0pUZENKVEJCSlRJd0pUSXdkMmhwYkdVbE1qQW9aR2x6Y0c5elpYSnpMbXhsYm1kMGFDVXlNQ1V6UlNVeU1EQXBKVEl3SlRkQ0pUQkJKVEl3SlRJd0pUSXdKVEl3WkdsemNHOXpaWEp6TG5CdmNDZ3BLQ2tsTTBJbE1FRWxNakFsTWpBbE4wUWxNRUVsTjBRbE0wSWxNRUUlM0QlMjZtb2R1bGVzJTNESlRWQ0pUVkUlMjZvcHRpb25zJTNEZXlKb2FXUmxiV1Z1ZFdsbWFXWnlZVzFsSWpwMGNuVmxMQ0p0YjJSbElqb2lhbUYyWVhOamNtbHdkQ0lzSW5OaGRtVnNiMkZrYVc1b1lYTm9JanAwY25WbExDSjBhR1Z0WlNJNklteHBaMmgwSW4wJTNEJTIyJTdEJTdEJTJDJTIycGx1Z2lucyUyMiUzQSU1QiUyMmh0dHBzJTNBJTJGJTJGbWVybWFpZC5tdGZtLmlvJTJGJTIzJTNGaG0lM0RkaXNhYmxlZCUyMiUyQyUyMmh0dHBzJTNBJTJGJTJGZWRpdG9yLm10Zm0uaW8lMkYlMjMlM0ZobSUzRGRpc2FibGVkJTI2b3B0aW9ucyUzREpUZENKVEl5Ylc5a1pTVXlNaVV6UVNVeU1tcHpiMjRsTWpJbE1rTWxNakp6WVhabGJHOWhaR2x1YUdGemFDVXlNaVV6UVhSeWRXVWxNa01sTWpKMGFHVnRaU1V5TWlVelFTVXlNbXhwWjJoMEpUSXlKVGRFJTIyJTVEJTJDJTIydmVyc2lvbiUyMiUzQSUyMjAuMyUyMiU3RA==\u0026minimal=false)\n\n\n## Description\n\n - user created javascript\n - user defined css modules\n\nThink of this like [codepen](https://codepen.io) or [others](https://www.sitepoint.com/code-playgrounds/) but stripped down focusing on core essentials, performance, and durability.\n\nThis website is also a [metaframe](https://docs.metapage.io/docs/what-is-a-metaframe): connect metaframes together into apps/workflows/dashboards: [metapages](https://docs.metapage.io/docs)\n\n[Github Repo](https://github.com/metapages/metaframe-js)\n\n**Architecture:**\n\n\n - no state is stored on the server (all embedded in the URL)\n   - this imposes some limits but current URL lengths are large or not specifically limited\n - The server simply serves a little `index.html`\n - The client then runs the embedded javascript (the javascript code is **not** sent to the server)\n\nThe server runs on https://deno.com/deploy which is\n\n - simple\n - fast\n - very performant\n - deploys immediately with a simply push to the repository\n - 🌟🌟🌟🌟🌟\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetapages%2Fmetaframe-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmetapages%2Fmetaframe-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmetapages%2Fmetaframe-js/lists"}