Skip to content

Quick Start Guide ​

This guide walks you through integrating <oim-player> into your web applications, from plain HTML to modern frontend frameworks.


1. Quickest Path: Plain HTML & CDN ​

The fastest way to embed interactive .oim files is using our pre-compiled Web Component script loaded directly via CDN:

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>OIM Interactive Media</title>
  <!-- Load the OIM Player Web Component -->
  <script src="https://cdn.oim.media/player/v1/oim-player.js"></script>
</head>
<body>

  <!-- Embed interactive image (a signed demo in Spanish and English) -->
  <oim-player 
    src="https://cdn.oim.media/demo/imagen-muestra.oim.png"
    lang="en"
    mode="full"
    fit="contain"
    style="max-width: 800px; height: 600px; display: block; margin: 0 auto;">
  </oim-player>

</body>
</html>

Stable URL and caching

/player/v1/ is the stable path: it stays compatible for as long as the major version is 1. Browsers cache the script for up to 4 hours, so an update can take that long to reach a returning visitor.

Opening the .oim.png file directly vs. using <oim-player>

An .oim file is a valid standard PNG image where the base visual background is stored in Layer −1 (Baked Image) and all interactive typography, buttons, and multilingual texts are stored in the Layer +1 (Dynamic) metadata chunk.

  • If you open https://cdn.oim.media/demo/imagen-muestra.oim.png directly in your browser's address bar (or with <img>), the browser's default image viewer only renders the static background image without text.
  • To decode and render the dynamic text, multilingual switching, and animations, the file must be embedded using <oim-player> (as shown in the code snippet above).

Where to host your .oim

The player downloads the file with fetch, so the server must allow your page's origin (CORS). The demo above is served from cdn.oim.media, which allows any origin.

Cloud Hosting & CDN Embeds

When hosted at an authorized embed endpoint (e.g. https://embed.oim.media/<id>.oim.png), the file is served from global edge caches with permissive CORS headers, providing embed-ready code for any website.

Self-hosting the player

If you copy oim-player.js to your own server, copy the vendor/ folder next to it as well. The player fetches Lottie from there only when a .oim contains a Lottie layer.


2. Modern Package Installation ​

If you are using a bundler (Vite, Webpack, Rollup) or a component framework, install @oim-media/player-oim:

Package Availability

@oim-media/player-oim is available through the private workspace and npm registry. Always use pnpm within the OIM ecosystem repository.

bash
# Using pnpm (recommended)
pnpm add @oim-media/player-oim

# Or using npm
npm install @oim-media/player-oim

In your main entry file (e.g. main.ts or index.js), import the package to register the custom element:

typescript
import '@oim-media/player-oim';

// The <oim-player> element is now registered in window.customElements

3. Production Framework Integrations ​

Vanilla TypeScript / JavaScript ​

typescript
import '@oim-media/player-oim';

const player = document.querySelector('oim-player') as any;

// Listen for metadata loading and signature verification
player.addEventListener('oim:loaded', (event: CustomEvent) => {
  const { metadata, security } = event.detail;
  console.log(`Document loaded. Security status: ${security}`);
  console.log(`Available languages:`, player.languages);
});

// Intercept interactive user actions
player.addEventListener('oim:action', (event: CustomEvent) => {
  console.log(`User interacted with slot: ${event.detail.slot}`);
  
  // Custom business logic: prevent default internal state change if needed
  if (event.detail.slot === 'purchase_btn') {
    event.preventDefault(); // Vetoes internal DOM state mutation
    openCheckoutModal();
  }
});

// Imperative language switching
function switchLanguage(code: string) {
  player.setLang(code);
}

React 18 / 19 & Next.js ​

Because Custom Elements accept attributes as strings and dispatch custom DOM events, wrap <oim-player> with a typed React component:

tsx
import React, { useEffect, useRef } from 'react';
import '@oim-media/player-oim';

// Extend JSX IntrinsicElements for TypeScript
declare global {
  namespace JSX {
    interface IntrinsicElements {
      'oim-player': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
        src?: string;
        lang?: string;
        mode?: 'full' | 'image';
        fit?: 'contain' | 'cover';
        align?: 'center' | 'top' | 'bottom';
        'allow-dynamic-colors'?: 'true' | 'false';
        'activate-on'?: 'visible' | 'hover' | 'manual';
      };
    }
  }
}

interface OimViewerProps {
  src: string;
  lang?: string;
  onAction?: (slotId: string, targets: string[]) => void;
}

export function OimViewer({ src, lang = 'en', onAction }: OimViewerProps) {
  const playerRef = useRef<HTMLElement>(null);

  useEffect(() => {
    const el = playerRef.current;
    if (!el) return;

    const handleAction = (e: any) => {
      onAction?.(e.detail.slot, e.detail.targets);
    };

    el.addEventListener('oim:action', handleAction);
    return () => el.removeEventListener('oim:action', handleAction);
  }, [onAction]);

  return (
    <div style={{ width: '100%', height: '500px' }}>
      <oim-player
        ref={playerRef}
        src={src}
        lang={lang}
        mode="full"
        fit="contain"
      />
    </div>
  );
}

Vue 3 ​

In your vite.config.ts, inform Vue that <oim-player> is a native custom element:

typescript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => tag.startsWith('oim-') || tag.startsWith('ovm-'),
        },
      },
    }),
  ],
});

Then use it seamlessly in single-file components:

vue
<script setup lang="ts">
import { ref } from 'vue';
import '@oim-media/player-oim';

const currentLang = ref('en');

function onOimAction(event: any) {
  console.log('Action triggered:', event.detail.slot);
}
</script>

<template>
  <div class="player-container">
    <div class="controls">
      <button @click="currentLang = 'en'">English</button>
      <button @click="currentLang = 'es'">Español</button>
    </div>

    <oim-player
      :src="'/media/sample.oim.png'"
      :lang="currentLang"
      mode="full"
      @oim:action="onOimAction"
    />
  </div>
</template>

4. Key Attributes Reference ​

AttributeTypeDefaultDescription
srcstring""URL to .oim.png or assigned Blob.
langstring"en"Active language code to resolve in slot.content.
mode"full" | "image""image""full" activates WAAPI animations and interactive click/hover states. "image" preserves static fidelity.
fit"contain" | "cover""contain"How the baked base image (Layer −1) fits inside the player container.
align"center" | "top" | "bottom""center"Alignment of the artwork inside the container box.
activate-on"visible" | "hover" | "manual""visible"Whether animations play when scrolled into view, only on pointer hover (hover), or only when the page calls play() (manual).
allow-dynamic-colors"true" | "false""true"When "true", resolves --oim-color-* CSS variables.