docx-editor 1.x has shipped. Vue support, i18n, agents.

Migration guide →
TutorialMay 19, 20264 min read

Vue DOCX Editor: Edit Word Documents in Vue 3

Add a DOCX editor to a Vue 3 app with @eigenpal/docx-editor-vue. Install, render, load, and save .docx files in the browser.

To add DOCX editing to a Vue 3 app, install @eigenpal/docx-editor-vue, pass an ArrayBuffer, and render <DocxEditor>. Editing runs in the browser; your app only uploads the document if you add upload code. This guide covers install, loading and saving .docx, Nuxt, tracked changes, comments, realtime collaboration, and agent tools.

Live demo

Install

npm install @eigenpal/docx-editor-vue

The package pulls @eigenpal/docx-editor-core and @eigenpal/docx-editor-i18n transitively. One install for the editor; add @eigenpal/docx-editor-agents if you want the AI agent toolkit on top.

Render <DocxEditor> in Vue 3

<script setup lang="ts">
import { ref } from "vue";
import { DocxEditor } from "@eigenpal/docx-editor-vue";
import "@eigenpal/docx-editor-vue/styles.css";
 
const buf = ref<ArrayBuffer | null>(null);
</script>
 
<template>
  <DocxEditor :document-buffer="buf" />
</template>

That's a working WYSIWYG Word document editor in your Vue 3 app. null mounts an empty document. Pass an ArrayBuffer to load a .docx file.

Load a .docx file

From a URL:

<script setup lang="ts">
import { ref, watchEffect } from "vue";
import { DocxEditor } from "@eigenpal/docx-editor-vue";
import "@eigenpal/docx-editor-vue/styles.css";
 
const props = defineProps<{ url: string }>();
const buf = ref<ArrayBuffer | null>(null);
 
watchEffect(async () => {
  buf.value = await fetch(props.url).then((r) => r.arrayBuffer());
});
</script>
 
<template>
  <DocxEditor :document-buffer="buf" />
</template>

From a file picker:

<script setup lang="ts">
import { ref } from "vue";
import { DocxEditor } from "@eigenpal/docx-editor-vue";
 
const buf = ref<ArrayBuffer | null>(null);
 
async function onFile(e: Event) {
  const file = (e.target as HTMLInputElement).files?.[0];
  if (file) buf.value = await file.arrayBuffer();
}
</script>
 
<template>
  <input type="file" accept=".docx" @change="onFile" />
  <DocxEditor v-if="buf" :document-buffer="buf" />
</template>

The editor parses OOXML in the browser. No server round-trip, no file upload.

Save a .docx file

<script setup lang="ts">
import { useTemplateRef } from "vue";
import { DocxEditor, type DocxEditorRef } from "@eigenpal/docx-editor-vue";
 
const editor = useTemplateRef<DocxEditorRef>("editor");
 
async function save() {
  const buf = await editor.value?.save();
  if (!buf) return;
  // Trigger a browser download:
  const blob = new Blob([buf], {
    type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  });
  const a = Object.assign(document.createElement("a"), {
    href: URL.createObjectURL(blob),
    download: "edited.docx",
  });
  a.click();
  URL.revokeObjectURL(a.href);
}
</script>
 
<template>
  <button @click="save">Download .docx</button>
  <DocxEditor ref="editor" :document-buffer="null" />
</template>

save() returns an ArrayBuffer of OOXML bytes, the same format the editor reads. Use the Word fidelity checklist before relying on a specific document workflow in production.

Nuxt

For Nuxt 3 and 4, install @eigenpal/nuxt-docx-editor. It wraps this adapter and auto-imports an SSR-safe <DocxEditor>, so you do not need a <ClientOnly> wrapper or Vite optimizer config:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ["@eigenpal/nuxt-docx-editor"],
});

<DocxEditor> is then available in any page or component with no import, and the stylesheet is injected for you. The Nuxt DOCX editor guide covers module options, loading, and saving.

Included features

  • Round-trip fidelity. Open a Word .docx, edit, save, and reopen in Word. Test your own documents against the fidelity checklist before rollout.
  • Tracked changes. Suggesting mode wraps every edit as a revision marker with author attribution. Accept or reject individually or in bulk.
  • Comments. Threaded comments anchored to text ranges. Add, reply, resolve, delete.
  • Realtime collaboration. Wire to a Yjs document to get live multi-user editing with cursors and presence. Works with y-webrtc (zero infra), PartyKit, Liveblocks, or any Yjs provider.
  • Document templates. A templatePlugin highlights {{variable}} placeholders. Fill them programmatically or through the built-in panel.
  • Plugins. Extensible architecture with ProseMirror plugins for custom toolbar actions, keyboard shortcuts, document transformations.
  • i18n. Built-in localization for English, Polish, German, Brazilian Portuguese, Hebrew, Turkish, Simplified Chinese, with per-locale code-splitting.

Tracked changes in Vue

<script setup lang="ts">
import { ref } from "vue";
import { DocxEditor, type EditorMode } from "@eigenpal/docx-editor-vue";
 
const props = defineProps<{ buf: ArrayBuffer; reviewer: string }>();
const mode = ref<EditorMode>("suggesting");
</script>
 
<template>
  <DocxEditor
    :document-buffer="buf"
    :author="reviewer"
    :mode="mode"
    @mode-change="(m) => (mode = m)"
  />
</template>

Edits made in "suggesting" mode wrap as tracked changes with reviewer as the author. The document owner can accept or reject them later.

Comments in Vue

<script setup lang="ts">
import { ref } from "vue";
import { DocxEditor } from "@eigenpal/docx-editor-vue";
import type { Comment } from "@eigenpal/docx-editor-core";
 
defineProps<{ buf: ArrayBuffer; author: string }>();
const comments = ref<Comment[]>([]);
</script>
 
<template>
  <DocxEditor
    :document-buffer="buf"
    :author="author"
    :comments="comments"
    @comments-change="(next) => (comments = next)"
  />
</template>

Controlled comments mean you own the source of truth. Mirror comments into a Y.Array on a shared Yjs doc and you get live comment sync across users.

Realtime collaboration (Yjs)

<script setup lang="ts">
import { ref, onUnmounted } from "vue";
import * as Y from "yjs";
import { WebrtcProvider } from "y-webrtc";
import { ySyncPlugin, yCursorPlugin, yUndoPlugin } from "y-prosemirror";
import { DocxEditor } from "@eigenpal/docx-editor-vue";
 
defineProps<{ buf: ArrayBuffer }>();
const ydoc = new Y.Doc();
const provider = new WebrtcProvider("room-1", ydoc);
const yXml = ydoc.getXmlFragment("docx");
 
const plugins = [
  ySyncPlugin(yXml),
  yCursorPlugin(provider.awareness),
  yUndoPlugin(),
];
 
onUnmounted(() => provider.destroy());
</script>
 
<template>
  <DocxEditor
    :document-buffer="buf"
    :external-plugins="plugins"
  />
</template>

Yjs handles shared editing state, cursors, and presence across browsers. Use the Yjs provider that fits your infrastructure model.

AI agents driving the editor

@eigenpal/docx-editor-agents/vue exposes the agent toolkit as a Vue composable. The 14 tools (read, find, comment, suggest, scroll) drive the editor live; the agent's comments and tracked changes land as the model streams tokens.

<script setup lang="ts">
import { useTemplateRef } from "vue";
import { DocxEditor, type DocxEditorRef } from "@eigenpal/docx-editor-vue";
import { useDocxAgentTools } from "@eigenpal/docx-editor-agents/vue";
import { useChat } from "@ai-sdk/vue";
 
defineProps<{ buf: ArrayBuffer }>();
const editor = useTemplateRef<DocxEditorRef>("editor");
const { tools } = useDocxAgentTools({ editorRef: editor });
const chat = useChat({ api: "/api/agent-chat", body: { tools } });
</script>
 
<template>
  <DocxEditor ref="editor" :document-buffer="buf" />
</template>

Server-side route uses getAiSdkTools() from @eigenpal/docx-editor-agents/ai-sdk/server and any OpenAI / Anthropic / Vercel-AI-SDK-compatible model.

Open source, Apache 2.0

@eigenpal/docx-editor-vue is open source under Apache 2.0. Use it in personal and commercial projects, modify the source, redistribute. No usage limits, no watermarks, no premium tier. The source lives at github.com/eigenpal/docx-editor in packages/vue/.

Comparison to other Vue Word editors

The Vue ecosystem has had a thin selection of .docx editors. Most options either:

  • Render to HTML and lose OOXML fidelity (no tables-of-contents, no page layout, no tracked changes when round-tripped).
  • Are SaaS components with server-side processing (your documents touch their servers).
  • Are React libraries with a Vue wrapper (extra bundle, extra hydration cost).

@eigenpal/docx-editor-vue is a published Vue 3 adapter built on a shared core. It uses the same OOXML parser as the React adapter and the same plugin contract, without a React wrapper. Editing happens client-side; documents only leave the browser if your app uploads them.

Where to next