{"id":15162192,"url":"https://github.com/rozek/aframe-within-svelte","last_synced_at":"2026-02-12T04:33:21.473Z","repository":{"id":114382871,"uuid":"523471562","full_name":"rozek/aframe-within-svelte","owner":"rozek","description":"some notes on how to use A-Frame within a Svelte Application","archived":false,"fork":false,"pushed_at":"2022-08-11T07:01:30.000Z","size":65,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-14T02:29:10.422Z","etag":null,"topics":["a-frame","svelte","svelte3"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rozek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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-10T19:26:34.000Z","updated_at":"2023-08-28T16:00:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"4b2be696-792f-41b4-8b27-af651095b656","html_url":"https://github.com/rozek/aframe-within-svelte","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/rozek%2Faframe-within-svelte","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rozek%2Faframe-within-svelte/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rozek%2Faframe-within-svelte/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rozek%2Faframe-within-svelte/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rozek","download_url":"https://codeload.github.com/rozek/aframe-within-svelte/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247767473,"owners_count":20992594,"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":["a-frame","svelte","svelte3"],"created_at":"2024-09-27T01:20:52.436Z","updated_at":"2026-02-12T04:33:16.417Z","avatar_url":"https://github.com/rozek.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aframe-within-svelte #\n\nsome notes on how to use A-Frame within a Svelte Application\n\n[A-Frame](https://github.com/aframevr/aframe) is a framework for creating \"virtual reality experiences\" in the same way as \"ordinary\" web pages: by means of HTML elements with attributes and content. Under the hood, A-Frame uses the DOM only to manage the hierarchical description of a VR/AR \"scene\" and its \"assets\" (especially, without burdening the browser's layout engine) and then simply maps these elements to corresponding objects of the underlying [Three.js](https://github.com/mrdoob/three.js/) library (this approach drastically simplifies the use of Three.js)\n\n[Svelte](https://github.com/sveltejs/svelte) is a tool for building web applications from components which look and behave like custom HTML elements. Svelte accesses the DOM directly to manage these elements and update their attributes and contents upon changes.\n\nWhile the underlying execution models of A-Frame and Svelte differ completely, their use of the DOM as a common data base ensures a fairly smooth interaction.\n\nThis repository illustrates how to integrate A-Frame entities, components and systems into a Svelte application - and how to use Svelte to implement custom A-Frame entities, components and systems. As you will see, it's quite simple.\n\n### Terminology ###\n\nA-Frame has an [entity-component-system](https://aframe.io/docs/1.3.0/introduction/entity-component-system.html) (ECS) architecture. As a consequence, an A-Frame \"component\" is something completely different than a Svelte \"component\". The following table tries to give a (really) rough mapping between A-Frame \"Entities\", \"Components\" and \"Systems\" and their Svelte counterparts:\n\n\u003ctable\u003e\u003ctbody\u003e\n\u003ctr\u003e\u003cth\u003eA-Frame\u003c/th\u003e\u003cth\u003eSvelte\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eEntity\u003c/td\u003e\u003ctd\u003esimilar to a Svelte Component\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eComponent\u003c/td\u003e\u003ctd\u003esimilar to Svelte \"props\"\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eSystem\u003c/td\u003e\u003ctd\u003ethe business logic behind these \"props\"\u003c/td\u003e\u003c/tr\u003e\n\u003c/tbody\u003e\u003c/table\u003e\n\nIn an object-oriented world, ECS \"components\" contain the data of a mixin or (in case of multiple inheritance) a single superclass, whereas a \"system\" contains the mixin's or superclass's implementation. ECS \"entities\" then simply represent instances of (classes inheriting from) these mixins or superclasses without any own data or business logic.\n\n### Example ###\n\nThis repository contains files for an example which demonstrates all mechanisms described below:\n\n* [`aframe-component.js`](./aframe-component.js) - implements an A-Frame \"component\"\n* [`aframe-system.js`](./aframe-system.js) - implements an A-Frame \"system\" (and its associated \"component\")\n* [`aframe-primitive.js`](./aframe-primitive.js) - implements an A-Frame \"primitive\"\n* [`AFrameEntity.svelte`](./AFrameEntity.svelte) - implements a Svelte component which acts like an A-Frame \"entity\"\n* [`App.svelte`](./App.svelte) - contains the Svelte application which uses all modules shown above\n\n`aframe-component.js` and `aframe-system.js` log invocations of their lifecycle method on the browser console - thus, make sure to open the browser's developer tools and watch the console.\n\n### Svelte REPL ###\n\nWhile the example also exists in the [Svelte REPL](https://svelte.dev/repl/43f54b1b2ab34533a69c363067194d2d), the mechanisms behind this REPL currently seem to be incompatible with A-Frame - the example therefore refuses to start.\n\nJust build the example offline instead and run it locally on your own computer.\n\n## Using A-Frame in a Svelte Application ##\n\nAssuming that you are following the usual workflow for Svelte applications (which finally runs [Rollup](https://rollupjs.org/guide/en/) or [WebPack](https://webpack.js.org/) to bundle a set of modules into an optimized JavaScript distribution), everything starts by installing A-Frame as such a module:\n\n```bash\nnpm install --save aframe\n```\n\nWithin a Svelte file, you then just import A-Frame like so:\n\n```html\n\u003cscript context=\"module\"\u003e\n  import \"aframe\"\n\u003c/script\u003e\n```\n\nTwo remarks seem appropriate:\n\n* importing A-Frame will blow up your final JavaScript distribution file by more than 2 MB - that's ok since A-Frame is not \"tree-shakeable\" yet and there seem to be [no plans to make it tree-shakeable](https://github.com/aframevr/aframe/issues/4242) in the near future\n* since A-Frame actually expects to be included by a `\u003cscript\u003e` element in the `\u003chead\u003e` section of an HTML document, it issues a _warning_ in the browser console if this is not the case - just ignore this warning...\n\nAfter having imported A-Frame, its elements may be used like any other HTML element in a Svelte application:\n\n```html\n\u003ca-scene\u003e\n  \u003ca-sky color=\"#ECECEC\"/\u003e\n  \u003ca-box color=\"#4CC3D9\"\n    position=\"0 0.5 -3\" rotation=\"0 45 0\"/\u003e\n  \u003ca-plane width=\"4\" height=\"4\" color=\"#7BC8A4\"\n    position=\"0 0 -4\" rotation=\"-90 0 0\"/\u003e\n\u003c/a-scene\u003e\n```\n\nEven better: Svelte's reactivity mechanisms work as usual:\n\n```html\n\u003cscript\u003e\n  let BoxIsVisible = false\n  setTimeout(() =\u003e { BoxIsVisible = true }, 5000)\n\n  let Angle = 45\n  setInterval(() =\u003e { Angle++ }, 100)\n\u003c/script\u003e\n\n\u003ca-scene a-svelte-system\u003e\n  \u003ca-sky color=\"#ECECEC\"/\u003e\n  {#if BoxIsVisible}\n    \u003ca-box color=\"#4CC3D9\"\n      position=\"0 0.5 -3\" rotation=\"0 {Angle} 0\"/\u003e\n  {/if}\n  \u003ca-plane width=\"4\" height=\"4\" color=\"#7BC8A4\"\n    position=\"0 0 -4\" rotation=\"-90 0 0\"/\u003e\n\u003c/a-scene\u003e\n```\n\nNote: while the rotation animation shown above works (and illustrates that you don't have to synchronize your business logic with the 3D rendering loop) using A-Frame's `animation` component should be preferred.\n\n## Implementing an A-Frame Component within Svelte ##\n\nA-Frame provides a mechanism for [adding new \"components\"](https://aframe.io/docs/1.3.0/introduction/writing-a-component.html) - this mechanism still works within a Svelte application.\n\nJust [implement the new A-Frame component](https://aframe.io/docs/1.3.0/core/component.html) in a separate JavaScript (or TypeScript) file:\n\n```javascript\nimport \"aframe\"\n\nAFRAME.registerComponent('a-svelte-component',{\n  ... // add your specification and implementation here\n})\n```\n\nand import it into your Svelte application. From then on it may be added to A-Frame elements as usual:\n\n```html\n\u003cscript context=\"module\"\u003e\n  import \"aframe\"\n  import \"./aframe-component.js\"\n\u003c/script\u003e\n\n\u003ca-scene\u003e\n  \u003ca-sky color=\"#ECECEC\"/\u003e\n\n  \u003ca-box a-svelte-component=\"...\" color=\"#4CC3D9\"\n    position=\"0 0.5 -3\" rotation=\"0 {Angle} 0\"/\u003e\n\n  \u003ca-plane width=\"4\" height=\"4\" color=\"#7BC8A4\"\n    position=\"0 0 -4\" rotation=\"-90 0 0\"\n  /\u003e\n\u003c/a-scene\u003e\n```\n\n## Implementing an A-Frame System within Svelte ##\n\nA-Frame also provides a mechanism for adding new \"systems\" - and, again, this mechanism also works within a Svelte application.\n\nJust [implement the new A-Frame system]([https://aframe.io/docs/1.3.0/core/component.html](https://aframe.io/docs/1.3.0/core/systems.html)) in a separate JavaScript (or TypeScript) file:\n\n```javascript\nimport \"aframe\"\n\nAFRAME.registerSystem('a-svelte-system',{\n  ... // add your specification and implementation here\n})\n\nAFRAME.registerComponent('a-svelte-system',{\n  ... // add your specification and implementation here\n})\n```\n\nand import it into your Svelte application. From then on it may be added to A-Frame as usual:\n\n```html\n\u003cscript context=\"module\"\u003e\n  import \"aframe\"\n  import \"./aframe-system.js\"\n\u003c/script\u003e\n\n\u003ca-scene a-svelte-system=\"...\"\u003e\n  \u003ca-sky color=\"#ECECEC\"/\u003e\n\n  \u003ca-box a-svelte-system=\"...\" color=\"#4CC3D9\"\n    position=\"0 0.5 -3\" rotation=\"0 {Angle} 0\"/\u003e\n\n  \u003ca-plane width=\"4\" height=\"4\" color=\"#7BC8A4\"\n    position=\"0 0 -4\" rotation=\"-90 0 0\"\n  /\u003e\n\u003c/a-scene\u003e\n```\n\n## Implementing an A-Frame Primitive within Svelte ##\n\nYou may even [implement new A-Frame \"primitives\"](https://aframe.io/docs/1.3.0/introduction/html-and-primitives.html) within Svelte.\n\nAs before, implement the primitive in a separate JavaScript (or TypeScript) file:\n\n```javascript\nimport \"aframe\"\n\nAFRAME.registerPrimitive('a-svelte-primitive',{\n  defaultComponents: { /* ... */ },\n  mappings:          { /* ... */ }\n})\n```\n\nand import it into your Svelte application where it may be used like any other A-Frame tag:\n\n```html\n\u003cscript context=\"module\"\u003e\n  import \"aframe\"\n  import \"./aframe-primitive.js\"\n\u003c/script\u003e\n\n\u003ca-scene a-svelte-system=\"...\"\u003e\n  \u003ca-sky color=\"#ECECEC\"/\u003e\n\n  \u003ca-svelte-primitive position=\"0 0.5 -3\" rotation=\"0 {Angle} 0\"/\u003e\n\n  \u003ca-plane width=\"4\" height=\"4\" color=\"#7BC8A4\"\n    position=\"0 0 -4\" rotation=\"-90 0 0\"\n  /\u003e\n\u003c/a-scene\u003e\n```\n\n## Using a Svelte Component as an A-Frame Entity ##\n\nSvelte may also be used to implement new A-Frame entities in order to benefit from Svelte features like [stores](https://svelte.dev/tutorial/writable-stores), [actions](https://svelte.dev/tutorial/actions), [contexts](https://svelte.dev/tutorial/context-api) and [component composition](https://svelte.dev/tutorial/slots).\n\nJust implement an ordinary Svelte component in a separate `.svelte` file and import A-Frame as usual:\n\n```html\n\u003cscript context=\"module\"\u003e\n  import \"aframe\"\n\u003c/script\u003e\n\n\u003cscript\u003e\n  export let color = 'red'\n\u003c/script\u003e\n\n\u003ca-entity geometry=\"primitive:box\" material=\"color:{color}\"\n  {...$$restProps} /\u003e\n```\n\nWithin the Svelte application you may then import and use the Svelte component as usual:\n\n```html\n\u003cscript context=\"module\"\u003e\n  import \"aframe\"\n  import AFrameEntity from './AFrameEntity.svelte'\n\u003c/script\u003e\n\n\u003cscript\u003e\n  let color = 'blue'\n\u003c/script\u003e\n\n\u003ca-scene a-svelte-system\u003e\n  \u003ca-sky color=\"#ECECEC\"/\u003e\n\n  \u003cAFrameEntity {color} position=\"0 0.5 -3\" rotation=\"0 45 0\"/\u003e\n\n  \u003ca-plane width=\"4\" height=\"4\" color=\"#7BC8A4\"\n    position=\"0 0 -4\" rotation=\"-90 0 0\"\n  /\u003e\n\u003c/a-scene\u003e\n```\n\n## License ##\n\n[MIT License](LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frozek%2Faframe-within-svelte","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frozek%2Faframe-within-svelte","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frozek%2Faframe-within-svelte/lists"}