How to Build on Top of OpenMAIC's Published npm Packages: A Complete Guide

OpenMAIC publishes a suite of modular, type-safe npm packages under the @openmaic namespace that enable you to compose custom slide-editing experiences, render presentations, persist data, and run AI generation pipelines without reinventing core logic.

The THU-MAIC/OpenMAIC repository distributes its architecture as discrete, composable libraries. Each package targets a specific concern—data modeling, rendering, editing, storage, or generation—allowing you to build on top of OpenMAIC's published npm packages by importing only the capabilities your application requires.

Understanding the @openmaic Package Architecture

OpenMAIC's monorepo uses PNPM workspaces to manage seven primary packages. Each library is pure TypeScript, publishes type declarations (dist/*.d.ts), and exposes a clean ESM entry point via the exports field in its package.json.

The core packages include:

  • @openmaic/dsl – A dependency-free package that defines the slide contract, JSON schema, validators, and migration helpers. Source: packages/@openmaic/dsl/package.json.
  • @openmaic/renderer – React components that render PPTist-style slide JSON, including a default <Renderer /> component and a ./elements namespace for custom implementations.
  • @openmaic/editor – ProseMirror-based editing logic with three entry points: ./core (schema and transactions), ./react (React surface), and ./ui (interface components).
  • @openmaic/storage – Pluggable persistence with sub-path exports for IndexedDB, HTTP, and PostgreSQL back-ends.
  • @openmaic/generation – Pipeline contracts and prompt templates for AI-driven slide creation. This package does not bundle an AI SDK; you bring your own provider.
  • @openmaic/importer – Utilities for migrating legacy slide formats into the OpenMAIC DSL.

All packages declare publishConfig.registry pointing to the public npm registry, ensuring they install seamlessly via standard package managers.

Installing the OpenMAIC npm Packages

Add the specific packages your project requires. For a full-stack application with editing, rendering, and AI generation, run:

npm install @openmaic/dsl @openmaic/renderer @openmaic/editor @openmaic/storage @openmaic/generation

Because the DSL is dependency-free, you can install @openmaic/dsl alone in backend services to validate slide data without pulling in React or ProseMirror dependencies.

Creating Slide Documents with @openmaic/dsl

The DSL package defines the canonical data structure for slides. Use the createSlide factory function to instantiate type-safe documents that conform to the OpenMAIC schema.

// src/slide.ts
import { createSlide, Slide } from "@openmaic/dsl";

const mySlide: Slide = createSlide({
  id: "slide-1",
  elements: [
    { type: "title", content: "Hello OpenMAIC" },
    { type: "paragraph", content: "Build on top of published packages." },
  ],
});

The source implementation in packages/@openmaic/dsl/package.json exposes validators and migration helpers alongside the core types, ensuring your documents remain compatible as the schema evolves.

Rendering Slides with @openmaic/renderer

Import the Renderer component to display DSL-compliant slides in any React application. The package also exposes a ./elements sub-path for extending the default element registry with custom React components.

// src/App.tsx
import { Renderer } from "@openmaic/renderer";
import { mySlide } from "./slide";

export default function App() {
  return <Renderer slide={mySlide} />;
}

To customize rendering, provide your own components that obey the same props contract defined in the DSL, then register them via the elements namespace.

Persisting Data with @openmaic/storage

The storage package implements a pluggable persistence layer with sub-path exports for specific back-ends. As configured in packages/@openmaic/storage/package.json, you can import only the runtime you need:

// src/storage.ts
import { http as httpRuntime } from "@openmaic/storage/runtime/http";
import { Document } from "@openmaic/dsl";

const client = httpRuntime({ baseUrl: "https://api.myapp.com" });

async function saveSlide(doc: Document) {
  await client.putDocument(doc.id, doc);
}

Available back-ends include ./runtime/http for REST APIs, browser-based IndexedDB, and ./document/pg for PostgreSQL persistence. This architecture lets you switch storage strategies without modifying your application logic.

Building Custom Editors with @openmaic/editor

The editor package exposes three distinct entry points that separate concerns across layers:

  • @openmaic/editor/core – ProseMirror schema definitions and transaction logic.
  • @openmaic/editor/react – React hooks like useEditor for embedding the editor surface.
  • @openmaic/editor/ui – Pre-built interface components for rapid prototyping.

Extend the editor by defining custom elements in the core schema, then manipulating them via the React layer:

// src/customBadge.tsx
import { BadgeElement } from "@openmaic/editor/core";
import { useEditor } from "@openmaic/editor/react";

export function BadgeEditor() {
  const { editor } = useEditor();
  
  const insertBadge = () => {
    const badge: BadgeElement = { type: "badge", content: "Beta" };
    editor.commands.insertElement(badge);
  };
  
  return <button onClick={insertBadge}>Insert Badge</button>;
}

Running AI Generation Pipelines with @openmaic/generation

The generation package bundles prompt templates and pipeline contracts but does not ship a specific AI SDK. This design keeps the generation contract stable while allowing you to integrate any LLM provider (OpenAI, Anthropic, etc.) via the @ai-sdk/* ecosystem:

// src/generate.ts
import { generateSlide } from "@openmaic/generation";
import { createAiProvider } from "ai"; // from @ai-sdk/openai or similar

const provider = createAiProvider({ apiKey: process.env.OPENAI_API_KEY! });

async function generateFromPrompt(prompt: string) {
  const slide = await generateSlide(provider, { prompt });
  return slide; // Returns a DSL-compliant Slide object
}

Because the output conforms to the @openmaic/dsl specification, you can immediately render the generated slide using the renderer or persist it via the storage package.

Summary

  • Modular Architecture – OpenMAIC distributes functionality across six focused packages (@openmaic/dsl, @openmaic/renderer, @openmaic/editor, @openmaic/storage, @openmaic/generation, @openmaic/importer), each published as pure TypeScript with ESM exports.
  • Dependency Isolation – The DSL package has zero dependencies, making it safe for backend validation, while the editor and renderer packages isolate React and ProseMirror concerns.
  • Sub-Path Imports – Storage and editor packages expose specific capabilities via sub-path exports (e.g., @openmaic/storage/runtime/http), enabling tree-shaking and reduced bundle sizes.
  • Extensibility – You can extend the renderer with custom elements, the editor with new ProseMirror nodes, and the generation pipeline with any AI provider that conforms to the standard interface.
  • Type Safety – All packages ship dist/*.d.ts declarations generated from the source in packages/@openmaic/*/package.json, ensuring full IntelliSense support when you build on top of OpenMAIC's published npm packages.

Frequently Asked Questions

What is the minimum set of packages needed to render a slide?

You only need @openmaic/dsl to define the slide data and @openmaic/renderer to display it. The DSL provides the createSlide function and TypeScript interfaces, while the renderer supplies the React component that consumes this data structure. No other packages are required for static rendering.

Can I use the OpenMAIC editor without the default UI components?

Yes. The @openmaic/editor package separates concerns into three layers: ./core for ProseMirror logic, ./react for framework bindings, and ./ui for pre-built components. You can import @openmaic/editor/core and @openmaic/editor/react to build a completely custom interface while retaining the battle-tested transaction and schema logic.

How do I switch from local IndexedDB storage to a PostgreSQL backend?

Change your import from @openmaic/storage/runtime/indexeddb (or the default browser runtime) to @openmaic/storage/document/pg. Both exports implement the same interface defined in the DSL, so swapping the import path and updating your configuration object is sufficient to migrate persistence layers without refactoring application code.

Does the generation package require a specific LLM provider?

No. @openmaic/generation defines pipeline contracts and prompt templates but does not bundle any AI SDK. You must provide your own provider instance (such as those from @ai-sdk/openai or @ai-sdk/anthropic) to the generateSlide function. This pattern decouples the slide generation logic from the underlying LLM implementation, allowing you to switch models or providers without modifying the generation package's internals.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →