Skip to content

Integration

Learn how to integrate SuperDoc with various JavaScript frameworks and environments.

SuperDoc is designed to work with any JavaScript environment. Whether you're using React, Vue, Angular, or vanilla JavaScript, SuperDoc provides a seamless integration experience.

React Integration

SuperDoc can be easily integrated into React applications using a wrapper component.

Basic Integration

jsx
import React, { useEffect, useRef } from 'react';
import '@harbour-enterprises/superdoc/style.css';
import { SuperDoc } from '@harbour-enterprises/superdoc';

function SuperDocComponent({ documentId, documentData, user }) {
  const containerRef = useRef(null);
  const superdocRef = useRef(null);

  useEffect(() => {
    // Initialize SuperDoc when the component mounts
    if (containerRef.current && !superdocRef.current) {
      superdocRef.current = new SuperDoc({
        selector: '#superdoc-container',
        documents: [
          {
            id: documentId,
            type: 'docx',
            data: documentData,
          },
        ],
        user: user,
      });
    }

    // Clean up SuperDoc when the component unmounts
    return () => {
      if (superdocRef.current) {
        // Clean up the SuperDoc instance
        superdocRef.current = null;
      }
    };
  }, [documentId, documentData, user]);

  return (
    <div
      id="superdoc-container"
      ref={containerRef}
      style={{ width: '100%', height: '700px' }}></div>
  );
}

export default SuperDocComponent;

Usage in a React Application

jsx
import React, { useState, useEffect } from 'react';
import SuperDocComponent from './SuperDocComponent';

function DocumentEditor() {
  const [documentData, setDocumentData] = useState(null);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    // Fetch document data
    fetch('/api/documents/123')
      .then((response) => response.blob())
      .then((blob) => {
        setDocumentData(blob);
        setIsLoading(false);
      })
      .catch((error) => {
        console.error('Error loading document:', error);
        setIsLoading(false);
      });
  }, []);

  const user = {
    name: 'John Doe',
    email: 'john@example.com',
    image: 'https://example.com/avatar.jpg',
  };

  return (
    <div className="document-editor">
      <h1>Document Editor</h1>
      {isLoading ? (
        <p>Loading document...</p>
      ) : (
        <SuperDocComponent documentId="doc-123" documentData={documentData} user={user} />
      )}
    </div>
  );
}

export default DocumentEditor;

Advanced React Integration

For more complex use cases, you might want to expose SuperDoc methods to your React component:

jsx
import React, { useEffect, useRef, useImperativeHandle, forwardRef } from 'react';
import '@harbour-enterprises/superdoc/style.css';
import { SuperDoc } from '@harbour-enterprises/superdoc';

const SuperDocComponent = forwardRef(({ documentId, documentData, user, onReady }, ref) => {
  const containerRef = useRef(null);
  const superdocRef = useRef(null);

  // Expose SuperDoc methods to parent components
  useImperativeHandle(ref, () => ({
    exportDocx: () => superdocRef.current.exportDocx(),
    exportPdf: () => superdocRef.current.exportPdf(),
    setDocumentMode: (mode) => superdocRef.current.setDocumentMode(mode),
  }));

  useEffect(() => {
    if (containerRef.current && !superdocRef.current) {
      superdocRef.current = new SuperDoc({
        selector: '#superdoc-container',
        documents: [
          {
            id: documentId,
            type: 'docx',
            data: documentData,
          },
        ],
        user: user,
      });

      if (onReady) {
        superdocRef.current.on('ready', onReady);
      }
    }

    return () => {
      if (superdocRef.current) {
        if (onReady) {
          superdocRef.current.off('ready', onReady);
        }
        superdocRef.current = null;
      }
    };
  }, [documentId, documentData, user, onReady]);

  return (
    <div
      id="superdoc-container"
      ref={containerRef}
      style={{ width: '100%', height: '700px' }}></div>
  );
});

export default SuperDocComponent;

Vue Integration

SuperDoc can be integrated with Vue applications, both with Vue 2 and Vue 3.

Vue 3 Integration

vue
<template>
  <div ref="superdocContainer" class="superdoc-container"></div>
</template>

<script>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import '@harbour-enterprises/superdoc/style.css';
import { SuperDoc } from '@harbour-enterprises/superdoc';

export default {
  name: 'SuperDocEditor',
  props: {
    documentId: {
      type: String,
      required: true,
    },
    documentData: {
      type: Object,
      default: null,
    },
    user: {
      type: Object,
      required: true,
    },
  },
  emits: ['ready', 'comments-update'],
  setup(props, { emit }) {
    const superdocContainer = ref(null);
    let superdoc = null;

    onMounted(() => {
      superdoc = new SuperDoc({
        selector: superdocContainer.value,
        documents: [
          {
            id: props.documentId,
            type: 'docx',
            data: props.documentData,
          },
        ],
        user: props.user,
      });

      // Set up event listeners
      superdoc.on('ready', () => {
        emit('ready', superdoc);
      });

      superdoc.on('commentsUpdate', (data) => {
        emit('comments-update', data);
      });
    });

    onBeforeUnmount(() => {
      if (superdoc) {
        // Clean up event listeners
        superdoc.off('ready');
        superdoc.off('commentsUpdate');
        superdoc = null;
      }
    });

    // Expose methods to parent component
    const exportDocx = () => superdoc?.exportDocx();
    const exportPdf = () => superdoc?.exportPdf();
    const setDocumentMode = (mode) => superdoc?.setDocumentMode(mode);

    return {
      superdocContainer,
      exportDocx,
      exportPdf,
      setDocumentMode,
    };
  },
};
</script>

<style scoped>
.superdoc-container {
  width: 100%;
  height: 700px;
}
</style>

Vue 2 Integration

vue
<template>
  <div ref="superdocContainer" class="superdoc-container"></div>
</template>

<script>
import '@harbour-enterprises/superdoc/style.css';
import { SuperDoc } from '@harbour-enterprises/superdoc';

export default {
  name: 'SuperDocEditor',
  props: {
    documentId: {
      type: String,
      required: true,
    },
    documentData: {
      type: Object,
      default: null,
    },
    user: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      superdoc: null,
    };
  },
  mounted() {
    this.superdoc = new SuperDoc({
      selector: this.$refs.superdocContainer,
      documents: [
        {
          id: this.documentId,
          type: 'docx',
          data: this.documentData,
        },
      ],
      user: this.user,
    });

    // Set up event listeners
    this.superdoc.on('ready', this.handleReady);
    this.superdoc.on('commentsUpdate', this.handleCommentsUpdate);
  },
  beforeDestroy() {
    if (this.superdoc) {
      // Clean up event listeners
      this.superdoc.off('ready', this.handleReady);
      this.superdoc.off('commentsUpdate', this.handleCommentsUpdate);
      this.superdoc = null;
    }
  },
  methods: {
    handleReady() {
      this.$emit('ready', this.superdoc);
    },
    handleCommentsUpdate(data) {
      this.$emit('comments-update', data);
    },
    exportDocx() {
      return this.superdoc?.exportDocx();
    },
    exportPdf() {
      return this.superdoc?.exportPdf();
    },
    setDocumentMode(mode) {
      this.superdoc?.setDocumentMode(mode);
    },
  },
};
</script>

<style scoped>
.superdoc-container {
  width: 100%;
  height: 700px;
}
</style>

Vanilla JS Integration

SuperDoc can be used with plain JavaScript without any framework.

Basic HTML Setup

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>SuperDoc Example</title>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/@harbour-enterprises/superdoc/dist/style.css" />
    <script
      src="https://cdn.jsdelivr.net/npm/@harbour-enterprises/superdoc/dist/superdoc.es.js"
      type="module"></script>
    <style>
      #superdoc-container {
        width: 100%;
        height: 700px;
        border: 1px solid #ccc;
      }
    </style>
  </head>
  <body>
    <div id="superdoc-container"></div>

    <script type="module">
      import { SuperDoc } from 'https://cdn.jsdelivr.net/npm/@harbour-enterprises/superdoc/dist/superdoc.es.js';

      // Initialize SuperDoc when the page loads
      document.addEventListener('DOMContentLoaded', () => {
        const superdoc = new SuperDoc({
          selector: '#superdoc-container',
          documents: [
            {
              id: 'example-doc',
              type: 'docx',
              // Use a file input to get the document data
              // data: document.getElementById('file-input').files[0]
            },
          ],
          user: {
            name: 'John Doe',
            email: 'john@example.com',
          },
        });
      });
    </script>
  </body>
</html>

Loading Files from Input

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>SuperDoc File Upload Example</title>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/@harbour-enterprises/superdoc/dist/style.css" />
    <script
      src="https://cdn.jsdelivr.net/npm/@harbour-enterprises/superdoc/dist/superdoc.es.js"
      type="module"></script>
    <style>
      #superdoc-container {
        width: 100%;
        height: 700px;
        border: 1px solid #ccc;
        margin-top: 20px;
      }
    </style>
  </head>
  <body>
    <div>
      <label for="file-input">Select a DOCX file:</label>
      <input type="file" id="file-input" accept=".docx" />
    </div>

    <div id="superdoc-container"></div>

    <script type="module">
      import { SuperDoc } from 'https://cdn.jsdelivr.net/npm/@harbour-enterprises/superdoc/dist/superdoc.es.js';

      let superdoc = null;

      document.addEventListener('DOMContentLoaded', () => {
        const fileInput = document.getElementById('file-input');

        fileInput.addEventListener('change', (event) => {
          const file = event.target.files[0];
          if (!file) return;

          // Clean up previous instance if it exists
          if (superdoc) {
            superdoc = null;
          }

          // Initialize SuperDoc with the selected file
          superdoc = new SuperDoc({
            selector: '#superdoc-container',
            documents: [
              {
                id: 'uploaded-doc',
                type: 'docx',
                data: file,
              },
            ],
            user: {
              name: 'John Doe',
              email: 'john@example.com',
            },
          });
        });
      });
    </script>
  </body>
</html>

Setting Up Collaborative Editing

SuperDoc supports real-time collaborative editing using Yjs. Here's how to set it up:

Client-Side Setup

javascript
const superdoc = new SuperDoc({
  selector: '#superdoc-container',
  documents: [
    {
      id: 'collaborative-doc', // This ID is used as the collaboration room name
      type: 'docx',
    },
  ],
  modules: {
    collaboration: {
      url: 'wss://your-collaboration-server.com',
      token: 'user-auth-token',
      // Optional: WebSocket connection parameters
      params: {
        docId: 'collaborative-doc',
        userId: 'user-123',
      },
    },
  },
  user: {
    name: 'Jane Doe',
    email: 'jane@example.com',
    image: 'https://example.com/jane.jpg', // Optional avatar URL
  },
});

// Listen for collaboration events
superdoc.on('awarenessUpdate', ({ users }) => {
  console.log('Currently active users:', users);
});

Server Setup with Hocuspocus

SuperDoc works well with Hocuspocus as a collaboration backend:

javascript
// server.js
import { Server } from '@hocuspocus/server';
import { Logger } from '@hocuspocus/extension-logger';
import { Database } from '@hocuspocus/extension-database';

const server = Server.configure({
  port: 1234,
  extensions: [
    new Logger(),
    new Database({
      // Database configuration for document persistence
    }),
  ],
  onAuthenticate: async ({ token }) => {
    // Validate user token
    // Return user data or throw an error if validation fails
    return {
      user: {
        id: 'user-123',
        name: 'Jane Doe',
      },
    };
  },
});

server.listen();

Next Steps

  • See Components for detailed component reference
  • Check out Resources for examples, FAQ, and community resources
  • Learn more about Getting Started for basic concepts and setup

© 2025 Harbour Enterprises, Inc. 💙💛