How to Convert Word to PDF in the Browser with Vue 3, mammoth, and html2pdf.js
Converting Word documents to PDFs on the server is the classic approach: upload the file, run LibreOffice or a cloud API, send the result back. But that means your users’ resumes, contracts, and reports touch your infrastructure. I wanted something simpler for en.sotool.top : pick a .docx file in the browser, preview the parsed content, and download a PDF. No server involved. Here is how I built it with Vue 3, mammoth , and html2pdf.js . Why Client-Side? The main reason is privacy. Resumes, contracts, tax documents — users do not want them on a stranger’s server. Client-side conversion also means: No upload bandwidth limits No file size caps from your server No storage to clean up Works offline after the page loads The trade-off is that very complex documents are limited by the browser’s rendering capabilities. For typical office documents, that is fine. The Stack Vue 3 — UI, file handling, and reactive state mammoth — Parse .docx files into clean HTML html2pdf.js — Render the HTML into a PDF using html2canvas + jsPDF Native File API — File selection npm install mammoth html2pdf.js Loading the Word Document The first step is reading the uploaded .docx file into an ArrayBuffer , then converting it to HTML with mammoth . import mammoth from ' mammoth ' ; async function convertDocxToHtml ( file ) { const arrayBuffer = await file . arrayBuffer (); const result = await mammoth . convertToHtml ({ arrayBuffer }); return result . value ; } mammoth intentionally produces simple, clean HTML. It ignores complex formatting like text boxes and embedded fonts, which makes the output predictable. I keep the HTML in a reactive ref and render it in a preview panel: < template > <div ref= "previewRef" class= "word-preview" v-html= "htmlContent" ></div> </ template > < script setup > import { ref } from ' vue ' ; const htmlContent = ref ( '' ); const previewRef = ref ( null ); </ script > Generating the PDF Once the user is happy with the preview, html2pdf.js turns the preview element