Content
# Pagus
A modular PPTX web renderer that parses PowerPoint files and renders them in the browser using SVG + DOM — no server-side conversion, no Office dependencies.
## Features
- **Pure client-side rendering** — parses `.pptx` files directly in the browser or Node.js
- **High-fidelity output** — shapes, text, images, tables, charts, gradients, shadows, and group elements
- **SVG + DOM hybrid** — shapes rendered as SVG paths; text and tables in `<foreignObject>` for native selection, copy, and rich layout
- **Web font substitution** — maps Office fonts (Calibri, Microsoft YaHei, SimSun, etc.) to metrically compatible Google Fonts
- **Embedded font extraction** — reads fonts embedded in `.pptx` files and renders them via `@font-face`
- **React components** — drop-in `<PptxViewer>` with file upload, slide navigation, and font loading
- **Slide transitions & entrance animations** — CSS-based playback for transitions and common DrawingML animation effects
- **Deck authoring API** — `@pagus-kit/builder` assembles the IR programmatically (slides, shapes, text, fills) for agent-driven generation
- **MCP Apps integration** — inline slide preview inside Claude Desktop / claude.ai via `@pagus-kit/mcp`
- **Framework-agnostic core** — use `@pagus-kit/core` + `@pagus-kit/renderer` with any framework or headless in Node.js
## Packages
| Package | Description | npm |
|---|---|---|
| [`@pagus-kit/core`](./packages/core) | PPTX parser + intermediate representation (IR) | [](https://www.npmjs.com/package/@pagus-kit/core) |
| [`@pagus-kit/renderer`](./packages/renderer) | Framework-agnostic SVG string renderer | [](https://www.npmjs.com/package/@pagus-kit/renderer) |
| [`@pagus-kit/builder`](./packages/builder) | IR authoring API for constructing decks programmatically | [](https://www.npmjs.com/package/@pagus-kit/builder) |
| [`@pagus-kit/react`](./packages/react) | React components (`PptxViewer`, `SlideView`, hooks) | [](https://www.npmjs.com/package/@pagus-kit/react) |
| [`@pagus-kit/mcp`](./packages/mcp) | MCP server for inline PPTX preview in AI clients | [](https://www.npmjs.com/package/@pagus-kit/mcp) |
## Quick Start
### React
```bash
npm install @pagus-kit/react
```
```tsx
import { PptxViewer } from '@pagus-kit/react'
function App() {
return <PptxViewer />
}
```
`PptxViewer` renders a drag-and-drop upload zone by default. Pass a `file` prop (an `ArrayBuffer` or `File`) for controlled mode:
```tsx
<PptxViewer
file={file}
page={1}
scale={1}
onLoad={({ slideCount }) => console.log(`${slideCount} slides loaded`)}
onError={(err) => console.error(err)}
onPageChange={(page) => console.log(`Now on page ${page}`)}
/>
```
### Headless (Node.js / any framework)
```bash
npm install @pagus-kit/core @pagus-kit/renderer
```
```ts
import { readFile } from 'node:fs/promises'
import { parse } from '@pagus-kit/core'
import { renderSlide, buildFontSubstitutes, generateFontCss } from '@pagus-kit/renderer'
const buf = await readFile('deck.pptx')
const presentation = await parse(buf.buffer)
// Optional: map Office fonts to Google Fonts
const fontSubs = buildFontSubstitutes(presentation.fonts)
const { css: fontCss } = generateFontCss(presentation.fonts)
// Render each slide to an SVG string
for (const slide of presentation.slides) {
const { svg, width, height } = renderSlide(slide, presentation.slideSize, {
fontSubstitutes: fontSubs,
})
// svg is a complete <svg>...</svg> string — write to file, embed in HTML, etc.
}
```
### MCP (inline preview in Claude)
```bash
npm install @pagus-kit/mcp
```
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"pagus": {
"command": "npx",
"args": ["-y", "@pagus-kit/mcp"]
}
}
}
```
Restart Claude Desktop. Ask Claude to preview any `.pptx` file — it renders as an interactive widget with slide navigation directly in the conversation.
## Architecture
```
┌──────────────┐
│ .pptx file │
└──────┬───────┘
│ ArrayBuffer
┌──────▼───────┐
│ @pagus-kit/core │ Parse OOXML → IR
│ │ (JSZip + fast-xml-parser)
└──────┬───────┘
│ Presentation (IR)
┌──────▼───────┐
│@pagus-kit/renderer│ IR → SVG strings
│ │ (pure functions, no DOM)
└──────┬───────┘
│ SVG strings
┌────────────┼────────────┐
▼ ▼ ▼
@pagus-kit/react @pagus-kit/mcp Your app
(PptxViewer) (MCP tool) (any framework)
```
### Rendering strategy
| Element | Method | Why |
|---|---|---|
| Shapes / lines | SVG `<path>`, `<rect>`, `<ellipse>` | DrawingML geometry maps directly to SVG |
| Images | SVG `<image>` with data URI | Unified coordinate system |
| Text | `<foreignObject>` wrapping HTML | Rich text layout, selection, copy |
| Tables | `<foreignObject>` wrapping `<table>` | Native cell merge and border support |
| Charts | SVG `<path>` arcs | Pie / doughnut via arc calculations |
| Backgrounds | SVG `<rect>` with fill | Solid / gradient / picture |
### Font handling
Pagus uses a two-source strategy for web font fidelity:
1. **Embedded fonts** — extracts fonts from `ppt/fonts/` (ODTTF/TTF) inside the `.pptx`, generates `@font-face` rules with blob URLs
2. **Google Fonts fallback** — maps common Office fonts to metrically compatible web fonts:
| Office Font | Web Substitute |
|---|---|
| Calibri | Carlito |
| Cambria | Caladea |
| Arial | Arimo |
| Times New Roman | Tinos |
| Microsoft YaHei / SimSun / SimHei | Noto Sans SC / Noto Serif SC |
| MS Gothic / MS Mincho | Noto Sans JP / Noto Serif JP |
| Malgun Gothic | Noto Sans KR |
## Development
```bash
git clone https://github.com/pagus-kit/pagus.git
cd pagus
npm install
npm run build # builds all packages in dependency order
npm run dev # starts the playground dev server
```
### Project structure
```
pagus/
├── packages/
│ ├── core/ # PPTX parser + IR types
│ ├── renderer/ # SVG string renderer
│ ├── builder/ # IR authoring API
│ ├── react/ # React components + hooks
│ └── mcp/ # MCP Apps server
├── playground/ # Development playground (Vite + React)
└── skills/ # Claude skill definitions
```
### Scripts
| Command | Description |
|---|---|
| `npm run dev` | Start the playground dev server |
| `npm run build` | Build all packages (core → renderer → builder → react → mcp → playground) |
| `npm run build:core` | Build `@pagus-kit/core` only |
| `npm run build:renderer` | Build `@pagus-kit/renderer` only |
| `npm run build:builder` | Build `@pagus-kit/builder` only |
| `npm run build:react` | Build `@pagus-kit/react` only |
| `npm test` | Run tests via Vitest |
## API Overview
### `@pagus-kit/core`
```ts
parse(data: ArrayBuffer): Promise<Presentation>
```
Returns a `Presentation` object containing `slides`, `slideSize`, `theme`, and `fonts`. See the [core README](./packages/core) for the full IR type reference.
### `@pagus-kit/renderer`
```ts
renderSlide(slide: Slide, slideSize: Size, options?: RenderOptions): SlideRenderResult
interface RenderOptions {
scale?: number // default 1
backgroundColor?: string // CSS color override
fontSubstitutes?: Record<string, string>
}
interface SlideRenderResult {
svg: string // complete <svg>...</svg>
width: number // px
height: number // px
}
```
Also exports `buildFontSubstitutes()`, `generateFontCss()`, individual element renderers, and the font mapping table. See the [renderer README](./packages/renderer).
### `@pagus-kit/react`
```ts
// Components
<PptxViewer file={ArrayBuffer | File | null} page={number} scale={number} ... />
<SlideView slide={Slide} slideSize={Size} scale={number} ... />
// Hooks
usePresentation(file: ArrayBuffer | File | null): UsePresentationResult
useFonts(fonts: PresentationFonts | undefined, options?: UseFontsOptions): UseFontsResult
```
See the [react README](./packages/react).
### `@pagus-kit/mcp`
Exposes a single MCP tool `render_slides` that converts a `.pptx` file path into an interactive inline widget via the MCP Apps extension. See the [mcp README](./packages/mcp).
## Roadmap
### Shipped
- [x] Deck authoring API (`@pagus-kit/builder`) — programmatic IR construction for agent-driven generation
- [x] Slide transitions and common entrance animations (CSS-based playback)
- [x] SmartArt support (via pre-rendered diagram drawing XML)
### Planned
- [ ] Remote HTTP MCP server with `StreamableHTTPServerTransport` for bypassing tool result size limits
- [ ] Image optimization (EMF/WMF drop, raster downsampling, cross-slide deduplication)
- [ ] Vue adapter (`@pagus-kit/vue`)
- [ ] Full DrawingML property inheritance chain
- [ ] More preset shape types
- [ ] Expanded animation coverage (motion paths, emphasis / exit effects)
- [ ] Slide notes and speaker view
- [ ] PPTX export from the builder IR
## License
MIT
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
Python tool for converting files and office documents to Markdown.
awesome-claude-skills
A curated list of awesome Claude Skills, resources, and tools for...
antigravity-awesome-skills
The Ultimate Collection of 130+ Agentic Skills for Claude...
claude-context-mode
claude-context-mode plugin reduces MCP context bloat, saving up to 99% of tokens.
context-mode
MCP is the protocol for tool access. We're the virtualization layer for context.