Developer documentation

Framework and deployment examples

Use the same browser loader in custom HTML, JavaScript, React, Next.js and Svelte.

HTML and page builders

Replace EXPERIENCE_ID with your own published UUID in these examples. Use the loader origin from the same environment’s generated snippet.

Custom HTML block
<div data-rapideye-experience="EXPERIENCE_ID"></div>
<script async src="https://www.rapideye.ai/embed/v1.js"></script>

Use a custom HTML feature that permits external scripts and iframes. The required editor permissions depend on your provider and plan; this guide does not assume a provider-specific setting.

If a page builder strips scripts, place the loader in its supported site-code location and retain the experience container in the page. Do not load the same loader origin multiple times intentionally.

Custom element
<rapideye-experience experience-id='EXPERIENCE_ID'></rapideye-experience>
<script async src='https://www.rapideye.ai/embed/v1.js'></script>

The custom element uses the same frame and loader. Configure its experience-id before connecting it; removal performs controller cleanup.

Create one browser loading helper

For the framework examples, create load-rapideye.js in your own project with this helper. This is integration sample code, not a RapidEye package or SDK.

load-rapideye.js
let pending;
let pendingOrigin;

export function loadRapidEye(loaderUrl) {
  const expectedOrigin = new URL(loaderUrl, location.href).origin;
  if (window.RapidEye?.version === '1') {
    return window.RapidEye.origin === expectedOrigin
      ? Promise.resolve(window.RapidEye)
      : Promise.reject(new Error('A different RapidEye origin is already loaded.'));
  }
  if (pending) {
    return pendingOrigin === expectedOrigin
      ? pending
      : Promise.reject(new Error('Load one RapidEye origin per page.'));
  }
  pendingOrigin = expectedOrigin;
  pending = new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = loaderUrl;
    script.async = true;
    script.addEventListener('load', () => {
      if (window.RapidEye?.version === '1' && window.RapidEye.origin === expectedOrigin) {
        resolve(window.RapidEye);
      } else {
        pending = undefined;
        script.remove();
        reject(new Error('The RapidEye loader did not initialize.'));
      }
    }, { once: true });
    script.addEventListener('error', () => {
      pending = undefined;
      script.remove();
      reject(new Error('Could not load RapidEye.'));
    }, { once: true });
    document.head.appendChild(script);
  });
  return pending;
}

Call it only in the browser. Pass the full loader URL from Copy snippet for your environment. It shares one pending load and refuses a conflicting origin.

Plain JavaScript

Create a container with id player and include this code in your application’s browser module. This programmatic container does not need the auto-mount data attribute.

Browser module
import { loadRapidEye } from './load-rapideye.js';

const api = await loadRapidEye('https://www.rapideye.ai/embed/v1.js');
const embed = api.mount(document.querySelector('#player'), {
  experienceId: 'EXPERIENCE_ID',
});
embed.on('ready', ({ revision }) => console.log('Published revision', revision));
// Before your application removes this instance: embed.destroy();

React and Next.js client components

Mount the browser widget inside an effect and destroy it on cleanup. A cancellation flag prevents a delayed script load from mounting after component removal.

RapidEyePlayer.jsx
'use client';
import { useEffect, useRef } from 'react';
import { loadRapidEye } from './load-rapideye.js';

export default function RapidEyePlayer({ experienceId }) {
  const container = useRef(null);
  useEffect(() => {
    let removed = false;
    let embed;
    loadRapidEye('https://www.rapideye.ai/embed/v1.js').then(api => {
      if (!removed && container.current) {
        embed = api.mount(container.current, { experienceId });
      }
    }).catch(error => {
      if (!removed) console.error('RapidEye could not load', error);
    });
    return () => {
      removed = true;
      embed?.destroy();
    };
  }, [experienceId]);
  return <div ref={container} />;
}

Pass the published UUID as experienceId. The use client directive supplies the Next.js App Router client boundary; ordinary React applications do not require that directive.

React effect and cleanup reference

Next.js client boundary reference

Svelte browser lifecycle

This Svelte 4-style component loads on mount and returns synchronous cleanup. Keep the async work inside the callback rather than returning an async cleanup function.

RapidEyePlayer.svelte
<script>
  import { onMount } from 'svelte';
  import { loadRapidEye } from './load-rapideye.js';
  export let experienceId;
  let container;

  onMount(() => {
    let removed = false;
    let embed;
    loadRapidEye('https://www.rapideye.ai/embed/v1.js').then(api => {
      if (!removed) embed = api.mount(container, { experienceId });
    }).catch(error => {
      if (!removed) console.error('RapidEye could not load', error);
    });
    return () => {
      removed = true;
      embed?.destroy();
    };
  });
</script>

<div bind:this={container}></div>

Pass the published UUID as experienceId. This example mounts that prop once; recreate the component or explicitly destroy/remount when switching experiences.

Svelte onMount reference

Local, preview and production

  • Copy a snippet from the RapidEye environment you intend to test.
  • Add the exact local hostname and port for local HTTP testing.
  • Add each intended HTTPS preview or production hostname before publication.
  • Use a fresh viewer session and validate the actual page policies.
  • Keep development and production loader origins separate.

A direct runtime iframe bypasses the wrapper’s private-grant handshake, resizing and controller API. Use the documented loader or custom element instead of copying a raw runtime URL.

No dedicated embed hostname is required by the current deployment. Use the generated origin; custom hostname provisioning is an operator concern, not a partner script option.