SuperDoc works with Nuxt 4+ as a client-side Vue component. Set ssr: false in your Nuxt config — SuperDoc manipulates the DOM directly and doesn’t run server-side.
Install
export default defineNuxtConfig ({
ssr: false ,
css: [ 'superdoc/style.css' ] ,
compatibilityDate: '2025-07-15' ,
})
ssr: false is required. SuperDoc renders documents in the browser using DOM APIs that aren’t available server-side.
Basic setup
Nuxt auto-imports Vue’s ref, watch, and lifecycle hooks — no manual imports needed.
< script setup lang = "ts" >
import { SuperDoc } from 'superdoc' ;
const container = ref < HTMLDivElement | null >( null );
const file = ref < File | null >( null );
let superdoc : SuperDoc | null = null ;
const handleFile = ( e : Event ) => {
const input = e . target as HTMLInputElement ;
if ( input . files ?.[ 0 ]) file . value = input . files [ 0 ];
};
const initEditor = () => {
if ( ! container . value || ! file . value ) return ;
superdoc ?. destroy ();
superdoc = new SuperDoc ({
selector: container . value ,
document: file . value ,
});
};
watch ( file , initEditor );
onBeforeUnmount (() => superdoc ?. destroy ());
</ script >
< template >
< div >
< div style = " padding : 1 rem ; background : #f5f5f5 " >
< input type = "file" accept = ".docx" @ change = " handleFile " />
</ div >
< div ref = "container" style = " height : calc ( 100 vh - 60 px ) " / >
</ div >
</ template >
Full component
Build a reusable DOCX editor component with controls:
app/components/DocEditor.vue
< script setup lang = "ts" >
import { SuperDoc } from 'superdoc' ;
const props = defineProps <{
document : string | File | Blob ;
}>();
const editor = ref < HTMLDivElement | null >( null );
let superdoc : SuperDoc | null = null ;
onMounted (() => {
if ( ! editor . value ) return ;
superdoc = new SuperDoc ({
selector: editor . value ,
document: props . document ,
documentMode: 'editing' ,
});
});
onBeforeUnmount (() => superdoc ?. destroy ());
const setMode = ( mode : 'editing' | 'suggesting' | 'viewing' ) => {
superdoc ?. setDocumentMode ( mode );
};
const exportFinal = async () => {
await superdoc ?. export ({ isFinalDoc: true });
};
</ script >
< template >
< div >
< div class = "controls" >
< button @ click = " setMode ( 'editing' ) " > Edit </ button >
< button @ click = " setMode ( 'suggesting' ) " > Review </ button >
< button @ click = " setMode ( 'viewing' ) " > View </ button >
< button @ click = " exportFinal " > Export Final </ button >
</ div >
< div ref = "editor" class = "editor-container" / >
</ div >
</ template >
< style scoped >
.editor-container {
height : 700 px ;
border : 1 px solid #e2e8f0 ;
}
.controls {
padding : 1 rem ;
display : flex ;
gap : 0.5 rem ;
}
</ style >
Then use it in a page:
< script setup lang = "ts" >
const file = ref < File | null >( null );
const handleFile = ( e : Event ) => {
const input = e . target as HTMLInputElement ;
if ( input . files ?.[ 0 ]) file . value = input . files [ 0 ];
};
</ script >
< template >
< div >
< input type = "file" accept = ".docx" @ change = " handleFile " />
< DocEditor v-if = " file " : document = " file " />
</ div >
</ template >
Next steps
Vue Integration Full Vue setup and patterns
Configuration All configuration options
Nuxt Example Working Nuxt example on GitHub
Collaboration Real-time collaboration