# How to Export OpenMAIC Content to PPTX and HTML Using `lib/export`

> Easily export OpenMAIC content to PPTX and HTML using the lib/export module. Generate editable PowerPoint decks and interactive HTML packages from your classroom scenes.

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

---

**OpenMAIC's `lib/export` module provides two production-ready hooks—`useExportPPTX` and `useExportClassroom`—to generate editable PowerPoint decks and self-contained interactive HTML packages directly from your classroom scenes.**

The export library in [THU-MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC) transforms generated course content into portable, offline-ready formats. Whether you need a speaker-ready `.pptx` file or a fully interactive classroom experience bundled for distribution, the pipeline handles media resolution, asset inlining, and ZIP assembly automatically.

## Export Format Overview

| Format | Primary Hook | Builder Function | Output Characteristics |
|--------|-------------|------------------|------------------------|
| **PowerPoint (.pptx)** | `useExportPPTX` | `buildPptxBlob` | Editable slides with embedded media, shapes, charts, tables, LaTeX, video/audio, and speaker notes |
| **Interactive HTML + Classroom ZIP** | `useExportClassroom` | `buildResourcePackZip` | Self-contained ZIP with inlined HTML pages, assets, and a [`manifest.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/manifest.json) for re-import |

Both formats are generated serverlessly in the browser using `pptxgenjs` for PPTX creation and native ZIP APIs for packaging.

## Exporting to PowerPoint (PPTX)

### How `useExportPPTX` Works

The hook gathers slide content from the stage store, builds a PPTX blob using `pptxgenjs`, and triggers a download. Here's the internal flow as implemented in [[`lib/export/use-export-pptx.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts):

**1. Collect slides and scenes:**

```typescript
const slides = useStageStore(s => s.scenes.filter(s => s.content.type === 'slide')
                                         .map(s => (s.content as SlideContent).canvas));
const scenes = useStageStore(s => s.scenes);

```

Source: [use-export-pptx.ts#L13-L15](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts#L13-L15)

**2. Build the PPTX blob via `buildPptxBlob`:**

- Each slide canvas becomes a `pptxgen` slide with preserved layout and background
- HTML text is converted to PPTX text properties using `formatHTML`
- Media is resolved through `resolvePptxEmbeddableSrc` and embedded as Base64 data URLs
- Speaker notes are assembled from `speech` actions via `buildSpeakerNotes`

Key implementation details:
- **Media resolution:** [`resolvePptxEmbeddableSrc`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts#L110-L128) fetches and caches remote assets
- **HTML-to-PPTX text:** [`formatHTML`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts#L62-L92) handles inline styles and formatting
- **Slide construction:** [`buildPptxBlob`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts#L98-L120) orchestrates the full deck generation

**3. Trigger download:**

```typescript
const blob = await buildPptxBlob(...);
saveAs(blob, `${fileName}.pptx`);

```

Source: [use-export-pptx.ts#L144-L160](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts#L144-L160)

### React Hook Usage

```tsx
import { useExportPPTX } from '@/lib/export/use-export-pptx';

function ExportPPTXButton() {
  const { exporting, exportPPTX } = useExportPPTX();

  return (
    <button disabled={exporting} onClick={exportPPTX}>
      {exporting ? 'Exporting…' : 'Download PPTX'}
    </button>
  );
}

```

The `exporting` boolean indicates active processing, useful for UI loading states.

## Exporting Interactive HTML (Classroom ZIP)

### How `useExportClassroom` Works

The classroom export creates offline-ready interactive experiences from scenes marked with `content.type === 'interactive'`. The `buildResourcePackZip` function in [[`lib/export/use-export-pptx.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts#L223-L260) handles:

- **HTML asset inlining:** External CSS, JavaScript, and images are fetched and embedded as data URIs via [`inlineHtmlAssets`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/inline-assets.ts)
- **Proxy-aware fetching:** [`createProxiedFetch`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/proxied-fetch.ts) respects CSP and authentication requirements
- **Manifest generation:** `buildStageAssetManifest` creates a [`manifest.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/manifest.json) for later re-import
- **Media bundling:** All audio, generated video, and image assets are included in the ZIP

### React Hook Usage

```tsx
import { useExportClassroom } from '@/lib/export/use-export-classroom';

function ExportHTMLButton() {
  const { exporting, exportClassroomZip } = useExportClassroom();

  return (
    <button disabled={exporting} onClick={exportClassroomZip}>
      {exporting ? 'Preparing…' : 'Download HTML Package'}
    </button>
  );
}

```

The resulting ZIP contains:
- Inlined HTML pages for each interactive scene
- Embedded media assets
- [`manifest.json`](https://github.com/THU-MAIC/OpenMAIC/blob/main/manifest.json) with stage metadata and scene definitions

## Manual Builder Access (Advanced)

For testing, server-side usage, or custom orchestration, import the builder functions directly:

```typescript
import { buildPptxBlob, buildResourcePackZip } from '@/lib/export/use-export-pptx';

// Build PPTX from prepared slide data
const pptxBlob = await buildPptxBlob(
  slides,           // Slide canvas data
  slideScenes,      // Scene metadata for slides
  viewportRatio,    // Aspect ratio (e.g., 16/9)
  viewportSize,     // { width: number, height: number }
  ratioPx2Inch,     // Pixel-to-inch conversion
  ratioPx2Pt,       // Pixel-to-point conversion
  stageId,          // Unique stage identifier
);

// Build complete classroom ZIP (includes PPTX + interactive HTML)
const zipResult = await buildResourcePackZip(
  scenes,           // All scenes (slides + interactive)
  slides,           // Slide canvas data
  slideScenes,      // Slide scene metadata
  {
    viewportRatio,
    viewportSize,
    ratioPx2Inch,
    ratioPx2Pt,
    fileName: 'my-course',
    getPptxBlob: () => pptxBlob,  // Lazy PPTX generator
  },
);

```

## Key Export Library Files

| File | Purpose |
|------|---------|
| [[`lib/export/use-export-pptx.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-pptx.ts) | PPTX hook, blob builder, and resource-pack orchestrator |
| [[`lib/export/use-export-classroom.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-classroom.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/use-export-classroom.ts) | Classroom ZIP hook and builder exposure |
| [[`lib/export/inline-assets.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/inline-assets.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/inline-assets.ts) | CSS/JS/image inlining for offline HTML |
| [[`lib/export/proxied-fetch.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/proxied-fetch.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/proxied-fetch.ts) | Authenticated, CSP-compliant fetch wrapper |
| [[`lib/export/svg2base64.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/svg2base64.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/svg2base64.ts) | SVG-to-Base64 conversion for PPTX embedding |
| [[`lib/export/html-asset-inventory.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/html-asset-inventory.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/html-asset-inventory.ts) | HTML asset scanning and dependency detection |
| [[`lib/export/classroom-zip-types.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/classroom-zip-types.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/classroom-zip-types.ts) | TypeScript definitions for ZIP manifests |
| [[`lib/export/classroom-zip-utils.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/classroom-zip-utils.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/classroom-zip-utils.ts) | Media collection and manifest utilities |

## Summary

- **Use `useExportPPTX`** for editable PowerPoint decks with full media embedding and speaker notes
- **Use `useExportClassroom`** for self-contained ZIP packages with offline-ready interactive HTML
- Both hooks provide `exporting` state for UI feedback and handle all media resolution automatically
- Builders like `buildPptxBlob` and `buildResourcePackZip` are exposed for advanced use cases
- The `lib/export` module ensures all exported content works offline through aggressive asset inlining and Base64 embedding

## Frequently Asked Questions

### Does the PPTX export preserve animations and transitions?

No. The `buildPptxBlob` function captures static slide states including shapes, text formatting, images, and media placement. Complex canvas animations are rendered as their final frames. Speaker notes from `speech` actions are preserved as PPTX notes.

### Can I customize the PPTX output dimensions or aspect ratio?

Yes. The `buildPptxBlob` function accepts `viewportRatio`, `viewportSize`, `ratioPx2Inch`, and `ratioPx2Pt` parameters that control slide dimensions and coordinate scaling. These map your canvas coordinates to PPTX inches and points.

### What makes the HTML package "offline-ready"?

The `inlineHtmlAssets` function in [[`lib/export/inline-assets.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/inline-assets.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/inline-assets.ts) fetches all external CSS, JavaScript, font, and image references and replaces them with data URIs. Combined with Base64-embedded media, this produces HTML files with zero external dependencies.

### How does `createProxiedFetch` handle authentication?

The proxied fetch in [[`lib/export/proxied-fetch.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/proxied-fetch.ts)](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/export/proxied-fetch.ts) routes requests through your application's API layer. This automatically includes session cookies, bearer tokens, and other auth headers required to access protected media URLs, while respecting Content Security Policy restrictions.