INTEGRATION GUIDE

Build a client-side Word to Markdown download

Convert DOCX to Markdown client-side with JavaScript or TypeScript. Process Word files in the browser and download Markdown with images.

Add a Word-to-Markdown download to a browser application. A user selects a .docx file and receives a ZIP containing Markdown, images, and metadata. The file is converted client-side.

Run the Client starter

Download the Client starter. Extract the ZIP, open its client directory, and use Node.js 22.12 or later:

npm install
npm run dev

Open the URL printed by Vite. Select a DOCX file to view Markdown, then download the Markdown, images, and metadata as a ZIP. This standalone TypeScript project uses installed packages, with no React dependency or monorepo aliases. Commit the generated lockfile to keep your package versions fixed.

Configure font and WebAssembly assets

The starter includes this Vite configuration:

import { defineConfig } from 'vite';

export default defineConfig({
  optimizeDeps: {
    exclude: [
      '@docx-editor.dev/docx-to-markdown',
      '@docx-editor.dev/core',
      '@docx-editor.dev/fonts',
    ],
  },
  build: { assetsInlineLimit: 0 },
});

Excluding these packages from development pre-bundling preserves their package-relative font and WASM URLs. Vite emits the referenced assets when building for production. You do not need to copy fonts manually.

npm run build
npm run preview

Deploy the complete dist directory, including assets. Test a DOCX on the deployed site to check that font and WASM requests succeed. This setup targets a Vite browser application; other bundlers can require different asset handling. Use the package documentation for the conversion API.

Download Markdown and images

Use createMarkdownZip() for a portable download:

import { createMarkdownZip, exportMarkdown } from '@docx-editor.dev/docx-to-markdown';

async function download(file: File) {
  const bytes = new Uint8Array(await file.arrayBuffer());
  const result = await exportMarkdown(bytes, { images: true });
  const zip = await createMarkdownZip(result);
  const blob = new Blob([zip.slice().buffer], {
    type: 'application/zip',
  });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = 'document.zip';
  link.click();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}

The ZIP contains document.md, document.json, and a media/ directory. Use relative image URLs for portable bundles; custom hosted URLs are not accepted by the ZIP helper.

Understand network access

Browser conversion does not require uploading the document. Font resolvers can still make network requests. The current demo uses bundled substitutes and an optional Google Fonts fallback.

For an offline application, serve font and WebAssembly assets locally and ensure your font resolvers use local data. Test the fonts required by your documents before describing the application as offline.

Use fonts for faces that must take precedence over the bundled substitutes. Use fallbackFonts for additional resolvers, such as googleFonts(), after bundled fonts. CSS fonts on your application page do not configure the export engine. See the package's font configuration and fallback example and inspect result.fontResolution to confirm which faces were used.

Match the demo settings

The interactive demo uses HTML image dimensions and Google Fonts fallback. The starter uses bundled fonts and standard Markdown images by default. To use the demo settings, replace the options in convert.ts:

import { googleFonts } from '@docx-editor.dev/fonts/google';

const result = await exportMarkdown(bytes, {
  images: { syntax: 'html' },
  fallbackFonts: googleFonts(),
  resourceTimeoutMs: 30_000,
});

The starter already declares the fonts package. In an existing app, install it with npm install @docx-editor.dev/fonts before adding this import. Remote fallback requires CDN access. Matching these options does not guarantee identical pagination across package versions or font configurations.

Connect a file input

Call download() when the user selects a DOCX file:

<label for="document">Convert a Word document</label>
<input id="document" type="file" accept=".docx" />
<p id="status" role="status"></p>
const input = document.querySelector<HTMLInputElement>('#document');
const status = document.querySelector<HTMLElement>('#status');

input?.addEventListener('change', async () => {
  const file = input.files?.[0];
  if (!file || !status) return;

  input.disabled = true;
  status.textContent = 'Converting document…';
  try {
    await download(file);
    status.textContent = 'Download ready.';
  } catch {
    status.textContent = 'Could not convert this document. Try another DOCX file.';
  } finally {
    input.disabled = false;
  }
});

Apply a file-size limit before reading the document into memory. The file input's accept attribute helps with selection; the converter still needs to validate the file.

Next steps

INSTALL THE PACKAGE

npm install @docx-editor.dev/docx-to-markdown @docx-editor.dev/core