Integration with React.js and Vue.js — Soft8Soft
Description: Learn how to integrate a Verge3D application into a React.js/Vue.js project.

# Integration with React.js/Vue.js

One of the easiest way of integrating a Verge3D scene into your project is to load it separately through an `<iframe>` HTML element. But if you want to use it directly inside your app then there could appear some difficulties along the way. However, there are plenty of possible project configurations with their specific issues and peculiarities. This guide can't comprehend them all and only targets such popular JavaScript frameworks as React.js and Vue.js.

There are simple React and Vue.js demos available in the Verge3D Asset Store. If you want to check out how to create a React/Vue.js + Verge3D app from scratch, follow the guide below.

Verge3D provides an example of how to make a simple "Hello, world!" React or Vue project and integrate a standard Verge3D application into it. The relevant files are located inside the Verge3D distribution: for Blender - manager/templates/Embeddable, for Max - manager/templates/Embeddable-Max, for Maya - manager/templates/Embeddable-Maya.

- Verge3D React.js Application Example
- Verge3D Vue.js Application Example
- Using the Puzzles Editor

#

## Verge3D React.js Application Example

Here's a simple instruction on how to create a basic React.js + Verge3D application with the Create React App utility. You can find a copy of this instruction in manager/templates/Embeddable/README.md inside the Verge3D distribution.

1) Create a React.js application via the Create React App utility:

`npx create-react-app react-app-example`

2) Enter the react-app-example directory and install the verge3d npm package:

`cd react-app-example npm i verge3d`

3) Copy the following files from Verge3D distribution into your app:

- the contents of Verge3D's manager/templates/Embeddable/public directory to react-app-example/public
- the contents of Verge3D's manager/templates/Embeddable/src directory to react-app-example/src

or use the commands below:

Linux/macOS/ChromeOS

Change V3D_PATH and MY_PATH to where the Verge3D distribution and your React application are located respectively.

`V3D_PATH=/path/to/v3d/distribution MY_PATH=/path/to/my/react/app cp -r $V3D_PATH/manager/templates/Embeddable/public/* $MY_PATH/public/ cp -r $V3D_PATH/manager/templates/Embeddable/src/* $MY_PATH/src/`
Windows (PowerShell)

Change V3D_PATH and MY_PATH to where the Verge3D distribution and your React application are located respectively.

`$V3D_PATH = "path\to\v3d\distribution" $MY_PATH = "path\to\my\react\app" Copy-Item -Path "$V3D_PATH\manager\templates\Embeddable\public\*" -Destination "$MY_PATH\public" -Recurse Copy-Item -Path "$V3D_PATH\manager\templates\Embeddable\src\*" -Destination "$MY_PATH\src" -Recurse`

4) Create a file called react-app-example/src/V3DApp.js with the following content:

`import React from 'react'; import { createApp } from './v3dApp/app'; import './v3dApp/app.css'; class V3DApp extends React.Component { #app = null; #PL = null; #uuid = window.crypto.randomUUID(); #containerId = `v3d-container-${this.#uuid}`; #fsButtonId = `fullscreen-button-${this.#uuid}`; #sceneURL = 'v3dApp/app.gltf'; async loadApp() { ({ app: this.#app, PL: this.#PL } = await createApp({ containerId: this.#containerId, fsButtonId: this.#fsButtonId, sceneURL: this.#sceneURL, })); } disposeApp() { this.#app?.dispose(); this.#app = null; // dispose Puzzles' visual logic this.#PL?.dispose(); this.#PL = null; } reloadApp() { this.disposeApp(); this.loadApp(); } componentDidMount() { this.loadApp(); } componentWillUnmount() { this.disposeApp(); } render() { return <div id={this.#containerId}> <div id={this.#fsButtonId} className="fullscreen-button fullscreen-open" title="Toggle fullscreen mode" ></div> </div>; } } export default V3DApp;`

5) Replace the contents of react-app-example/src/index.js with the following code:

`import React from 'react'; import ReactDOM from 'react-dom/client'; import V3DApp from './V3DApp'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(<V3DApp/>);`

6) Run the development server by executing the following command in the react-app-example directory:

`npm start`

By default the application now should be available at http://localhost:3000/.

#

## Verge3D Vue.js Application Example

Here's a simple instruction on how to create a basic Vue.js + Verge3D application with Vite. You can find a copy of this instruction in manager/templates/Embeddable/README.md inside the Verge3D distribution.

1) Create a Vue.js application via Vite:

`npm create vite@latest vue-app-example -- --template vue`

2) Enter the vue-app-example directory and install the verge3d npm package:

`cd vue-app-example npm i verge3d`

3) Copy the following files from Verge3D distribution into your app:

- the contents of Verge3D's manager/templates/Embeddable/public directory to vue-app-example/public
- the contents of Verge3D's manager/templates/Embeddable/src directory to vue-app-example/src

or use the commands below:

Linux/macOS/ChromeOS

Change V3D_PATH and MY_PATH to where the Verge3D distribution and your Vue application are located respectively.

`V3D_PATH=/path/to/v3d/distribution MY_PATH=/path/to/my/vue/app cp -r $V3D_PATH/manager/templates/Embeddable/public/* $MY_PATH/public/ cp -r $V3D_PATH/manager/templates/Embeddable/src/* $MY_PATH/src/`
Windows (PowerShell)

Change V3D_PATH and MY_PATH to where the Verge3D distribution and your Vue application are located respectively.

`$V3D_PATH = "path\to\v3d\distribution" $MY_PATH = "path\to\my\vue\app" Copy-Item -Path "$V3D_PATH\manager\templates\Embeddable\public\*" -Destination "$MY_PATH\public" -Recurse Copy-Item -Path "$V3D_PATH\manager\templates\Embeddable\src\*" -Destination "$MY_PATH\src" -Recurse`

4) Create a file vue-app-example/src/components/V3DApp.vue containing the following code:

Vue 3 `<template> <div :id="containerId"> <div :id="fsButtonId" class="fullscreen-button fullscreen-open" title="Toggle fullscreen mode" ></div> </div> </template> <script> import { createApp } from '../v3dApp/app'; export default { name: 'V3DApp', created() { this.app = null; this.PL = null, this.uuid = window.crypto.randomUUID(); this.containerId = `v3d-container-${this.uuid}`; this.fsButtonId = `fullscreen-button-${this.uuid}`; this.sceneURL = 'v3dApp/app.gltf'; this.loadApp = async function() { ({ app: this.app, PL: this.PL } = await createApp({ containerId: this.containerId, fsButtonId: this.fsButtonId, sceneURL: this.sceneURL, })); } this.disposeApp = function() { this.app?.dispose(); this.app = null; // dispose Puzzles' visual logic this.PL?.dispose(); this.PL = null; } this.reloadApp = function() { this.disposeApp(); this.loadApp(); } }, mounted() { this.loadApp(); }, beforeUnmount() { this.disposeApp(); }, } </script> <style> @import '../v3dApp/app.css'; </style>` Vue 2 `<template> <div :id="containerId"> <div :id="fsButtonId" class="fullscreen-button fullscreen-open" title="Toggle fullscreen mode" ></div> </div> </template> <script> import { createApp } from '../v3dApp/app'; export default { name: 'V3DApp', created() { this.app = null; this.PL = null, this.uuid = window.crypto.randomUUID(); this.containerId = `v3d-container-${this.uuid}`; this.fsButtonId = `fullscreen-button-${this.uuid}`; this.sceneURL = 'v3dApp/app.gltf'; this.loadApp = async function() { ({ app: this.app, PL: this.PL } = await createApp({ containerId: this.containerId, fsButtonId: this.fsButtonId, sceneURL: this.sceneURL, })); } this.disposeApp = function() { this.app?.dispose(); this.app = null; // dispose Puzzles' visual logic this.PL?.dispose(); this.PL = null; } this.reloadApp = function() { this.disposeApp(); this.loadApp(); } }, mounted() { this.loadApp(); }, beforeDestroy() { this.disposeApp(); }, } </script> <style> @import '../v3dApp/app.css'; </style>`

5) Replace the contents of vue-app-example/src/App.vue with the following code:

`<template> <V3DApp></V3DApp> </template> <script> import V3DApp from './components/V3DApp.vue'; export default { name: 'App', components: { V3DApp, }, } </script>`

6) Run the development server by executing the following command in the vue-app-example directory:

`npm run dev`

By default the application now should be available at http://localhost:5173/.

#

## Using the Puzzles Editor

There's no direct integration between React/Vue and the Puzzles Editor/App Manager. Nevertheless, you can still use Puzzles for adding behavior scenarios to your React/Vue applications. This section explains how to do that and what are the limitations of the chosen approach.

### App Manager Setup

Suppose you have a React or a Vue application created according to the guide described in this manual. In order to "connect" the App Manager and the React/Vue project you need to copy a dedicated `adapter` application from the "Embeddable" template directory to your Vue/React project. Additionally, copy `v3d.js` engine runtime to the `adapter` folder.

`cp -rv manager/template/Embeddable/adapter /path/to/my_awesome_app cp build/v3d.js /path/to/my_awesome_app/adapter`

Now you can see your project in the App Manager and you can use the Puzzles Editor.

### Loading Resources in Puzzles

Such puzzles as replace texture, load scene, load sound, load video, load data, etc... may require to specify URLs to load textures, media and other kinds of files.

When using the Puzzles Editor with a React/Vue application all file paths specified in such puzzles are calculated relatively to the app root path which usually points to the app's public directory. If the Puzzles Editor was integrated with a React/Vue application the way described in this manual then the Editor can only access the app's public/v3dApp directory.

So, if, for example, we want to load a sound file via puzzles, then that file, let's name it sound.mp3, should be placed inside the public/v3dApp directory (or its subdirectories). After that the file can be loaded by using v3dApp/mySound.mp3 inside the URL field in the load sound puzzle: