Quickstart
Load, edit, and save a .docx in the browser with React or Vue in one file.
Build a browser editor that opens a local .docx and downloads the edited file.
Install the editor
Install an adapter and its engine peer:
npm install @docx-editor.dev/react @docx-editor.dev/corenpm install @docx-editor.dev/vue @docx-editor.dev/coreThis example runs in client-rendered apps such as Vite. In Next.js, Nuxt, Remix, or Astro, render the editor on the client only. See Installation.
Load and save a document
This component reads a file input, edits the document, and downloads the result:
// 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>
);
}<!-- App.vue -->
<script setup lang="ts">
import { ref, shallowRef } from 'vue';
import { DocxEditor, type DocxEditorRef } from '@docx-editor.dev/vue';
import '@docx-editor.dev/vue/styles.css';
const editorRef = ref<DocxEditorRef | null>(null);
const fileName = ref<string>();
const bytes = shallowRef<Uint8Array>();
async function pick(event: Event) {
const picked = (event.target as HTMLInputElement).files?.[0];
fileName.value = picked?.name;
bytes.value = picked ? new Uint8Array(await picked.arrayBuffer()) : undefined;
}
async function download() {
const buffer = await editorRef.value?.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 = fileName.value ?? 'document.docx';
a.click();
URL.revokeObjectURL(url);
}
</script>
<template>
<div style="height: 100vh; display: flex; flex-direction: column">
<div style="padding: 8px; display: flex; gap: 8px">
<input type="file" accept=".docx" @change="pick" />
<button type="button" @click="download">Download .docx</button>
</div>
<div style="flex: 1; min-height: 0">
<DocxEditor v-if="bytes" ref="editorRef" :document="bytes" mode="edit" />
</div>
</div>
</template>Parsing, editing, and serialization run in the browser. The editor does not upload the document anywhere.
Check the required options
| Option | Values | Notes |
|---|---|---|
document | Uint8Array, ArrayBuffer, DocumentHandle, or 'blank' | 'blank' opens an empty document. An omitted document means no document: the editor shows its loading screen, and editing controls stay unavailable until a document loads. File > Open works once the editor instance exists. |
mode | 'edit' (default), 'view', or 'suggesting' | Changes apply without a remount. 'suggesting' requires a review module and a nonempty author. |
save() on the ref | Promise<ArrayBuffer | null> | Returns a complete .docx, or null when no document is loaded. |
| Stylesheet | @docx-editor.dev/core/styles/editor.css (React) or @docx-editor.dev/vue/styles.css (Vue) | Import it once per app. |
| Container height | Any nonzero CSS height | The editor fills its parent. A parent without a height collapses. |
Limits
- The packaged
<DocxEditor>shows a document page with loading status while a document opens. - To handle the built-in File > Save action, use
onSave(React) or@save(Vue). The handler replaces the packaged action, so read the bytes through the ref. - Tracked changes and comments require
@docx-editor.dev/pro. - To load from a URL or autosave, see Loading and saving.
Next steps
- Loading and saving: Fetch, save handlers, and autosave.
- React props or Vue props: Configure the packaged editor.
- Live demo: Try a document before you install.