@juuno-sdk/iframe-app-react
v1.1.0
Published
React SDK for building iframe-based Juuno apps (v0, Vercel, etc.)
Readme
@juuno-sdk/iframe-app-react
React SDK for building iframe-based Juuno apps. Use this for apps built with v0, Vercel, or any React framework that will be embedded in the Juuno player via iframe.
Installation
npm install @juuno-sdk/iframe-app-reactQuick Start
import { useJuuno } from '@juuno-sdk/iframe-app-react';
export default function MyApp() {
const { isActive, isPaused, duration } = useJuuno();
if (!isActive) {
return <div>Waiting...</div>;
}
return <Game duration={duration} paused={isPaused} />;
}API
useJuuno(defaultDuration?, callbacks?)
| Parameter | Type | Default | Description |
| ----------------- | ---------------- | ------- | --------------------------------------- |
| defaultDuration | number | 30000 | Duration in ms when running standalone |
| callbacks | JuunoCallbacks | - | Optional callbacks for lifecycle events |
Returns:
| Property | Type | Description |
| ------------ | --------- | ----------------------------------------------------- |
| isActive | boolean | true when scene is active (playing or paused) |
| isPaused | boolean | true when player is paused |
| duration | number | Scene duration in milliseconds |
| resetCount | number | Increments each reset - use to restart effects |
State Model:
| State | isActive | isPaused | Description |
| ----------- | -------- | -------- | ------------------------------ |
| Waiting | false | false | Scene not started or was reset |
| Playing | true | false | Actively running |
| Paused | true | true | Active but frozen |
Derive isPlaying if needed: const isPlaying = isActive && !isPaused
Callbacks:
| Callback | Arguments | Description |
| ---------- | ----------------------------------------- | -------------------------- |
| onStart | { duration: number, timestamp: number } | Scene became visible |
| onReset | - | Scene hidden, should reset |
| onPause | - | Player paused |
| onResume | - | Player resumed |
How It Works
When your app runs inside the Juuno player:
- App loads inside an iframe and displays a "waiting" state
- Juuno sends a
startsignal when the scene becomes visible - Your app starts running with the scene
duration - If the user pauses the player, Juuno sends
pause/resumesignals - Juuno sends a
resetsignal when the scene ends - Your app returns to the waiting state for the next cycle
When running standalone (for local development):
isActiveistrueimmediatelyisPausedis alwaysfalsedurationuses the default value
Examples
Basic Usage
import { useJuuno } from '@juuno-sdk/iframe-app-react';
export default function MyApp() {
const { isActive, isPaused, duration } = useJuuno();
if (!isActive) {
return <div className="loading">Waiting...</div>;
}
return (
<div className="app">
{isPaused && <div className="paused-overlay">Paused</div>}
<Game duration={duration} paused={isPaused} />
</div>
);
}Using Callbacks
import { useJuuno } from '@juuno-sdk/iframe-app-react';
import { useRef } from 'react';
export default function VideoApp() {
const videoRef = useRef<HTMLVideoElement>(null);
const { isActive, duration } = useJuuno(30000, {
onStart: () => {
videoRef.current?.play();
},
onReset: () => {
if (videoRef.current) {
videoRef.current.pause();
videoRef.current.currentTime = 0;
}
},
onPause: () => {
videoRef.current?.pause();
},
onResume: () => {
videoRef.current?.play();
},
});
if (!isActive) {
return <div>Loading video...</div>;
}
return <video ref={videoRef} src="/video.mp4" />;
}Using resetCount for Animations
import { useJuuno } from '@juuno-sdk/iframe-app-react';
import { useEffect, useState } from 'react';
export default function AnimatedApp() {
const { isActive, isPaused, resetCount, duration } = useJuuno();
const [items, setItems] = useState<string[]>([]);
// Restart animation when scene resets.
useEffect(() => {
if (!isActive) return;
setItems([]);
const timeouts: NodeJS.Timeout[] = [];
const itemsToShow = ['First', 'Second', 'Third'];
itemsToShow.forEach((item, index) => {
const delay = (duration / itemsToShow.length) * index;
timeouts.push(
setTimeout(() => setItems((prev) => [...prev, item]), delay),
);
});
return () => timeouts.forEach(clearTimeout);
}, [isActive, resetCount, duration]);
if (!isActive) return <div>Waiting...</div>;
return (
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
);
}v0 Integration Prompt
Use this prompt when creating a new Juuno app with v0:
Add Juuno player integration to this app using @juuno-sdk/iframe-app-react.
Install: npm install @juuno-sdk/iframe-app-react
Use the useJuuno hook:
const { isActive, isPaused, duration, resetCount } = useJuuno();
Requirements:
1. Show a waiting/loading state when !isActive
2. Pause animations/timers when isPaused is true
3. Use duration to time content to fit the scene length
4. Use resetCount as a useEffect dependency to restart animations when the scene cycles
5. Derive isPlaying if needed: const isPlaying = isActive && !isPaused
State model:
- isActive: false, isPaused: false → Waiting (show loading state)
- isActive: true, isPaused: false → Playing (run animations)
- isActive: true, isPaused: true → Paused (freeze state, don't reset)License
MIT
