Quickstart
Load, edit, and save a .docx in the browser with React. Copy-paste setup: a file input, the editor component, and a download button, in one file.
This page builds a browser editor that opens a local .docx and downloads the edited document.
Install
The adapter carries the string catalog and holds the engine as a peer, so install both.
npm install @docx-editor.dev/react @docx-editor.dev/coreOn Next.js, Remix, or other SSR frameworks the editor must render client-side; mounting it during SSR throws window is not defined. Use the recipe in Installation. The code below works as-is in client-rendered apps such as Vite.
Load, edit, save
The whole flow in one file. A file input feeds the editor, the editor handles editing (typing, formatting, undo, tables), and a button serializes the current state back to a .docx download.
// App.tsx
import { useRef, useState } from 'react';
import { DocxEditor, type DocxEditorRef } from '@docx-editor.dev/react';
import '@docx-editor.dev/core/styles/editor.css';
export default function App() {
const editorRef = useRef<DocxEditorRef>(null);
const [file, setFile] = useState<File | null>(null);
const [bytes, setBytes] = useState<Uint8Array>();
async function pick(e: React.ChangeEvent<HTMLInputElement>) {
const picked = e.target.files?.[0] ?? null;
setFile(picked);
setBytes(picked ? new Uint8Array(await picked.arrayBuffer()) : undefined);
}
async function download() {
const buffer = await editorRef.current?.save();
if (!buffer) return;
const blob = new Blob([buffer], {
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = file?.name ?? 'document.docx';
a.click();
URL.revokeObjectURL(url);
}
return (
<div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
<div style={{ padding: 8, display: 'flex', gap: 8 }}>
<input type="file" accept=".docx" onChange={pick} />
<button onClick={download}>Download .docx</button>
</div>
<div style={{ flex: 1, minHeight: 0 }}>
{bytes && <DocxEditor ref={editorRef} document={bytes} mode="edit" />}
</div>
</div>
);
}Four things to know about this code:
documenttakes aUint8Array, anArrayBuffer, or aDocumentHandle. Omit it to mount an empty editor.modeis'edit'or'view', and is read at mount. Remount to change it.save()on the ref returnsPromise<ArrayBuffer | null>: a complete.docx, ornullwhen there is no document. Parsing and serialization both happen in the browser; the document never touches a server.<DocxEditor>fills its parent, so give it a box with a real height. The stylesheet import is required once per app.
Fetch instead of a file input (optional)
Loading a template from your own server is the same prop with fetched bytes:
const bytes = new Uint8Array(await fetch('/template.docx').then((r) => r.arrayBuffer()));
// <DocxEditor document={bytes} />To react to the built-in Save action (Cmd+S, or File → Save) instead of adding your own button, pass onSave. It replaces the packaged behavior, so read the bytes off the ref:
<DocxEditor
ref={editorRef}
document={bytes}
onSave={async () => {
const buffer = await editorRef.current?.save();
if (buffer) await upload(buffer);
}}
/>Open a real .docx from your machine
Run your dev server, click the file input, and pick a .docx: a contract, a CV, or a report with tables and headers. The editor parses it client-side and the download button writes the current state back. Check the result in Microsoft Word. If something renders or saves incorrectly, file an issue with the document.
No file handy? Try the live demo first.
Next steps
- Installation for Next.js, Remix, and Astro specifics
- Composition to replace the packaged chrome with your own
- Word fidelity if you're evaluating feature support and round-trip behavior
- Props and ref methods for everything
<DocxEditor>can do
Introduction
Open source WYSIWYG DOCX editor for React. Runs in the browser: .docx in, .docx out, with tracked changes, comments, content controls, and custom nodes.
Installation
Install the DOCX editor in React, Next.js, Vite, Remix, or Astro. Covers the stylesheet import, the client-only SSR boundary, fonts, and which package to pick.