# How OpenMAIC Transforms Documents into Interactive Classroom Experiences: The 6-Step Pipeline Explained

> Discover how OpenMAIC transforms documents into interactive classroom experiences with its 6-step pipeline. Learn to create engaging React-based lessons powered by AI.

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

---

**OpenMAIC converts static documents into interactive classrooms through a modular pipeline that imports content, stores it as structured stage documents, generates AI-powered enhancements via LLMs, and renders them as fully interactive React-based lessons.**

OpenMAIC is an open-source educational technology framework developed by THU-MAIC that bridges the gap between static teaching materials and dynamic, AI-enhanced learning environments. By combining document parsing, intelligent content generation, and real-time rendering, it enables educators to transform any PDF, PowerPoint, or text document into an engaging classroom experience. This article examines the complete technical pipeline as implemented in the [THU-MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC) repository, including the specific packages, APIs, and configuration points that make this transformation possible.

## The Six-Stage Transformation Pipeline

### Stage 1: Document Import and Normalization

The transformation begins in `@openmaic/importer`, where raw files are parsed and normalized into the **MAIC slide DSL** (`Slide[]`).

The package exposes two primary entry points:
- `importPptx(file, options)` — for PowerPoint files
- `parse(file)` — for PDF and plain text documents

During import, the system:
- Extracts text, layout, and embedded media from source files
- Normalizes all content into a standardized slide structure
- Optionally uploads media assets to user-provided object storage via the `upload` callback

In `packages/@openmaic/importer/README.md`, the import contract specifies that all slide geometry, typography, and asset references must conform to the `Slide` TypeScript interface, ensuring downstream components receive predictable data.

### Stage 2: Document Storage and Persistence

Once normalized, slides are persisted as a **stage document** (`MaicDocument`) through `@openmaic/storage`.

The storage layer provides:
- **Contract-first design** — HTTP contracts defined in `packages/@openmaic/storage/docs/` guarantee JSON-safe payloads
- **Multiple backends** — PostgreSQL for server-side deployments, IndexedDB for browser environments
- **Immutable stage IDs** — each document receives a unique `stageId` that serves as the canonical reference for all subsequent operations

The `MaicDocument` schema includes:
- `outline` — structural metadata for the lesson
- `scenes` — individual slides with canvas content
- `assets` — media references and generation placeholders
- `runtime` — session state and progress tracking

According to `packages/@openmaic/storage/README.md`, the `DocumentStore.putStage()` method guarantees atomic writes, ensuring data consistency during concurrent generation jobs.

### Stage 3: AI-Powered Content Generation

The **generation engine** (`@openmaic/generation`) orchestrates a multi-stage LLM pipeline through the `/api/generate-classroom` endpoint.

The generation workflow follows a **two-stage architecture**:

| Phase | Description | Output |
|-------|-------------|--------|
| **Outline creation** | LLM analyzes document structure and learning objectives | Hierarchical lesson outline with scene boundaries |
| **Scene generation** | Parallel generation of content, quizzes, and media per scene | Populated scenes with interactive elements |

Each scene may trigger additional AI services:
- **Text completion** — elaborated explanations, discussion prompts
- **Quiz generation** — multiple-choice, fill-in-blank, coding exercises
- **Image generation** — diagrams, illustrations, scene backgrounds
- **Text-to-speech** — narrated content for accessibility

All prompt templates reside in `packages/@openmaic/generation/templates/` and are selected based on the `DEFAULT_MODEL` environment variable. Feature flags (`enableWebSearch`, `enableImageGeneration`, `enableTTS`) control which capabilities are activated per request, as documented in [`skills/openmaic/references/generate-flow.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/skills/openmaic/references/generate-flow.md).

### Stage 4: Interactive Rendering

The `@openmaic/renderer` package converts stored `MaicDocument` instances into running React applications.

Key rendering capabilities include:
- **Canvas-based slide display** with drag-and-drop interaction
- **Embedded widgets** — quizzes, code playgrounds, whiteboards
- **Video and audio playback** with synchronized transcripts
- **Skeleton placeholders** for asynchronously generated media

The renderer implements a **progressive loading strategy**: when a slide references a media asset still being generated, it displays a skeleton UI using the `elementId` stored in the document, then hot-swaps the final asset upon completion. This pattern is defined in `packages/@openmaic/renderer/README.md`.

### Stage 5: Runtime Manipulation and Live Editing

During active classroom sessions, the **agent-runtime** layer (`skills/agent-runtime/stage-dsl/`) provides programmatic access to stage documents.

Three core utilities enable live interaction:

- `read_stage(stageId)` — Retrieves current document state
- `patch_stage(stageId, operations)` — Applies atomic modifications to scenes or metadata
- `grep_stage(stageId, query)` — Searches content across all scenes

These primitives power features like:
- Real-time instructor annotations
- Student progress tracking
- Dynamic content adaptation based on quiz responses

The [`SKILL.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/SKILL.md) file in `skills/agent-runtime/stage-dsl/` specifies the complete operation schema and concurrency guarantees for these runtime utilities.

### Stage 6: End-to-End Orchestration

The complete document-to-classroom flow integrates all prior stages:

```

User uploads document
    ↓
importPptx() / parse() — Slide[] extraction
    ↓
DocumentStore.putStage() — persistence with stageId
    ↓
POST /api/generate-classroom — async generation job
    ↓
Poll /api/job/{jobId} — monitor until completion
    ↓
MaicRenderer — interactive lesson display

```

This orchestration pattern is illustrated in the generation pipeline diagram located in the repository's top-level [`README.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/README.md), under the `#generation` section.

## Modular Architecture and Extension Points

### Package-Based Design

Each pipeline stage is published as an independent npm package under `@openmaic/*`:

| Package | Responsibility | Install Command |
|---------|--------------|---------------|
| `@openmaic/importer` | File parsing and normalization | `npm i @openmaic/importer` |
| `@openmaic/storage` | Document persistence contracts | `npm i @openmaic/storage` |
| `@openmaic/generation` | LLM orchestration and prompts | `npm i @openmaic/generation` |
| `@openmaic/renderer` | React-based interactive output | `npm i @openmaic/renderer` |
| `@openmaic/dsl` | Shared type definitions | `npm i @openmaic/dsl` |

This structure enables **selective adoption** — a custom learning management system might import and store documents directly while implementing its own rendering layer.

### Provider Configuration

The generation pipeline accepts environment-based configuration for pluggable AI services:

```bash

# Required

DEFAULT_MODEL=anthropic/claude-3-sonnet

# Optional capabilities

ENABLE_WEB_SEARCH=true
ENABLE_IMAGE_GENERATION=true
ENABLE_TTS=true
ENABLE_VIDEO_GENERATION=false

# Provider-specific keys

OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-...
REPLICATE_API_TOKEN=r8_...

```

Configuration details are maintained in [`provider-keys.md`](https://github.com/THU-MAIC/OpenMAIC/blob/main/provider-keys.md) within the skills documentation.

## Complete Implementation Example

The following TypeScript demonstrates the full transformation pipeline in a Node.js environment:

```typescript
// 1️⃣ Import and normalize a PowerPoint file
import { importPptx } from '@openmaic/importer';
import type { Slide } from '@openmaic/importer';

async function loadSlides(file: Buffer): Promise<Slide[]> {
  return await importPptx(file, {
    upload: async (blob) => {
      const url = await uploadToOss(blob);
      return url;
    },
  });
}

```

```typescript
// 2️⃣ Persist as a stage document
import { DocumentStore } from '@openmaic/storage/document/pg';
import { MaicDocument } from '@openmaic/dsl';

async function createStage(slides: Slide[]): Promise<string> {
  const stageId = `stage-${Date.now()}`;
  const doc: MaicDocument = {
    id: stageId,
    name: 'Interactive Lesson',
    dslVersion: 'v1',
    outline: { objectives: [], duration: 45 },
    scenes: slides.map((s, i) => ({
      id: `scene-${i}`,
      content: { canvas: s },
    })),
  };
  await DocumentStore.putStage(doc);
  return stageId;
}

```

```typescript
// 3️⃣ Initiate generation and poll for completion
import fetch from 'node-fetch';

async function generateAndRender(stageId: string) {
  const { jobId } = await fetch(`${OPENMAIC_URL}/api/generate-classroom`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      stageId,
      enableImageGeneration: true,
      enableTTS: true,
    }),
  }).then(r => r.json());

  // Poll until completion
  while (true) {
    const { status, result } = await fetch(
      `${OPENMAIC_URL}/api/job/${jobId}`
    ).then(r => r.json());

    if (status === 'completed') return result.stageId;
    if (status === 'failed') throw new Error('Generation failed');
    await new Promise(res => setTimeout(res, 60000));
  }
}

```

```typescript
// 4️⃣ Render in a React application
import { MaicRenderer } from '@openmaic/renderer';

function Classroom({ stageId }: { stageId: string }) {
  const [doc, setDoc] = React.useState(null);

  React.useEffect(() => {
    DocumentStore.getStage(stageId).then(setDoc);
  }, [stageId]);

  return doc ? <MaicRenderer document={doc} /> : <p>Loading…</p>;
}

```

## Summary

- **OpenMAIC implements a six-stage pipeline** — import, store, generate, render, runtime manipulation, and end-to-end orchestration — that transforms static documents into interactive classrooms.
- **The `@openmaic/*` monorepo packages** provide modular, contract-guaranteed components that can be adopted individually or as a complete system.
- **Two-stage generation** enables parallel content creation with fine-grained retry logic, while skeleton placeholders ensure responsive UI during asynchronous media generation.
- **Immutable stage documents** with unique `stageId` references provide the foundational data model for persistence, generation tracking, and runtime editing.
- **Provider-configurable AI services** allow deployment-specific selection of LLMs, image models, and voice synthesis without code changes.

## Frequently Asked Questions

### What file formats does OpenMAIC support for document import?

OpenMAIC currently supports **PowerPoint (PPTX)**, **PDF**, and **plain text** documents. The `@openmaic/importer` package provides `importPptx()` for PPTX files and `parse()` for PDF and text files. Both functions normalize content into the same `Slide[]` DSL structure, ensuring consistent downstream processing regardless of source format.

### How does OpenMAIC handle media generation that takes longer than the HTTP timeout?

The generation pipeline returns immediately with a `jobId` that clients poll via `/api/job/{jobId}`. During generation, the renderer displays **skeleton placeholders** using `elementId` references stored in the document. When media completes, the final URL is patched into the stage document and the renderer hot-swaps the placeholder. This pattern decouples generation latency from user experience.

### Can OpenMAIC integrate with custom storage backends beyond PostgreSQL and IndexedDB?

Yes. The storage contracts in `packages/@openmaic/storage/docs/` define the interface that any backend must implement. The package provides reference implementations for PostgreSQL (`@openmaic/storage/document/pg`) and IndexedDB (`@openmaic/storage/document/idb`), but developers can implement the same contract for Redis, MongoDB, or proprietary systems. The contract-first design ensures that front-end components remain compatible regardless of backend choice.

### What control do educators have over the AI-generated content?

Educators influence generation through **feature flags** (`enableImageGeneration`, `enableTTS`, etc.) and **model selection** (`DEFAULT_MODEL`). The prompt templates in `packages/@openmaic/generation/templates/` can be customized for institution-specific pedagogy. Additionally, the `patch_stage` runtime utility allows live editing of generated content before or during classroom delivery, and the `stage-dsl` SKILL documentation defines how to programmatically constrain or guide generation through the outline structure.