Library / SDK
electroluxcode/onlyoffice-web-comp avatar
electroluxcode/onlyoffice-web-comp

onlyoffice-web-comp runs the OnlyOffice editor with no Document Server

A component based on OnlyOffice (v9) for viewing, editing, and converting documents entirely on the user's device, no backend required.基于 OnlyOffice (v9) 的纯前端组件,封装文档查看、编辑、转换功能,全在用户设备本地运行,无需后端,即插即用

537 stars76 forksTypeScriptAGPL-3.0

At a glance

What is it?
onlyoffice-web-comp wraps the OnlyOffice static SDK so a browser can view, edit and convert Word, Excel and PowerPoint files entirely on the client. The interesting part is that it is not packaged as an npm dependency: you copy the component directory and the SDK assets into your own application and drive an OnlyOfficeManager instance yourself.
Who is it for?
Adopt onlyoffice-web-comp if you need document editing in the browser and cannot run an OnlyOffice Document Server, since the whole runtime is static assets and the files never leave the client. Skip it if you want a published package you can add to package.json, because the project explicitly is not one yet, and if your application needs collaborative editing, which is the server's job.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 85 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The editor without the server

The project is a browser-based document solution built on the OnlyOffice static SDK. You can view, edit and convert Word, Excel and PowerPoint documents entirely on the client, with no Document Server required.

That last clause is the whole idea, and it changes the deployment story completely. The conventional OnlyOffice arrangement is a server: your application talks to a Document Server over its API, the Document Server holds the file, and the browser talks to the Document Server to render the editing surface. That is the only way to get collaborative editing, and it is a substantial piece of infrastructure to run.

The static SDK is the other half of OnlyOffice's distribution. It carries the editor itself as JavaScript that runs in the browser, and the conversion engine, x2t, as WebAssembly. With those assets hosted somewhere, the browser can open a file, render it for editing, and convert it, with no server in the middle.

The consequence for the user is that the document stays in the browser. The core advantages section says local processing, documents stay in the browser, and no backend, you host static SDK assets only. For an application where the document is the user's own and the server has no business seeing it, that is the entire appeal.

The trade is collaborative editing and anything server-shaped, because the server was what provided those. The project does not pretend otherwise, and the position it takes is stated plainly: this is not an npm package with a one-line install flow yet, it is a browser-only OnlyOffice integration template.

The repository has two parts, and the table at the top says so. The component library is at src/components/onlyoffice-web-comp/ and holds the reusable web editor wrapper plus Markdown docs. The demo site is at src/app/ and src/features/ and is a Next.js landing page, documentation and live demos.

The demo site is described as intentionally part of the repository, so you can copy a working integration instead of reconstructing the editor lifecycle from scattered snippets. That is a good reason for a template project to carry a demo, and it is the reason to read the demo code rather than the API docs.

The project is TypeScript, AGPL-3.0 licensed, with the default branch main, the last push on 2026-07-30 and no GitHub releases. There is a live demo hosted at onlyoffice-web-comp.vercel.app.

How the integration actually works

The practical integration path is three steps, and it is worth reading because it explains what this project is.

First, copy src/components/onlyoffice-web-comp/ into your application source tree. Second, copy the static assets from public/packages/onlyoffice/ into your app's public/packages/onlyoffice/ directory. Third, build your UI following the demo page at src/features/demo/office-preview-page.tsx.

That third step is the interesting one, because it names the lifecycle explicitly. You create an editor container, keep an OnlyOfficeManager instance, call openDocument, downloadExport and toggleReadOnly, and destroy the manager on unmount.

That is a short list, and each item is a decision the integration has to make. The container is where the editor mounts. The manager is a long-lived object rather than something created per render, which is what lets it hold the editor instance and the event subscriptions. The three methods are the operations you actually need: open a document, export the result back out, and switch the document between editable and read-only. And destroying the manager on unmount is the cleanup step that a wrapper around a third-party editor always needs and that nobody writes in the documentation.

There is a separate path for deeper integration. To call the editor Automation API from the parent page, you get a Developer Edition Connector with createConnector(). The Automation API is the low-level interface the editor exposes for scripting it, and the connector is how you reach it.

The import is a single line:

typescript
import { OnlyOfficeManager, FILE_TYPE, ONLYOFFICE_ID } from "@/components/onlyoffice-web-comp";

The exported names are the manager, a FILE_TYPE constant and an ONLYOFFICE_ID constant, which is presumably the DOM element id the editor is mounted into.

The static resource resolution is centralised in the constant file at src/components/onlyoffice-web-comp/const/index.ts, and the detail there is that both local and CDN modes use the same SDK build by default: the Developer Edition Docker-exported 9.4 SDK at /packages/onlyoffice/9.4.0-develop. The onlyofficeVersion option can override the CDN directory when needed.

Centralising that is what makes the two modes work the same way. If the asset root were resolved in several places, local and CDN mode would drift apart, and the most common bug in this kind of integration is a path that resolves in one mode and 404s in the other.

The demo site and the routes

The demo site is a Next.js application with a small set of routes, and they are laid out to show the two things that matter: one editor and several editors at once.

The routes are a product landing page at /, the component library documentation at /docs rendered from Markdown, a single-instance editor demo at /docs/demos/single and a multi-instance tab demo at /docs/demos/multi.

The legacy routes are handled too: /examples redirects to the single-instance demo and /multi redirects to the multi-instance demo. That is a small thing, but keeping old links alive is the difference between a template that people can bookmark and one they cannot.

The whole thing runs locally with three commands:

bash
git clone <repository-url>
cd onlyoffice-web-comp
pnpm install
pnpm dev
# http://localhost:3001

And the dev script uses port 3001 rather than the Next.js default, with a separate dev:cdn script that serves the public/packages directory on port 3010 with a small Node static server. That second script is a convenience for testing the CDN asset path locally without deploying anything.

The project structure is laid out in the documentation and it is a good map of a Next.js application with a component library in it:

code
onlyoffice-web-comp/
├── src/
│   ├── app/                              # Next.js routes
│   │   ├── page.tsx                      # Landing
│   │   ├── docs/                         # Documentation site
│   │   │   ├── page.tsx                  # /docs (overview md)
│   │   │   ├── [slug]/page.tsx           # /docs/*
│   │   │   └── demos/                    # /docs/demos/single|multi
│   │   └── examples/                     # → redirect to single demo
│   ├── features/
│   │   ├── docs/                         # Docs shell, markdown renderer, site-map
│   │   ├── demo/                         # Live demo components
│   │   ├── marketing/                    # Landing page
│   │   └── shell/                        # Site header / footer / layout
│   └── components/
│       └── onlyoffice-web-comp/          # SDK wrapper + docs/*.md source
├── public/                               # OnlyOffice SDK static assets
└── ...

The app/ directory holds the routes, including the docs routes with a dynamic slug segment and the demos. The features/ directory is where the site-level code lives, split into docs for the documentation shell with its markdown renderer and site map, demo for the live demo components, marketing for the landing page and shell for the header, footer and layout. And components/ holds onlyoffice-web-comp, the SDK wrapper with its docs source.

The split into app, features and components is a Next.js convention that has become a sensible default, and it matters for a template because it tells you where to put your own code. Your application logic goes in features, your routes in app, and the vendored editor wrapper stays in components where you copied it.

The docs pages read Markdown directly from the component's docs directory, and the demo tabs embed live editors from the demo feature directory. So the documentation you read in the browser is the documentation that ships with the component you copied, which is a nice property for a template.

The component library documentation

The documentation organisation is stated with a principle that is worth repeating, because it is the right one for a component that you copy rather than install: API details live in the component library docs, not duplicated here.

The entry point is the component README, and there is an overview document beside it. Then there is a table of documents by topic. A quick start covering initialisation and container mount. A core API document covering OnlyOfficeManager and multi-instance support. An events document for the EventBus. An examples document with React integration patterns. A reference document for constants and types. A notes and formats document covering prerequisites and supported formats. A fonts document on custom font registration. A document on comments and revisions with the Word API. And separate documents for the single-instance demo and the multi-instance demo, each with its source.

Two of those entries are worth expanding on.

The events document is the one that answers the question every wrapper around a third-party editor has to answer, which is how the host application learns what happened inside. An EventBus is the mechanism, and a bus rather than a callback per method is a deliberate choice, because the editor emits many kinds of event and a host that cares about several of them would otherwise need a listener for each.

The fonts document is the one that catches people out. An editor that renders documents in the browser needs the fonts the document uses, and a font that is not present on the machine will not be present in the browser either. Registering custom fonts is therefore part of making a document render correctly rather than a cosmetic extra, and it is the kind of thing that is easy to discover only when a customer sends you a document in a typeface your server has never heard of.

The comments and revisions document, which is tied to the Word API, is the point where the connector approach earns its place. Comment and revision handling is deep editor functionality, and it is the kind of thing you need exactly when you need it and would never want to implement yourself.

The document naming is in Chinese in the source, which is worth noting as a practical detail for anyone reading the repository: the English component README is the entry point, and the other documents are named in the language of the original author.

Hosting the SDK assets separately

The deployment section has two parts, and the second one is the more interesting because it solves a problem most people hit only in production.

The first part is the ordinary one. You run pnpm install and pnpm build, then deploy to Vercel or any static host.

bash
pnpm install
pnpm build

The second part is hosting the SDK assets on a separate CDN, which the documentation describes as OnlyOffice SDK assets can be hosted separately from the app. You deploy the contents of public/packages to Cloudflare Pages, then register the Pages URL before creating an editor.

bash
npx wrangler pages project create onlyoffice-packages

# upload public/packages as the CDN root
npx wrangler pages deploy public/packages \
  --project-name onlyoffice-packages \
  --commit-dirty=true

After deployment, the asset URL should look like a specific shape, ending in the api.js path under the versioned SDK directory.

The reason to separate the two is caching and versioning. The SDK assets are large and they change only when the SDK version changes, while your application code changes on every deploy. Serving the editor from a separate origin means a browser that has already fetched the SDK keeps it, and it means you can roll your application back without rolling the editor back.

It also means the SDK assets can be deployed on a different schedule from the application, which matters when the editor is a large binary asset and you do not want every application deploy to re-upload it.

The registration is done through the same manager API, with a registerStaticResource call taking a cdnOrigin:

typescript
import { OnlyOfficeManager } from "@/components/onlyoffice-web-comp";

OnlyOfficeManager.registerStaticResource({

The manager API is the same in both modes, which is the design goal stated earlier: both local and CDN modes use the same SDK build by default, and the connector support works in both local and cross-origin CDN modes. So switching between hosting the assets with the app and hosting them on a CDN is a configuration change rather than a code change, which is exactly what you want when the first deployment is fine and the second is not.

One caveat is implied by the cross-origin wording. A separate origin is a different origin, and the browser will treat requests to it as cross-origin, so the SDK has to be able to work that way. The documentation says it does, and that it is a supported mode rather than an accident.

The toolchain, and where this fits

The package file is small and shows a project with a conventional modern stack.

Next.js 15.5.7 and React 19.1.0 for the demo application, Tailwind CSS 4 with the PostCSS plugin for styling, and TypeScript 5. The build and dev scripts both pass the turbopack flag, so the Next.js bundler is in use rather than webpack.

The dependencies reveal what the demo site does besides embedding the editor. exceljs for generating spreadsheet files, mammoth for reading Word documents, react-markdown with remark-gfm and rehype-slug for rendering the documentation, github-slugger for generating the same slugs on the server side, lodash-es for utilities, nanoid for identifiers, and ahooks for React hooks.

The testing setup is end-to-end with Playwright, and there is a script that generates the office files the tests use, called test:e2e:files, which runs a Node script at tests/e2e/scripts/generate-office-files.mjs. That is the right approach for this project: generating the fixtures with a library rather than checking binary files into the repository means the test documents are reproducible and the format conversion path is exercised.

The repository also carries a .devcontainer/, a .codesandbox/ directory and an .agents/ directory, which together say that the project is meant to be opened in several different places and that it expects automated agents to work in it.

Now the honest assessment of where this fits.

The project is explicitly a template rather than a package, and it says so. Copy two directories into your application and follow a demo file. That is a different adoption model from installing a dependency, and it has a real cost: you are now maintaining a copy of the wrapper, and when the upstream OnlyOffice SDK changes shape you have to merge the change yourself.

For a project where you need this once, that trade is usually right, because the wrapper is the part you would otherwise have to write from the OnlyOffice documentation, and the demo shows you the correct lifecycle.

The case where it is wrong is when you need collaborative editing, shared documents across users, or anything where the server is the point. That is the Document Server's job and this project does not replace it.

And the licence deserves attention. AGPL-3.0 is a strong copyleft, and copying the component into your application means your application inherits the obligation to publish the source of the combination. For an internal tool that is not a problem. For a proprietary product that embeds a document editor, it is a legal question that has to be answered before you start, and it is worth checking before copying a directory into your tree.

Editorial conclusion

Adopt onlyoffice-web-comp if you need document editing in the browser and cannot run an OnlyOffice Document Server, since the whole runtime is static assets and the files never leave the client. Skip it if you want a published package you can add to package.json, because the project explicitly is not one yet, and if your application needs collaborative editing, which is the server's job. Verify first where you will host the SDK assets, since the local and CDN modes differ in how they are registered, and that the version of the SDK you copy matches the API the component expects.

Frequently asked questions

What does onlyoffice-web-comp do and how is it installed?

It is a browser-based document solution built on the OnlyOffice static SDK, so you can view, edit and convert Word, Excel and PowerPoint files entirely on the client with no Document Server required. It is not an npm package with a one-line install flow, so you copy src/components/onlyoffice-web-comp/ into your source tree, copy the assets from public/packages/onlyoffice/ into your app's public directory, and then follow the demo page to create a container, keep an OnlyOfficeManager instance, call openDocument, downloadExport and toggleReadOnly, and destroy the manager on unmount.

How do I host the OnlyOffice SDK assets on a CDN?

You deploy the contents of public/packages to Cloudflare Pages, using `npx wrangler pages project create onlyoffice-packages` once and then `npx wrangler pages deploy public/packages --project-name onlyoffice-packages --commit-dirty=true`, and you register the resulting Pages origin as the runtime resource root with `OnlyOfficeManager.registerStaticResource({ cdnOrigin: ... })`. Both local and CDN modes use the same SDK build by default, and the connector support works in both.

What does the OnlyOfficeManager API expose?

The manager holds the editor instance and the event subscriptions for a single editor, with methods for opening a document, exporting the result and toggling read-only mode, and it must be destroyed on unmount. To call the editor Automation API from the parent page you obtain a Developer Edition Connector with createConnector(). The library also exports a FILE_TYPE constant, an ONLYOFFICE_ID constant and an EventBus for editor events.

Official sources

  1. electroluxcode/onlyoffice-web-comp on GitHub
  2. Issues
  3. License: AGPL-3.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/electroluxcode-onlyoffice-web-comp.svg)](https://hysenlabs.com/projects/electroluxcode-onlyoffice-web-comp)

Was this useful?