Open-source WYSIWYG DOCX editor for React. Open, edit, and save .docx files entirely in the browser — no server required. Try the live demo.
We built it for ourselves in eigenpal.com in order to have an editor for .docx files, which serve as AI document workflow output templates for our clients.
| Framework | Example |
|---|---|
examples/vite (demo) |
|
examples/nextjs |
|
examples/remix |
|
examples/astro |
npm install @eigenpal/docx-js-editorimport { useRef } from 'react';
import { DocxEditor, type DocxEditorRef } from '@eigenpal/docx-js-editor';
import '@eigenpal/docx-js-editor/styles.css';
function Editor({ file }: { file: ArrayBuffer }) {
const editorRef = useRef<DocxEditorRef>(null);
const handleSave = async () => {
const buffer = await editorRef.current?.save();
if (buffer) {
await fetch('/api/documents/1', { method: 'PUT', body: buffer });
}
};
return (
<>
<button onClick={handleSave}>Save</button>
<DocxEditor ref={editorRef} documentBuffer={file} onChange={() => {}} />
</>
);
}Next.js / SSR: The editor requires the DOM. Use a dynamic import or lazy
useEffectload to avoid server-side rendering issues.
| Prop | Type | Default | Description |
|---|---|---|---|
documentBuffer |
ArrayBuffer | Uint8Array | Blob | File |
— | .docx file contents to load |
document |
Document |
— | Pre-parsed document (alternative to buffer) |
readOnly |
boolean |
false |
Read-only preview (hides toolbar, rulers, panel) |
showToolbar |
boolean |
true |
Show formatting toolbar |
showRuler |
boolean |
false |
Show horizontal & vertical rulers |
rulerUnit |
'inch' | 'cm' |
'inch' |
Unit for ruler display |
showZoomControl |
boolean |
true |
Show zoom controls in toolbar |
showVariablePanel |
boolean |
true |
Show template variable panel |
variablePanelPosition |
'left' | 'right' |
'right' |
Variable panel position |
variableDescriptions |
Record<string, string> |
— | Descriptions for template variables |
showPrintButton |
boolean |
true |
Show print button in toolbar |
showPageNumbers |
boolean |
true |
Show page number indicator |
enablePageNavigation |
boolean |
true |
Enable interactive page navigation |
pageNumberPosition |
string |
'bottom-center' |
Position of page number indicator |
showOutline |
boolean |
false |
Show document outline sidebar (table of contents) |
showMarginGuides |
boolean |
false |
Show page margin guide boundaries |
marginGuideColor |
string |
'#c0c0c0' |
Color for margin guides |
initialZoom |
number |
1.0 |
Initial zoom level |
theme |
Theme | null |
— | Theme for styling |
toolbarExtra |
ReactNode |
— | Custom toolbar items appended to the toolbar |
placeholder |
ReactNode |
— | Placeholder when no document is loaded |
loadingIndicator |
ReactNode |
— | Custom loading indicator |
className |
string |
— | Additional CSS class name |
style |
CSSProperties |
— | Additional inline styles |
onChange |
(doc: Document) => void |
— | Called on document change |
onSave |
(buffer: ArrayBuffer) => void |
— | Called on save |
onError |
(error: Error) => void |
— | Called on error |
onSelectionChange |
(state: SelectionState | null) => void |
— | Called on selection change |
onFontsLoaded |
() => void |
— | Called when fonts finish loading |
onPrint |
() => void |
— | Called when print is triggered |
onCopy |
() => void |
— | Called when content is copied |
onCut |
() => void |
— | Called when content is cut |
onPaste |
() => void |
— | Called when content is pasted |
const ref = useRef<DocxEditorRef>(null);
await ref.current.save(); // Returns ArrayBuffer of the .docx
ref.current.getDocument(); // Current document object
ref.current.setZoom(1.5); // Set zoom to 150%
ref.current.focus(); // Focus the editor
ref.current.scrollToPage(3); // Scroll to page 3
ref.current.print(); // Print the documentUse readOnly for a preview-only viewer. This disables editing, caret, and selection UI.
<DocxEditor documentBuffer={file} readOnly />Extend the editor with the plugin system. Wrap DocxEditor in a PluginHost and pass plugins that can contribute ProseMirror plugins, side panels, document overlays, and custom CSS:
import { DocxEditor, PluginHost, templatePlugin } from '@eigenpal/docx-js-editor';
function Editor({ file }: { file: ArrayBuffer }) {
return (
<PluginHost plugins={[templatePlugin]}>
<DocxEditor documentBuffer={file} />
</PluginHost>
);
}| Plugin | Description |
|---|---|
| Docxtemplater | Syntax highlighting and annotation panel for docxtemplater tags |
See docs/PLUGINS.md for the full plugin API, including how to create custom plugins with panels, overlays, and ProseMirror integrations.
- Full WYSIWYG editing with Microsoft Word fidelity
- Text and paragraph formatting (bold, italic, fonts, colors, alignment, spacing)
- Tables, images, hyperlinks
- Extensible plugin architecture
- Undo/redo, find & replace, keyboard shortcuts
- Print preview
- Zero server dependencies
bun install
bun run dev # Vite example on localhost:5173
bun run dev:nextjs # Next.js example on localhost:3000
bun run dev:remix # Remix example on localhost:3001
bun run dev:astro # Astro example on localhost:4321Each example is independently deployable. Copy any examples/<framework>/ directory to start your own project — just npm install and go.
MIT