# Four Content Kinds Supported Within the Scene Generic in OpenMAIC: Complete TypeScript Reference

> Discover the four content kinds supported in OpenMAIC's Scene generic: Slide, Quiz, Interactive, and PBL. Explore this TypeScript reference for detailed implementation.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: api-reference
- Published: 2026-09-12

---

**The `Scene` generic in OpenMAIC supports four persisted content kinds—Slide, Quiz, Interactive, and PBL (Project-Based Learning)—defined as a discriminated union in [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts) that extends the base `@openmaic/dsl` contract.**

OpenMAIC implements a flexible content architecture through its generic `Scene` type, which wraps the contract-defined `@openmaic/dsl` `Scene` to support diverse educational content. The generic parameter `SceneContent` creates a type-safe union encompassing four distinct content kinds, enabling developers to handle everything from static slides to complex project-based learning configurations within a single consistent interface.

## Understanding the Scene Generic Architecture

The `Scene` type in OpenMAIC serves as a generic wrapper that enriches the base contract with application-specific content variants. Located in [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts) (lines 57-90), this implementation defines `SceneContent` as a four-way union that accommodates varying pedagogical content structures while maintaining strict TypeScript type safety.

The generic structure allows the `Scene` type to hold both an `actions` array and a discriminated `content` field, where the `type` property determines which of the four supported kinds is active.

## The Four Content Kinds Supported Within the Scene Generic

OpenMAIC extends the base `@openmaic/dsl` contract—which only includes **slide** and **quiz**—with two additional kinds to form the complete union.

### Slide Content (`slide`)

The **Slide** kind represents standard slide content containing text, images, videos, and other static media elements. As the foundational content type inherited from the base DSL contract, it supports rich multimedia layouts without interactive requirements.

### Quiz Content (`quiz`)

The **Quiz** kind handles interactive assessment elements including questions, options, and answer configurations. This type manages both single-select and multiple-choice interactions, storing question metadata and scoring logic within the scene's content field.

### Interactive Content (`interactive`)

The **Interactive** kind enables embedded web pages and iframes through the `InteractiveContent` type, which utilizes a `WidgetConfig`-based payload. This extends the base contract capabilities by allowing external tools and widgets to run within the scene framework, configured via the `widgetConfig` property.

### PBL Content (`pbl`)

The **PBL** (Project-Based Learning) kind stores complex project configurations through the `PBLContent` type. It maintains both legacy project configuration data and optional V2 runtime state (`projectV2`), supporting long-form collaborative learning experiences that persist across multiple sessions.

## TypeScript Type Definitions and Unions

The type system defines the relationship between these content kinds through a hierarchical union structure. According to the source code in [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts):

```typescript
export type AppSceneContent = DslSceneContent | InteractiveContent | PBLContent;
export type SceneContent = AppSceneContent;   // the four-way union used by Scene

```

Here, `DslSceneContent` represents the base contract types (**slide** and **quiz**), while `InteractiveContent` and `PBLContent` are OpenMAIC-specific extensions. The `Scene` generic uses this `SceneContent` union to ensure that only valid content payloads are assigned to a scene's `content` field.

## Practical Implementation Examples

The following TypeScript examples demonstrate how to instantiate each content kind within the `Scene` generic:

**Slide Scene:**

```typescript
import type { Scene, Action } from '@/lib/types/stage';

const slideScene: Scene = {
  id: 's1',
  order: 0,
  title: 'Intro Slide',
  actions: [] as Action[],
  type: 'slide',
  content: { type: 'slide', elements: [{ text: 'Welcome' }] },
};

```

**Quiz Scene:**

```typescript
const quizScene: Scene = {
  id: 's2',
  order: 1,
  title: 'Quiz Time',
  actions: [] as Action[],
  type: 'quiz',
  content: {
    type: 'quiz',
    questions: [{ id: 'q1', type: 'single', prompt: 'What?' }],
  },
};

```

**Interactive Scene:**

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

const interactiveScene: Scene = {
  id: 's3',
  order: 2,
  title: 'Embedded Tool',
  actions: [] as Action[],
  type: 'interactive',
  content: {
    type: 'interactive',
    src: 'https://example.com/tool',
    widgetConfig: { /* widget-specific config */ },
  } as InteractiveContent,
};

```

**PBL Scene:**

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

const pblScene: Scene = {
  id: 's4',
  order: 3,
  title: 'Project-Based Learning',
  actions: [] as Action[],
  type: 'pbl',
  content: {
    type: 'pbl',
    projectConfig: { /* legacy config */ },
    projectV2: { /* runtime state */ },
  } as PBLContent,
};

```

## Key Source Files and Type Dependencies

Several files work together to implement the four content kinds within the OpenMAIC architecture:

- **[`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts)**: Declares the `Scene` generic, the four content kind definitions, and the `makeScene` factory function.
- **`@openmaic/dsl`** (external package): Provides the base contract types `SlideContent` and `QuizContent` that form the foundation of the union.
- **[`lib/types/action.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/action.ts)**: Defines the `Action` type used in every `Scene` instance's `actions` array.
- **[`lib/types/widgets.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/widgets.ts)**: Supplies the `WidgetConfig` interface consumed by `InteractiveContent` payloads.
- **[`lib/pbl/legacy/read.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/pbl/legacy/read.ts)** and **[`lib/pbl/v2/types.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/pbl/v2/types.ts)**: Contain the legacy and V2 project configuration types referenced by `PBLContent`.

## Summary

- OpenMAIC's `Scene` generic supports **four content kinds**: Slide, Quiz, Interactive, and PBL.
- The base `@openmaic/dsl` contract provides **Slide** and **Quiz**, while OpenMAIC adds **Interactive** and **PBL** extensions.
- Type definitions reside in [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts), utilizing a union type `SceneContent` that encompasses all four variants.
- Each content kind uses TypeScript discriminated unions via the `type` property for compile-time type narrowing.
- **Interactive** content relies on `WidgetConfig` from [`lib/types/widgets.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/widgets.ts), while **PBL** content references legacy and V2 types from the `lib/pbl/` directory.

## Frequently Asked Questions

### What is the difference between the base contract and OpenMAIC's Scene generic?

The base `@openmaic/dsl` contract defines only **Slide** and **Quiz** content kinds. OpenMAIC's `Scene` generic extends this through the `AppSceneContent` union type, adding **Interactive** and **PBL** kinds to support embedded widgets and project-based learning workflows. This widening occurs in [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts) where `SceneContent` combines both base and extended types.

### How does the Interactive content kind handle external widget configuration?

The **Interactive** kind uses the `InteractiveContent` type, which includes a `widgetConfig` property typed as `WidgetConfig` from [`lib/types/widgets.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/widgets.ts). This configuration object manages iframe sources, sizing parameters, and widget-specific metadata, allowing external tools to integrate seamlessly within the scene framework while maintaining type safety through the generic parameter.

### Can I extend the Scene generic with additional content types?

While the current implementation in [`lib/types/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/types/stage.ts) defines a fixed four-way union, TypeScript's structural typing allows extension by modifying the `AppSceneContent` union to include new content interfaces. Any new kind must implement the discriminated union pattern with a unique `type` property and should be added to the `SceneContent` definition to maintain compatibility with the generic `Scene` type constraints.

### Where is the PBL legacy configuration defined in the codebase?

The **PBL** content kind references legacy project configurations defined in [`lib/pbl/legacy/read.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/pbl/legacy/read.ts), while the modern V2 runtime state is declared in [`lib/pbl/v2/types.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/pbl/v2/types.ts). The `PBLContent` interface aggregates both structures, storing legacy data in `projectConfig` and optional V2 data in `projectV2`, enabling backward compatibility with existing project-based learning content while supporting new feature iterations.