Web Design Guidelines
Core Design Philosophy
Designing for the Agent Board requires a shift from traditional web development to Frame-Driven Design. Because the final output is a rendered video, all visual changes must be deterministic and synchronized with Remotion's timeline.
Frame-Driven Execution
The most critical rule in Agent Board design is that the UI must be a function of the current frame. You must use the useCurrentFrame() hook to drive all visual state.
import { useCurrentFrame, useVideoConfig, interpolate } from 'remotion';
export const MyDesign = () => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// Calculate values based on the frame
const opacity = interpolate(frame, [0, fps], [0, 1], {
extrapolateRight: 'clamp',
});
return <div style={{ opacity }}>Agent Output</div>;
};
Animation Guidelines
Standard web animation techniques often fail in a video rendering context because they rely on the browser's refresh rate rather than the video's frame rate.
Forbidden Techniques
- CSS Transitions:
transition: all 0.3swill not render correctly. - CSS Keyframes:
@keyframesanimations are forbidden. - Tailwind Animation Classes: Classes like
animate-bounceoranimate-pulsemust not be used. - SetTimeout/SetInterval: Never use timers to trigger visual changes.
Recommended Techniques
Use Remotion's interpolation and spring primitives to create smooth, frame-accurate motion.
- Interpolate: For linear or mapped transitions.
- Spring: For natural-feeling physics (e.g., scale-ups, slides).
import { spring, useCurrentFrame, useVideoConfig } from 'remotion';
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const scale = spring({
frame,
fps,
config: { stiffness: 100 },
});
<div style={{ transform: `scale(${scale})` }} />
Layout and Styling
Tailwind CSS
Tailwind is fully supported for static layout and styling (colors, padding, flexbox, grid). However, remember to avoid any Tailwind classes that involve motion or transitions.
Composition Dimensions
Design your layouts relative to the width and height provided by useVideoConfig(). This ensures the UI scales correctly if the composition resolution changes.
const { width, height } = useVideoConfig();
return (
<div style={{ width, height }} className="bg-slate-900 flex items-center justify-center">
{/* Content */}
</div>
);
Typography and Fonts
To prevent layout shifts during rendering, fonts must be loaded before the first frame is captured.
Google Fonts
Use the @remotion/google-fonts package for type-safe, pre-loaded typography.
import { loadFont } from '@remotion/google-fonts/Inter';
const { fontFamily } = loadFont();
export const TextElement = () => {
return <div style={{ fontFamily }}>Hello Agent</div>;
};
Assets and Media Handling
The staticFile() Helper
Always use staticFile() when referencing assets in the public/ folder. This ensures paths are resolved correctly during both development and cloud rendering.
import { Img, staticFile } from 'remotion';
<Img src={staticFile('agent-avatar.png')} />
Media Components
Always use the specialized media components from @remotion/media and remotion to ensure the renderer waits for assets to buffer:
- Use
<Img />instead of<img>. - Use
<Video />instead of<video />. - Use
<Audio />instead of<audio />.
Data Visualization
When creating charts or dashboards, do not use the built-in animations provided by charting libraries (like Recharts or D3 transitions).
- Disable Library Animations: Set
isAnimationActive={false}or equivalent. - Manual Control: Manually animate the data points or container heights using
useCurrentFrame().
Staggered Animations
For lists or bar charts, stagger the entrance of elements by offsetting the frame calculation:
{data.map((item, i) => {
const progress = spring({
frame: frame - i * 5, // 5 frame delay per item
fps,
});
return <Bar height={item.value * progress} />;
})}
3D Content (Three.js)
If the Agent Board requires 3D elements, follow these constraints:
- Canvas Wrapper: Wrap 3D content in
<ThreeCanvas>from@remotion/three. - No useFrame: The
@react-three/fiberuseFramehook is forbidden. - Manual Rotation/Motion: Drive mesh properties (position, rotation) directly from
useCurrentFrame(). - Sequence Layout: Set
layout="none"for any<Sequence>components nested inside a 3D canvas.