# Nextcloud Text: collaborative Markdown editing in the browser

> Nextcloud Text is the AGPL-3.0 Nextcloud app that gives the platform a collaborative rich text editor on top of Tiptap and ProseMirror, with files saved as plain Markdown and LaTeX math support. It suits self-hosted teams who want to edit documents with people who are not on Nextcloud, and it is an app in the platform sense, with its own occ commands and release train.

**nextcloud/text** — 📑 Collaborative document editing using Markdown

- Repository: https://github.com/nextcloud/text
- Stars: 665 · Forks: 133
- Language: JavaScript
- License: AGPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/nextcloud-text

## The default text editor since Nextcloud 17

Nextcloud Text is described as collaborative document editing using Markdown, and it is the default text editor since Nextcloud 17. To start editing you open an existing markdown or plaintext file or create a new one, which is the whole onboarding: no import step, no format conversion dialog, no separate document type.

The feature list gives the design intent. Simple focused writing, with no distractions and only the formatting you need. Work together, sharing and collaborating with friends and colleagues no matter if they use Nextcloud or not, which is the point of a web editor over a synced file. Open format, with files saved as Markdown so they can be edited from any other text app. A strong foundation, using Tiptap which is based on ProseMirror. And math support, with formulas written in LaTeX syntax and rendered by KaTeX.

That combination of rich editing and plain Markdown storage is the interesting technical position, and it is where the design effort went. A rich text editor that stores a proprietary document format is normal and problematic, because the file is only readable by that editor. One that stores Markdown can offer a WYSIWYG surface while the file on disk remains text, diffable, greppable and editable elsewhere.

The audience is a self-hosted team whose files live in Nextcloud, including collaborators who have no account at all.

The licence is AGPL-3.0-or-later, stated in the source headers and the COPYING file, and the repository carries a REUSE badge and a REUSE.toml file, which is the metadata standard for licence and copyright attribution across a distributed codebase.

## How the Tiptap and ProseMirror stack shapes the editor

The README credits Tiptap, which is based on ProseMirror, as the foundation, and that choice determines a lot about the editor's character. ProseMirror is a document model with a defined schema of nodes and marks, and a plugin system for behaviour, and Tiptap is a Vue layer on top of it that lets the schema be described in a friendlier way.

The practical consequence is that the editor is a rich text editor with a Markdown storage format rather than a Markdown editor. Formatting is applied to a structured document in the browser, and the document is serialised to Markdown when saved. That is why the file list and the toolbar talk about formatting rather than about markup, and why the maths support sits alongside a visual editor rather than in a separate plugin.

The maths implementation is specific enough to be worth reading. Inline math is wrapped in single dollar signs, and display math is wrapped in double dollar signs on separate lines, and the rendering is powered by KaTeX. The dependency list in package.json confirms the pieces, with the mdit plugin for tex and floating-ui for the positioning of the editing popups.

For a developer extending the app, the dependency list is also a map of the integration surface. The @nextcloud/axios, router, auth, l10n, logger, dialogs, event-bus, files and browser-storage packages are the standard way this app talks to the surrounding platform, and initial-state is how the server passes state to the client at boot. The app does not reinvent any of it, which is the right call and also the reason it only works inside Nextcloud.

## Maths editing has its own rules, including a soft line break

The mathematics section is a good example of a small feature that has sharp edges, and the documentation handles them explicitly.

Inline math is written between single dollar signs, for example $E=mc^2$, and display or block math is written between double dollar signs on their own lines. The documented example is the sum of the first n integers, written as a summation with a fraction.

The edge case is the one worth knowing before you paste a formula. The note says that when typing in the editor, you need to create a soft line break with Shift+Return to add lines within the formula block. In other words, a plain Return inside a block formula will not add a line, it will break out of the formula, because Return is the paragraph key and Shift+Return is the line break key in a rich text editor.

Three other interactions are documented. You can select text and use the maths buttons in the toolbar to convert it into a formula. You can click an existing formula to edit it in a dialog. And you can paste Markdown containing maths formulas and have them rendered automatically, which is the one that matters for anyone migrating documents written in a desktop Markdown editor.

The last one is the reason the storage format decision has a cost. A document with maths in it is still valid Markdown with LaTeX in dollar signs, so it stays readable elsewhere, but a renderer that does not implement the dollar-sign convention will show you the raw LaTeX source.

## Two occ commands that change how the app behaves

The Configuration section documents two global settings, and both are set with the occ command, the standard Nextcloud administrative command line tool.

The first turns off the rich workspaces in the file list. Users can do this themselves in the files app settings, and an administrator can do it globally:

```bash
occ config:app:set text workspace_available --value=0
```

The second makes the app open files read-only by default, and it is described as globally valid and administrator only:

```bash
occ config:app:set text open_read_only_enabled --value=1
```

Both settings exist because the app is opinionated by default, and both are the kind of switch an administrator needs precisely when a shared instance has users who find a rich editing surface in a file list intrusive. The read-only default is the more interesting one, because it is the natural setting for a server where the file list mixes documents of many kinds and only some of them are meant to be edited in the browser.

The plugin store of the platform, not this repository, is where the app is installed and updated, and the occ commands are therefore the administration surface that a Nextcloud operator actually uses.

## Developing the app, and the hot module replacement setup

The development setup is documented in four steps, and it has a prerequisite that catches people out. The app requires the main branch of the Viewer app to be installed and enabled, and you are told to follow that setup first and then continue with this app.

The steps are to clone the app into the apps folder of your Nextcloud, run make in the app folder to install dependencies and build the JavaScript, enable the app through the app management of your Nextcloud, and then help fix issues and review pull requests.

The Makefile shows what make actually does. The default target is dev-setup, lint and build-js-production, and dev-setup is clean, clean-dev and npm-init, where npm-init runs npm ci. The build targets delegate to the npm scripts: build-js-production runs npm run build and build-js runs npm run dev, and there are watch and lint targets as well. The clean target removes the contents of the js directory, and clean-git also resets js and css from git, which tells you those two directories are build output that is committed for distribution.

For a faster loop, the documentation explains how to use vite serve with hot module replacement so you do not recompile the JavaScript assets after each change. The idea is to point your webserver at the vite server, with an nginx location block that proxies to host.docker.internal on port 5173, with a fallback to the Nextcloud server if the vite server does not answer. Then run npm run serve, or with a BASE prefix if the app does not live at /apps/text. After that, code changes apply in the browser automatically.

The npm scripts themselves show the toolchain: vite for the build with a 4 GB old space size cap, vue-tsc and eslint for linting across src, cypress and playwright, and vitest for the unit tests.

## Three test layers, and a Docker requirement for the browser tests

The testing section is unusually detailed for an app README, and it is worth reading because it explains the cost of contributing.

There are three kinds of tests. The backend PHP is tested with Psalm and PHPUnit, with the cases in the tests/ directory, run through the composer scripts psalm and test:unit. The frontend unit tests use jest, with the unittests in src/tests/. And end to end testing uses cypress, with those tests in the cypress/ directory, run through npm run test:cypress.

The cypress layer has a prerequisite that catches contributors out. The tests require a running Nextcloud server, and if no running server is detected a Docker container will be started, which requires the current user to be in the docker group. Alternatively you can set the CYPRESS_baseUrl environment variable to point at a custom Nextcloud server. So the end to end suite is not something you can run in a bare container without Docker socket access.

The repository layout reflects a modernised toolchain. The package.json scripts mention vitest for the unit tests and playwright for something, alongside cypress, and there are both vitest.config.ts and playwright.config.ts files at the root, plus a playwright/ directory with a start-nextcloud-server.mjs script wired to an npm run start:nextcloud script. There is a translation directory l10n/ with an l10nignore file, a Krankerl configuration for translation management, a rector.php file for automated refactoring, a psalm.xml for the static analyser, a .php-cs-fixer.dist.php for PHP formatting, and renovate.json for dependency updates.

The last push was on 2026-10-20, so the app is being worked on actively, and the package version in the manifest is a development version, 10.0.0-dev.0.

## Direct editing, the route the mobile apps take

There is a second entry point into the editor that the documentation explains, and it is the one that matters for anyone building on the platform.

The mobile apps open the text editor through a direct editing session. To reproduce that in a browser, the documentation gives a single curl command that posts to the direct editing endpoint of the files API, with the editor id, a creator id of textdocument, and a path of /test.md, and pipes the result through jq to extract the URL from the response:

```bash
curl --silent --insecure --request POST --url 'https://admin:admin@nextcloud.local/ocs/v2.php/apps/files/api/v1/directEditing/open?editorId=text&creatorId=textdocument&format=json' --header 'Content-Type: multipart/form-data' --header 'OCS-APIRequest: true' --form path=/test.md | jq -r '.ocs.data.url'
```

The returned URL opens the direct editing view and contains a one-time token that expires after being opened once. That expiry is the security model of the feature: a session URL is minted on demand and burned on use, so it can be handed to an app or a device without creating a persistent share.

This is also the integration surface for other apps, since the app documents a LoadEditor event that your code can dispatch if the class exists, which is the pattern for loading the editor inside your own app. The README also explains how to add support for a new mime type, which needs the type to be known to the Nextcloud server first, then a pull request against the mime helper, and then a test in the cypress files spec.

That last point is the clearest statement of the app's scope. Text handles what Nextcloud knows how to open, and extending it requires a server-side change first.

## Conclusion

Nextcloud Text suits a self-hosted Nextcloud team that wants document editing to work in the browser, keeps the file format as Markdown so nothing is trapped in the platform, and is willing to live with the app's own upgrade cycle and its AGPL-3.0 licence. It is the wrong choice for an organisation that does not run Nextcloud at all, for a team whose documents are richer than Markdown can hold, or for anyone who needs a stable platform to build on. Before adopting it, check that the app version you install matches your server version, decide whether the rich workspaces in the file list help or clutter, and try the direct editing flow the mobile apps use, since that path is the one most users of the app will actually hit.

## FAQ

### What is Nextcloud Text and what format do the files use?

It is a Nextcloud app providing collaborative document editing with a rich text interface, and it has been the default text editor since Nextcloud 17. Files are saved as Markdown, so they remain editable in any other text application.

### How do I add math formulas in Nextcloud Text?

Write LaTeX between single dollar signs for inline math and between double dollar signs on separate lines for display math, rendered with KaTeX. Inside a formula block you need a soft line break with Shift+Return rather than Return to add a line.

### How do I disable the rich workspaces in the Nextcloud file list?

Users can turn them off in the files app settings, and an administrator can do it globally with occ config:app:set text workspace_available --value=0. The app can also be made to open files read-only by default with occ config:app:set text open_read_only_enabled --value=1.

### How do I develop Nextcloud Text locally?

The app requires the main branch of the Viewer app to be installed and enabled first. Then clone the text app into the apps folder of your Nextcloud, run make to install dependencies and build the JavaScript, and enable the app through the app management interface.

### What licence is Nextcloud Text released under?

The app is licensed AGPL-3.0-or-later, stated in the source headers, the COPYING file and the REUSE metadata in the repository. The last push was on 2026-10-20 and the repository has no GitHub releases.

## Sources

- [Issues](https://github.com/nextcloud/text/issues)
- [License: AGPL-3.0](https://github.com/nextcloud/text/blob/main/LICENSE)
- [nextcloud/text on GitHub](https://github.com/nextcloud/text)
- [README](https://github.com/nextcloud/text/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nextcloud-text
