# OpenMAIC DSL SlideContent Type Structure: A Complete Guide

> Discover the SlideContent type structure in the OpenMAIC DSL. Learn how it represents slides with PPTCanvas drawings, background metadata, and version tracking.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: deep-dive
- Published: 2026-09-04

---

**The `SlideContent` type in the OpenMAIC DSL is a discriminated union with a literal `type: "slide"` field that encapsulates a `PPTCanvas` drawing surface, optional background metadata, and runtime version tracking to represent fully qualified slide objects.**

The `SlideContent` type serves as the core data structure for representing individual slides within the OpenMAIC presentation framework. Defined in the `@openmaic/dsl` npm package and re-exported through the main repository's type definitions, this interface provides the schema for canvas dimensions, element hierarchies, and slide-specific metadata. Understanding this structure is essential for developers building custom renderers, editors, or migration tools for the OpenMAIC ecosystem.

## Structure of the SlideContent Type

`SlideContent` follows a discriminated union pattern where the `type` field acts as a singleton discriminator. According to the source in [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts), the interface is re-exported from `@openmaic/dsl` and exposes the following fields:

| Field | Type | Description |
|-------|------|-------------|
| `type` | `"slide"` | Literal string discriminant identifying the content as a slide |
| `canvas` | `PPTCanvas` | The slide's drawing surface containing dimensions and renderable elements |
| `schemaVersion?` | `number` | Optional version identifier for schema migration handling |
| `background?` | `SlideBackground` | Optional background specification (solid color, gradient, or image) |
| `metadata?` | `Record<string, unknown>` | Arbitrary key-value pairs for editor or runtime annotations |

The discriminant approach allows TypeScript to narrow union types effectively when processing mixed content collections.

### The PPTCanvas Interface

The `canvas` property implements the `PPTCanvas` interface, which adopts a PPT-style coordinate system for rendering. In [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts), this nested structure defines the spatial container for all slide elements:

```typescript
interface PPTCanvas {
  /** Width in points (typically 720pt for standard 10-inch slide width) */
  width: number;
  /** Height in points (typically 540pt for standard 7.5-inch slide height) */
  height: number;
  /** Ordered array of elements rendered to the slide */
  elements: PPTElement[];
}

```

Each `PPTElement` within the `elements` array is itself a discriminated union representing drawable objects such as text boxes, images, shapes, or video embeds. Elements carry geometry properties (`x`, `y`, `width`, `height`, `rotate`) alongside content-specific payloads.

## Runtime Type Guards

Because `SlideContent` participates in union types, the OpenMAIC DSL provides runtime validation through the `isSlideContent` guard function. Exported from [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts) and sourced from `@openmaic/dsl`, this utility performs structural validation:

```typescript
import { isSlideContent } from '@/lib/types/stage';

// Returns true only if obj.type === 'slide' and required canvas field exists
if (isSlideContent(unknownObject)) {
  // TypeScript narrows unknownObject to SlideContent
  console.log(unknownObject.canvas.width);
}

```

Using this guard prevents runtime errors when handling data from external sources or untyped JSON payloads.

## Working with SlideContent Objects

### Creating a New Slide Programmatically

Instantiate a compliant `SlideContent` object by satisfying the discriminant and canvas requirements:

```typescript
import type { SlideContent } from '@/lib/types/stage';
import { isSlideContent } from '@/lib/types/stage';

const blankSlide: SlideContent = {
  type: 'slide',
  schemaVersion: 4,
  canvas: {
    width: 720,
    height: 540,
    elements: []
  },
  background: { color: '#ffffff' },
  metadata: { author: 'system' }
};

if (isSlideContent(blankSlide)) {
  console.log('Slide validated and ready for rendering');
}

```

### Adding Elements to an Existing Slide

Manipulate the immutable slide structure by spreading existing properties when adding new elements:

```typescript
import type { SlideContent, PPTTextElement } from '@/lib/types/stage';

function addTitle(slide: SlideContent, title: string): SlideContent {
  const textElement: PPTTextElement = {
    type: 'text',
    id: `title-${Date.now()}`,
    x: 50,
    y: 30,
    width: 620,
    height: 80,
    rotate: 0,
    text: title,
    style: { fontSize: 36, fontWeight: 'bold', color: '#222222' }
  };

  return {
    ...slide,
    canvas: {
      ...slide.canvas,
      elements: [...slide.canvas.elements, textElement]
    }
  };
}

```

### Migrating Legacy Slide Schemas

Handle version drift using the built-in migration utility:

```typescript
import { migrateSlideContent } from '@/lib/types/stage';
import type { SlideContent } from '@/lib/types/stage';

const legacySlide: SlideContent = {
  type: 'slide',
  // Missing schemaVersion implies legacy data
  canvas: { width: 720, height: 540, elements: [] }
};

const currentSlide = migrateSlideContent(legacySlide);
console.log(`Migrated to schema version ${currentSlide.schemaVersion}`);

```

## Key Implementation Files

The `SlideContent` type and its associated utilities are distributed across the following locations:

- **[`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts)** – Re-exports the core `SlideContent` type and `isSlideContent` guard from `@openmaic/dsl`, lines 31-33
- **`@openmaic/dsl` (npm package)** – Source of truth for the type definitions and guard implementations
- **[`tests/edit/slide-schema.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/edit/slide-schema.test.ts)** – Unit tests validating construction, validation, and migration of `SlideContent` objects
- **[`tests/slide-renderer/screen-canvas-renderer.test.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/tests/slide-renderer/screen-canvas-renderer.test.ts)** – Integration tests demonstrating `SlideContent` consumption in the rendering pipeline

## Summary

- **`SlideContent`** is a discriminated union using `type: "slide"` as its discriminator, defined in `@openmaic/dsl` and re-exported from [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts)
- The **`canvas`** property contains a `PPTCanvas` with width, height, and an ordered `elements` array of `PPTElement` objects
- Optional fields include **`schemaVersion`** for migration tracking, **`background`** for visual styling, and **`metadata`** for extensibility
- The **`isSlideContent`** runtime guard provides safe type narrowing when processing untyped data
- The **`migrateSlideContent`** function handles schema evolution and backward compatibility

## Frequently Asked Questions

### How does OpenMAIC distinguish SlideContent from other content types?

OpenMAIC uses a discriminated union pattern where the literal string `"slide"` in the `type` property distinguishes `SlideContent` from other content variants. TypeScript leverages this literal type to provide automatic type narrowing in conditional blocks, while the `isSlideContent` runtime guard performs equivalent checks in JavaScript execution contexts.

### What coordinate system does the PPTCanvas use?

The `PPTCanvas` interface adopts a point-based coordinate system consistent with PowerPoint specifications, typically operating at 72 DPI where 720 points equals 10 inches of width. All element positioning through `x` and `y` properties, as well as dimensions via `width` and `height`, reference this absolute coordinate space regardless of the target display resolution.

### Can I extend SlideContent with custom fields?

The `metadata?: Record<string, unknown>` field provides an extension point for arbitrary data without breaking the core schema. Store custom annotations, editor state, or application-specific flags within this object while preserving type safety for standard `SlideContent` properties. Avoid modifying the `canvas` structure directly, as this may break renderer compatibility.