Multi-Framework Integrations Guide
<oim-player> and <ovm-player> are standard W3C Custom Elements that integrate seamlessly into any modern frontend framework. Below are production-ready code patterns for each popular web stack.
1. React 19 & Next.js (App Router / Pages)
In React applications, register the web component inside an effect to ensure client-side hydration:
tsx
'use client';
import React, { useEffect, useRef } from 'react';
import '@oim-media/player-oim';
interface OimViewerProps {
src: string;
lang?: string;
onAction?: (actionName: 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: Event) => {
const customEvent = e as CustomEvent;
if (onAction) {
onAction(customEvent.detail.name);
}
};
el.addEventListener('oim:action', handleAction);
return () => el.removeEventListener('oim:action', handleAction);
}, [onAction]);
return (
<div className="w-full max-w-2xl mx-auto">
{/* @ts-expect-error custom-element */}
<oim-player ref={playerRef} src={src} lang={lang} fit="contain" />
</div>
);
}2. Vue 3 (Composition API / Nuxt 3)
Vue handles custom elements natively. Ensure your compiler options recognize oim- tags:
vue
<template>
<div class="player-container">
<oim-player
ref="playerRef"
:src="src"
:lang="activeLang"
fit="contain"
@oim:action="handleAction"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import '@oim-media/player-oim';
const props = defineProps<{ src: string }>();
const activeLang = ref('en');
const playerRef = ref<HTMLElement | null>(null);
const handleAction = (e: CustomEvent) => {
console.log('Action selected:', e.detail.name);
};
</script>3. Svelte 5 & SvelteKit
Dynamic client import ensures server-side rendering (SSR) does not attempt to evaluate custom element definitions:
svelte
<script lang="ts">
import { onMount } from 'svelte';
export let src: string;
export let lang: string = 'en';
onMount(async () => {
await import('@oim-media/player-oim');
});
</script>
<div class="oim-wrapper">
<oim-player {src} {lang} fit="contain"></oim-player>
</div>
<style>
.oim-wrapper {
width: 100%;
aspect-ratio: 16 / 9;
}
</style>4. Astro (Island Architecture)
In Astro, <script> tags run exclusively on the client, providing zero hydration cost:
astro
---
interface Props {
src: string;
lang?: string;
}
const { src, lang = 'en' } = Astro.props;
---
<div class="interactive-card">
<oim-player src={src} lang={lang} fit="contain"></oim-player>
</div>
<script>
import '@oim-media/player-oim';
</script>5. Vanilla JavaScript & HTML5
No bundler or build step is required for standard web pages:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script type="module" src="https://cdn.oim.media/player/v1/oim-player.js"></script>
</head>
<body>
<oim-player
id="myPromo"
src="/media/hero.oim.png"
lang="en"
fit="cover">
</oim-player>
<script>
const player = document.getElementById('myPromo');
player.addEventListener('oim:loaded', () => {
console.log('OIM Ready!');
});
</script>
</body>
</html>