Embedding Add-ons As Single Page Apps (SPAs)

In addition to iframes, add-ons can be added to Cobot as single page apps using only JavaScript and CSS running in the browser. This works by your add-on providing Cobot with URLs to JavaScript and CSS files. Cobot will render link/script tags referencing these URLs on a dedicated page in the Cobot web UI.

Iframes are becoming increasingly problematic to use as browsers stop sending cookies to iframes when the domain of the iframe is not the same as the domain of the outer document (3rd party cookies). This is mostly the case on Cobot, where spaces can set up custom domains and add-ons typically are not hosted under the cobot.me domain. Using SPAs is therefore recommended.

In order to run an SPA on Cobot, the following steps must be taken:

  • the JS/CSS files that comprise the SPA need to be hosted somewhere on the Internet
  • you need to create an SPA on Cobot via the API, passing the URLs of your JS/CSS files
  • when the code of your SPA changes, you need to change the URLs and tell Cobot about those
  • for each space wanting to use the app on Cobot, you need to create a navigation link via the API
  1. In addition to an SPA that runs in the user's browser, you need some kind of web server/backend to manage creating/updating the SPA and the navigation links.
  2. In order for your backend to communicate with Cobot, it needs to authenticate with Cobot.
  3. If your add-on wants to communicate with services other than Cobot, it needs to authenticate with these as well.

We published an example app on Glitch that re-implements our tip jar add-on - which uses iframes - as an SPA: https://glitch.com/edit/#!/keen-cubic-boat

  • server.js implements the backend
    • src/actions/auth.mjs handles authentication of the backend with Cobot
    • src/actions/install.mjs deals with installing the SPA on Cobot
  • /bot contains the SPA source code

To access the Cobot API from your backend, you first need to authenticate with Cobot. Cobot supports OAUth 2 as well as OpenID Connect. See the API docs home page for more information.

To create an SPA, call the create endpoint, passing it the URLs of any JS/CSS files you need to be loaded for your SPA to work. You only do this once for your add-on.

When the code of your SPA changes, you need to make sure the URLs also change (e.g. filename finderprinting). You then call the update endpoint to tell Cobot about the new URLs.

For every Cobot space that wants to use your add-on, you need to add your SPA to their Cobot site. To do that, you create one or more navigation links, referencing the SPA you created before via the singlePageApp relationship.

Navigation links can be added to one of the admin sections or the member section of a space.

Once a user opens your SPA (the userUrl of the navigation link), the SPA is loaded into the Cobot UI.

Cobot adds an API access token to the page in a meta tag with the name navigation-link-access-token. The token belongs to the user that is currently logged in to Cobot, so you can make API calls in their name/with their permissions.

There are also meta tags called navigation-link-space-id and navigation-link-section so your code knows where on Cobot it is being run.

We want to suggest two ways to access other services:

If the service you want to use supports it, you can ask your users to authenticate with it from within your SPA (e.g. using OAuth), without involving your own backend. You can store any API tokens in a cookie for later use. The drawback here is that the user has to re-authenticate when the token or the cookie expires.

In order for your users to not have to re-authenticate again and again, you can use your own backend as a proxy. After the user has authenticated with the other service once, you store the credentials in your backend's database, under the Cobot id of the current user.

To get the Cobot user id, call the user endpoint with the access token you got from the meta tag above.

To retrieve the other service's credentials later, again fetch the user id from Cobot and look up the credentials in your database. Then either serve the credentials to the SPA so it can make requests directly, or make requests in your backend and only serve your SPA the data response data.

back to index