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

> Learn how to build on top of OpenMAIC's published npm packages to create custom slide-editing experiences, render presentations, and run AI pipelines without reinventing core logic. Get started today!

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

---

**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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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:

```bash
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.

```typescript
// 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.

```tsx
// 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:

```typescript
// 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:

```tsx
// 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:

```typescript
// 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.