How to Export OpenMAIC Content to PPTX and HTML Using `lib/export`
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 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 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):
1. Collect slides and scenes:
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
2. Build the PPTX blob via buildPptxBlob:
- Each slide canvas becomes a
pptxgenslide with preserved layout and background - HTML text is converted to PPTX text properties using
formatHTML - Media is resolved through
resolvePptxEmbeddableSrcand embedded as Base64 data URLs - Speaker notes are assembled from
speechactions viabuildSpeakerNotes
Key implementation details:
- Media resolution:
resolvePptxEmbeddableSrcfetches and caches remote assets - HTML-to-PPTX text:
formatHTMLhandles inline styles and formatting - Slide construction:
buildPptxBloborchestrates the full deck generation
3. Trigger download:
const blob = await buildPptxBlob(...);
saveAs(blob, `${fileName}.pptx`);
Source: use-export-pptx.ts#L144-L160
React Hook Usage
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#L223-L260) handles:
- HTML asset inlining: External CSS, JavaScript, and images are fetched and embedded as data URIs via
inlineHtmlAssets - Proxy-aware fetching:
createProxiedFetchrespects CSP and authentication requirements - Manifest generation:
buildStageAssetManifestcreates amanifest.jsonfor later re-import - Media bundling: All audio, generated video, and image assets are included in the ZIP
React Hook Usage
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.jsonwith stage metadata and scene definitions
Manual Builder Access (Advanced)
For testing, server-side usage, or custom orchestration, import the builder functions directly:
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
Summary
- Use
useExportPPTXfor editable PowerPoint decks with full media embedding and speaker notes - Use
useExportClassroomfor self-contained ZIP packages with offline-ready interactive HTML - Both hooks provide
exportingstate for UI feedback and handle all media resolution automatically - Builders like
buildPptxBlobandbuildResourcePackZipare exposed for advanced use cases - The
lib/exportmodule 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) 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) 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →