# How to Use @openmaic/renderer to Render OpenMAIC Slides: A Complete Guide

> Learn how to use the @openmaic/renderer component to render OpenMAIC slides. This guide explains transforming Slide JSON objects into responsive canvas renderings with ease.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: how-to-guide
- Published: 2026-09-02

---

**@openmaic/renderer is a read-only React component library that transforms PPTist-style Slide JSON objects into responsive canvas renderings using the `<SlideCanvas>` component and a pluggable element architecture.**

The `@openmaic/renderer` package, located in the THU-MAIC/OpenMAIC monorepo, provides the definitive rendering engine for OpenMAIC presentation slides. It consumes structured slide data and outputs faithful visual representations without allowing direct editing, making it ideal for slide previewing, presentation mode, or static export scenarios.

## Core Architecture and File Structure

The library is organized around a central canvas component with specialized dispatchers and effect overlays. Understanding these modules helps you customize rendering behavior effectively.

- **`SlideCanvas`** ([`src/SlideCanvas.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/SlideCanvas.tsx)): The main entry point that receives a `Slide` object and renders all slide elements inside an auto-fitting container.
- **`SlideElement`** ([`src/SlideElement.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/SlideElement.tsx)): A wrapper dispatcher that routes each element to its specific renderer, such as `BaseTextElement` or `BaseImageElement`.
- **Effect Overlays** (`src/effects/*`): Optional visual layers including `LaserOverlay`, `SpotlightOverlay`, `HighlightOverlay`, and `ZoomWrapper` that animate on top of rendered content.
- **Context API** ([`src/context.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/context.tsx)): Provides `<SlideRendererProvider>` for sharing slide data across the component tree and `useSlideContext()` for consuming that data.
- **Utility Hooks** (`src/hooks/*`): Contains `useViewportSize` for auto-fit calculations and `useSlideBackgroundStyle` for generating background CSS.
- **Type Definitions** (`src/types/*`): Central TypeScript interfaces including `Slide`, `PPTElement`, `SlideBackground`, and `SlideEffects`.

## Installation and Prerequisites

Before integrating the renderer, ensure your project meets the peer dependency requirements. The package expects **React ≥18**, **Tailwind CSS ≥4**, and **Motion ≥11**.

```bash
npm install @openmaic/renderer

```

Import the optional CJK font stylesheet if your slides contain Chinese, Japanese, or Korean characters.

```typescript
import '@openmaic/renderer/fonts.css';

```

## The Rendering Pipeline

The `@openmaic/renderer` follows a strict five-step flow to convert JSON data into visual output:

1. **Data Ingestion**: A `Slide` object (conforming to the `Slide` type) is passed to `<SlideCanvas>` or supplied via `<SlideRendererProvider>`.
2. **Viewport Calculation**: `SlideCanvas` invokes `useViewportSize` to auto-fit the canvas to its parent container, unless a fixed `scale` prop overrides this behavior.
3. **Element Dispatching**: For each item in `slide.elements`, `SlideCanvas` renders a `<SlideElement>` which delegates to the appropriate base component based on the element type.
4. **Effect Application**: Optional `effects` props trigger overlay components that animate on top of specific elements.
5. **Custom Slot Injection**: Props like `renderImage` and `renderVideo` allow you to inject custom media handling while preserving the default layout pipeline.

## Basic Usage: Rendering a Single Slide

Pass a valid Slide JSON object to the `slide` prop of `SlideCanvas`. The component handles layout, background styling, and element positioning automatically.

```tsx
import { SlideCanvas, type Slide } from '@openmaic/renderer';
import '@openmaic/renderer/fonts.css';

const slide: Slide = {
  id: 'demo-1',
  viewportSize: 1000,
  viewportRatio: 0.5625, // 16:9
  theme: {
    backgroundColor: '#fff',
    themeColors: ['#5b8def'],
    fontColor: '#222',
    fontName: 'sans-serif',
  },
  elements: [
    {
      type: 'text',
      id: 't1',
      left: 100,
      top: 80,
      width: 800,
      height: 60,
      rotate: 0,
      content: '<p>Hello, Slide</p>',
      defaultFontName: 'sans-serif',
      defaultColor: '#222',
    },
  ],
  background: { type: 'solid', color: '#fff' },
};

export default function Demo() {
  return (
    <div style={{ width: 800, height: 450 }}>
      <SlideCanvas
        slide={slide}
        effects={{
          laser: { elementId: 't1', color: '#ff3b30', duration: 1500 },
        }}
      />
    </div>
  );
}

```

### Auto-Fitting and Viewport Handling

By default, `SlideCanvas` uses the `useViewportSize` hook to compute dimensions that maintain the slide's aspect ratio within the parent container. To disable responsive scaling and use a fixed size, provide the `scale` prop with a numeric value between 0 and 1.

## Advanced Patterns

### Using SlideRendererProvider for Context

When multiple components need access to the same slide data—such as annotation layers, navigation controls, or thumbnail strips—wrap them in `<SlideRendererProvider>` instead of passing props manually.

```tsx
import {
  SlideRendererProvider,
  SlideCanvas,
  useSlideContext,
} from '@openmaic/renderer';

function AnnotationLayer() {
  const { slide } = useSlideContext();
  return <div className="annotation">Annotations for {slide.id}</div>;
}

export default function Presentation() {
  return (
    <SlideRendererProvider slide={slide} scale={0.9}>
      <SlideCanvas />
      <AnnotationLayer />
    </SlideRendererProvider>
  );
}

```

This pattern, implemented in [`src/context.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/context.tsx), ensures all descendants share consistent slide state and rendering options.

### Customizing Media with Render Slots

Inject custom rendering logic for specific media types without modifying the core library. The `renderImage`, `renderVideo`, and `renderText` props accept functions that receive the element config, source URL, and default React node.

```tsx
<SlideCanvas
  slide={slide}
  renderImage={(element, src, defaultContent) =>
    src.startsWith('placeholder:') 
      ? <MyPlaceholder src={src} /> 
      : defaultContent
  }
/>

```

### Granular Element Composition

For scenarios requiring fine-grained control over individual elements, import base components directly from the elements barrel. This allows you to wrap or extend specific renderers while maintaining type safety.

```tsx
import { BaseImageElement } from '@openmaic/renderer/elements';

function CustomImage({ el }: { el: PPTImageElement }) {
  return (
    <BaseImageElement
      elementInfo={el}
      renderImage={(element, src, defaultNode) => (
        <MyLazyImage src={src} fallback={defaultNode} />
      )}
    />
  );
}

```

## Working with Effect Overlays

The `effects` prop accepts an object defining visual animations that render above the slide content. Configure laser pointers, spotlights, or highlight regions by referencing element IDs from your slide JSON.

```tsx
<SlideCanvas
  slide={slide}
  effects={{
    laser: { elementId: 't1', color: '#ff3b30', duration: 1500 },
    spotlight: { x: 500, y: 300, radius: 100, opacity: 0.5 },
  }}
/>

```

These overlays are implemented in [`src/effects/LaserOverlay.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/effects/LaserOverlay.tsx) and related files, using the Motion library for smooth animations.

## Summary

- **@openmaic/renderer** provides a read-only canvas for OpenMAIC slide data via the `<SlideCanvas>` component defined in [`src/SlideCanvas.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/SlideCanvas.tsx).
- The rendering pipeline auto-fits viewports using `useViewportSize`, delegates elements through [`SlideElement.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/SlideElement.tsx), and supports visual effect overlays.
- Use `<SlideRendererProvider>` from [`src/context.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/context.tsx) to share slide data across component trees, accessing it via `useSlideContext()`.
- Custom rendering logic can be injected through slots like `renderImage` and `renderVideo` without disrupting the layout engine.
- The library requires React 18+, Tailwind CSS 4+, and Motion 11+ as peer dependencies.

## Frequently Asked Questions

### How do I install @openmaic/renderer and its dependencies?

Install the package via npm or yarn, ensuring your project includes React 18 or higher, Tailwind CSS 4 or higher, and Motion 11 or higher as peer dependencies. For CJK language support, import the optional [`fonts.css`](https://github.com/THU-MAIC/OpenMAIC/blob/main/fonts.css) stylesheet provided by the package.

### Can I customize how images or videos render without forking the library?

Yes. Pass custom render functions to the `renderImage`, `renderVideo`, or `renderText` props on `SlideCanvas`. These slots receive the element data, source URL, and default content node, allowing you to implement lazy-loading, placeholders, or custom video players while preserving the layout calculations.

### What is the difference between SlideCanvas and SlideRendererProvider?

`SlideCanvas` is a presentational component that accepts a `slide` prop directly and renders the content immediately. `SlideRendererProvider` is a context wrapper from [`src/context.tsx`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/context.tsx) that supplies slide data to any descendant via React context. Use the provider when multiple components—such as annotation layers or navigation controls—need simultaneous access to the same slide object.

### How does the auto-fit scaling work?

The component uses the `useViewportSize` hook located in [`src/hooks/useViewportSize.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/hooks/useViewportSize.ts) to calculate dimensions that fit the parent container while preserving the slide's aspect ratio defined by `viewportRatio` in the slide data. You can override this behavior by providing a fixed `scale` prop to either `SlideCanvas` or `SlideRendererProvider`.