Incorporating speckle viewer into React.js SPA

I want to use speckle viewer in a web app I’ve built with React. My initial, not so great solution was to use an iframe with the src set to “Speckle” + stream ID. This worked ok for a while but something seems to have broken it, and now users are only seeing a blank viewer with no streams selected (unless they’ve logged into the speckle server before on their machine).

Before I bother pursuing the iframe approach any further, I wanted to see if anyone had any suggestions for a better way to do this. I know there’s things like this GitHub - akxcv/vuera: Vue in React, React in Vue. Seamless integration of the two. that allow you to use vue components in react apps and vice versa, but is this just another dodgy idea? And will it even fix the issue of sharing with others? I’m not familiar enough with the code base to really tell.

Hello @tluther! It really depends on how much time you have on your hands.

To do this properly, I would first create a npm module from the speckle viewer itself (the threejs parts). Right now diffing and loading logic is embedded in the vue component, and, perhaps, it should be extracted out into the module itself.

As an aside / note to self, i’ve upgraded hestia’s proxy to use http2, so all the crazy orchestration to get many objects can be simplified probably.

Once you have that module, you can thereafter use it in your react app - where you will still need to implement authentication to the speckle server in use, but that should be easy. You just need to open a popup to the /signin url of that server, but your app needs to be whitelisted on the server.

That’s probably the proper way. It will take a while. Therefore, I’m asking: what’s broken with the iframe parts, and how can we fix that?

Thanks dimitrie.

At the moment, it seems that I can take a link to a speckle stream in the viewer and open it without logging in/having previous login cookies etc. But if I put the same link in an iframe I end up with a blank viewer.
I notice whenever you open the viewer it generates a token and adds it to the query string. If I copy the whole url with the token and open it in a new browser env its all good, but if I try open it in an iframe, nup.
Whats this token even for? Do I even need to worry about it? Should I be requesting one before launching the iframe and adding it to a query string in the iframe src ?

you nailed it. the appended query string tells the app what server to look at, and if it’s missing it freaks out. it’s easy to generate on your side - it’s just a base64 encoded string :slight_smile:

E.g., from this viewer link, the query string:

eyJzZXJ2ZXIiOiJodHRwczovL2hlc3RpYS5zcGVja2xlLndvcmtzL2FwaSIsImNhbWVyYSI6eyJ0YXJnZXQiOlstOC42Njg4ODk1OTI1NjcwMywtOS4wMTg4NTkzNzA4MDYzMDcsMC4yNjg4NzI1NDU0NzA3NjYxXSwicG9zaXRpb24iOlsxOS40NjQzODYyMTExMzkzMzUsMTkuMTE0NDE2NDMyOTAwMDU0LDI4LjQwMjE0ODM0OTE3NzEwN10sInJvdGF0aW9uIjpbLTAuNzg1Mzk4MTYzMzk3NDQ4NiwwLjYxNTQ3OTcwODY3MDM4NzYsMi42MTc5OTM4Nzc5OTE0OTQ0XX19

is actually this (via window.atob()):

{"server":"https://hestia.speckle.works/api","camera":{"target":[-8.66888959256703,-9.018859370806307,0.2688725454707661],"position":[19.464386211139335,19.114416432900054,28.402148349177107],"rotation":[-0.7853981633974486,0.6154797086703876,2.6179938779914944]}}

It contains extra stuff for camera rotation, filter by stuff, etc.
so all you need to do to get the links working again is encode just this:

let serverQueryObj = { server: "https://THE  SERVER" }
let myLinkUrl = `https://app.speckle.systems/#/${ YOUR STREAM ID }?s=${ window.btoa( JSON.stringify( serverQueryObj ) ) }

Perfect spotting! I didn’t know about your iframe embedding adventures when i made this change. Let me know if it works out!