CorePlugin & headless
Server-side document manipulation with CorePlugin and DocumentAgent. Run template processing and headless edits without a browser or the editor UI.
What is the headless API?
The plugin system spans two npm entry points:
@eigenpal/docx-editor-react/plugin-api → browser editor plugins (React, needs DOM)
@eigenpal/docx-editor-core/headless → headless API (Node.js, no DOM needed)The headless API gives you DocumentAgent, parsers, serializers, and template processing: everything you need to manipulate DOCX files programmatically in Node.js. No browser, no React, no ProseMirror.
import { DocumentAgent, parseDocx, processTemplate } from '@eigenpal/docx-editor-core/headless';CorePlugins extend the headless API with custom command handlers. They're the server-side equivalent of EditorPlugins.
When to use the headless API
- API routes: fill templates, generate documents server-side
- CI/CD pipelines: validate templates, extract variables
- Node.js scripts: batch-process DOCX files
- Server-side agents: programmatic document manipulation
If you need UI panels, overlays, or ProseMirror decorations, use an EditorPlugin instead.
DocumentAgent
DocumentAgent wraps a Document in a chainable, immutable API for headless reads and edits:
import { readFile } from 'node:fs/promises';
import { DocumentAgent } from '@eigenpal/docx-editor-core/headless';
const buf = await readFile('template.docx');
const agent = await DocumentAgent.fromBuffer(buf);
const filled = await agent.applyVariables({ customer_name: 'Jane Doe', date: '2026-07-01' });
const out = await filled.toBuffer();The full surface (parsing, text extraction, mutation, serialization) is covered in Headless DOCX processing.
In a Next.js API route
// app/api/fill-template/route.ts
import { processTemplate } from '@eigenpal/docx-editor-core/headless';
export async function POST(req: Request) {
const formData = await req.formData();
const file = formData.get('file') as File;
const variables = JSON.parse(formData.get('variables') as string);
const buf = await file.arrayBuffer();
const filled = processTemplate(buf, variables);
return new Response(filled, {
headers: {
'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
},
});
}Template processing utilities
import {
processTemplate,
getTemplateTags,
validateTemplate,
} from '@eigenpal/docx-editor-core/headless';
// Get all template variables from a DOCX
const tags = getTemplateTags(buf);
// → ['name', 'date', 'total']
// Validate template syntax
const result = validateTemplate(buf);
// → { valid: boolean, errors: TemplateError[], tags: string[] }
// Fill template with string values
const filled = processTemplate(buf, {
name: 'Jane Doe',
date: '2026-07-01',
total: '$9.99',
});For loops and nested data, use processTemplateAdvanced(buf, data) from the same entry point.
CorePlugin interface
CorePlugins extend DocumentAgent with custom command handlers:
interface CorePlugin {
id: string;
name: string;
version?: string;
description?: string;
commandHandlers?: Record<string, CommandHandler>;
mcpTools?: McpToolDefinition[];
initialize?: () => void | Promise<void>;
destroy?: () => void | Promise<void>;
dependencies?: string[];
}Fields
| Field | Required | Description |
|---|---|---|
id | Yes | Unique identifier |
name | Yes | Human-readable name |
version | No | Semver version string |
description | No | Short description |
commandHandlers | No | Map of command type → handler function |
mcpTools | No | MCP tool definitions exposed via the registry |
initialize | No | Called once during registration |
destroy | No | Cleanup on unregistration |
dependencies | No | IDs of plugins that must be registered first |
Command handlers
A command handler is a pure function that receives a Document and a command, then returns a new Document:
type CommandHandler = (doc: Document, command: PluginCommand) => Document;
interface PluginCommand {
type: string;
id?: string;
position?: Position;
range?: Range;
[key: string]: unknown;
}Example: a plugin that adds watermark text:
import type { Document } from '@eigenpal/docx-editor-core';
import type { CorePlugin, PluginCommand } from '@eigenpal/docx-editor-core/core-plugins';
const watermarkPlugin: CorePlugin = {
id: 'watermark',
name: 'Watermark',
commandHandlers: {
addWatermark(doc: Document, cmd: PluginCommand) {
const text = (cmd as { text: string }).text;
// ..transform doc to add a watermark header
return doc;
},
},
};Use it:
import { pluginRegistry } from '@eigenpal/docx-editor-core/core-plugins';
pluginRegistry.register(watermarkPlugin);
const handler = pluginRegistry.getCommandHandler('addWatermark');
if (handler) {
const newDoc = handler(doc, { type: 'addWatermark', text: 'DRAFT' });
}PluginRegistry
The global pluginRegistry manages all CorePlugins:
import { pluginRegistry } from '@eigenpal/docx-editor-core/core-plugins';
// Register
pluginRegistry.register(myPlugin);
// Query
pluginRegistry.has('watermark'); // true
pluginRegistry.getAll(); // CorePlugin[]
pluginRegistry.getCommandTypes(); // ['addWatermark']
// Unregister
pluginRegistry.unregister('watermark');
// Batch registration
import { registerPlugins } from '@eigenpal/docx-editor-core/core-plugins';
registerPlugins([pluginA, pluginB]);Reference implementation: docxtemplater plugin
The built-in docxtemplaterPlugin in packages/core/src/core-plugins/docxtemplater/ is a full reference:
- Command handlers:
insertTemplateVariable,replaceWithTemplateVariable - Lazy dependency validation:
processTemplatechecks fordocxtemplater/pizzipat call time
import { pluginRegistry, docxtemplaterPlugin } from '@eigenpal/docx-editor-core/core-plugins';
pluginRegistry.register(docxtemplaterPlugin);
// Now DocumentAgent can dispatch insertTemplateVariable commandsNote: there is also a separate EditorPlugin for template UI (packages/react/src/plugins/template/) that handles syntax highlighting and the annotation panel in the browser. The two systems are independent but complement each other; a single feature can span both.
Next steps
- EditorPlugin API: browser-side UI plugins
- Examples & cookbook: advanced patterns
- Headless DOCX processing: the full DocumentAgent and parser surface
EditorPlugin API
Full reference for browser-side EditorPlugins: the plugin interface, lifecycle, panels, overlays, ProseMirror plugins, CSS injection, and limitations.
Examples & cookbook
A cookbook of plugin patterns: keyboard shortcuts, decorations, overlays, transaction filters, and recipes built against the editor plugin API.