Getting Started

Installation

Framework-specific installation guides for Next.js, Vite, Remix, Astro, and Vue.

Prerequisites

  • React 18+ (or React 19)
  • Node.js 18+

Install the Package

npm install @eigenpal/docx-js-editor

Don't forget to import the styles:

import '@eigenpal/docx-js-editor/styles.css';

Next.js

The editor uses browser APIs and must be loaded client-side. Use next/dynamic with ssr: false:

// components/Editor.tsx
'use client';
 
import dynamic from 'next/dynamic';
 
const DocxEditor = dynamic(
  () => import('@eigenpal/docx-js-editor').then((mod) => mod.DocxEditor),
  { ssr: false }
);
 
import '@eigenpal/docx-js-editor/styles.css';
 
export function Editor({ buffer }: { buffer: ArrayBuffer }) {
  return <DocxEditor documentBuffer={buffer} showToolbar />;
}

Add the package to transpilePackages in next.config.ts:

// next.config.ts
const nextConfig = {
  transpilePackages: ['@eigenpal/docx-js-editor'],
};
export default nextConfig;

Vite (React)

Works out of the box — no special configuration needed:

import { useState, useEffect } from 'react';
import { DocxEditor } from '@eigenpal/docx-js-editor';
import '@eigenpal/docx-js-editor/styles.css';
 
function App() {
  const [buffer, setBuffer] = useState<ArrayBuffer | null>(null);
 
  useEffect(() => {
    fetch('/template.docx')
      .then((res) => res.arrayBuffer())
      .then(setBuffer);
  }, []);
 
  if (!buffer) return <div>Loading...</div>;
  return <DocxEditor documentBuffer={buffer} showToolbar />;
}

Remix

Use ClientOnly to prevent server rendering:

import { ClientOnly } from 'remix-utils/client-only';
import { DocxEditor } from '@eigenpal/docx-js-editor';
import '@eigenpal/docx-js-editor/styles.css';
 
export default function EditorRoute() {
  const [buffer, setBuffer] = useState<ArrayBuffer | null>(null);
 
  useEffect(() => {
    fetch('/template.docx')
      .then((res) => res.arrayBuffer())
      .then(setBuffer);
  }, []);
 
  return (
    <ClientOnly fallback={<div>Loading editor...</div>}>
      {() => buffer && <DocxEditor documentBuffer={buffer} showToolbar />}
    </ClientOnly>
  );
}

Astro

Use a React island with client:only="react":

---
// src/pages/editor.astro
---
<html>
  <body>
    <EditorWrapper client:only="react" />
  </body>
</html>
// src/components/EditorWrapper.tsx
import { useState, useEffect } from 'react';
import { DocxEditor } from '@eigenpal/docx-js-editor';
import '@eigenpal/docx-js-editor/styles.css';
 
export default function EditorWrapper() {
  const [buffer, setBuffer] = useState<ArrayBuffer | null>(null);
 
  useEffect(() => {
    fetch('/template.docx')
      .then((res) => res.arrayBuffer())
      .then(setBuffer);
  }, []);
 
  if (!buffer) return <div>Loading...</div>;
  return <DocxEditor documentBuffer={buffer} showToolbar />;
}

Vue (via Web Component wrapper)

The editor is a React component, but you can wrap it for Vue using @veaury/vue-react:

npm install @eigenpal/docx-js-editor @veaury/vue-react react react-dom
<template>
  <ReactDocxEditor v-if="buffer" :documentBuffer="buffer" :showToolbar="true" />
</template>
 
<script setup>
import { ref, onMounted } from 'vue';
import { applyReactInVue } from '@veaury/vue-react';
import { DocxEditor } from '@eigenpal/docx-js-editor';
import '@eigenpal/docx-js-editor/styles.css';
 
const ReactDocxEditor = applyReactInVue(DocxEditor);
const buffer = ref(null);
 
onMounted(async () => {
  const res = await fetch('/template.docx');
  buffer.value = await res.arrayBuffer();
});
</script>

Example Repositories

Full working examples for each framework are available on GitHub: