# DeepNotes: an end-to-end encrypted infinite canvas with nested pages

> DeepNotes is an open source note-taking tool built on an infinite canvas with deep page nesting, end-to-end encryption and realtime collaboration, running on Vue, Quasar and Yjs. It is a monorepo app served through Postgres and KeyDB.

**DeepNotesApp/DeepNotes** — End-to-end encrypted visual note-taking tool with deep page navigation. 

- Repository: https://github.com/DeepNotesApp/DeepNotes
- Website: https://deepnotes.app
- Stars: 606 · Forks: 56
- Language: TypeScript
- License: AGPL-3.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/deepnotesapp-deepnotes

## A canvas where pages nest inside pages

DeepNotes is described as an open source, end-to-end encrypted infinite canvas tool with deep page nesting and realtime collaboration. That combination is unusual enough to be the whole design idea rather than a feature list.

Most note tools give you a tree of documents. DeepNotes gives you a canvas you can pan, and inside that canvas a page can contain further pages, so a concept can be explored at whatever depth it needs. The stated benefit is escaping the big wall of text and organising notes in whatever way you want. The navigation model is not a sidebar of documents but spatial and hierarchical at the same time, which is why the homepage describes the tool as a visual note-taking app.

The audience is people whose thinking does not fit in a linear outline: researchers, students, engineers mapping a system, or a team doing whiteboard work that needs to survive a meeting. The repository topics list note-taking, notes, productivity, privacy, encryption, end-to-end-encryption and realtime-collaboration, which is the same set of concerns.

The primary language is TypeScript and the code is a monorepo: apps/ holds the applications, packages/ the shared libraries, with a pnpm-workspace.yaml and a turbo.json driving the build.

## End-to-end encryption and Yjs collaboration are the same mechanism

The two headline features are less separable than they look. Realtime collaboration is handled by Yjs, the shared document and conflict-free data type library, and the stack also includes Tiptap for the rich text editor and Vue with Quasar for the interface. Realtime collaboration with end-to-end encryption means the encrypted document has to be merged across peers, and a CRDT-based model like Yjs is a natural fit for that, since merging happens on the document structure rather than on a server-authoritative stream.

KeyDB and Redis are listed for scalable shared memory and communication, and the docker-compose.yml confirms a keydb service running the eqalpha/keydb:alpine_x86_64_v6.3.3 image with the local keydb.conf mounted as the Redis configuration. That is the transport layer for the collaboration and the shared state the app needs between processes.

The server side is split into several services by the captain-definition files at the repository root: app-server, client, collab-server, realtime-server and scheduler, each with a staging variant alongside it. The naming tells you the split: an application server, a collaboration server, a realtime server and a scheduler, with a client tier on top. The staging definitions exist so the same topology can be stood up against a staging environment, which is what a collaboration product needs to be able to test.

What the documentation does not spell out is the encryption envelope: which keys are derived how, and where the key exchange happens. If the cryptographic design is the deciding factor for your use, that is the gap to probe before committing.

## One command builds the whole stack

The development setup is a single chained command that clones, copies the environment template, installs dependencies, builds the packages and then brings the services up with Docker Compose.

```console
git clone https://github.com/DeepNotesApp/DeepNotes && cd DeepNotes && cp template.env .env && pnpm install && pnpm run repo:build && docker-compose up -d
```

On Windows the documentation says to use WSL or Git Bash for those commands. The presence of template.env in the repository root, and the cp of it to .env, tells you the configuration is environment driven and that the template is the supported starting point.

The compose file is small and gives you the two stateful services the application needs. Postgres 15.3 holds the data, with the credentials and database name set through POSTGRES_USER, POSTGRES_PASSWORD and POSTGRES_DB, port 5432 published, the data directory mounted from ./postgres_data and ./postgres-init.sql mounted into the initdb hook so the schema is created on first start.

```yaml
  postgres:
    image: postgres:15.3
    container_name: postgres
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres_password_here
      POSTGRES_DB: deepnotes
    ports:
      - '5432:5432'
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
      - ./postgres-init.sql:/docker-entrypoint-initdb.d/init.sql
```

The keydb service follows the same pattern with the 6379 port published and keydb.conf mounted. Both services set restart: always, so a crash brings the container back rather than leaving the app without its database.

One thing to notice: the compose file hardcodes a placeholder password, POSTGRES_PASSWORD: postgres_password_here, and publishes both ports to the host. That is fine for a development machine and wrong for anything else, so treat the compose file as a development default rather than a deployment artifact.

## Five frontends from one shared client package

The client is built once and run five ways. The backend servers start with pnpm run dev, and the frontend server is chosen by a separate script for each target: dev:spa for the Single Page Application, dev:ssr for the server side rendered app, dev:electron for the desktop build, dev:android for the Android app and dev:ios for the iOS app. The mobile targets need Android Studio and Xcode respectively, which the documentation notes.

This is the monorepo pattern working as intended. The package.json scripts build the same client for each target with pnpm --filter @deepnotes/client run build:spa, build:ssr, build:electron and build:ios, and turbo runs the pipeline across the workspace. The shared packages such as @deeplib/tsconfig and eslint-config-base are workspace dependencies, so the apps and packages stay in step.

There is one operational constraint that will cost you an hour if you miss it. If you use the SPA or the SSR build, you must reach the app through http://localhost:60379 by default, and other URLs will not work. The host and ports are configurable in the .env file, so the fix is a configuration change rather than a bug hunt. In a browser app where the URL is the routing model and encryption state is tied to the origin, that kind of strictness is a design decision rather than an accident.

For teams, the build and release scripts are conventional: turbo handles build, build:watch and clean, and concurrently plus cross-env are available for running processes together.

## AGPL-3.0 is the licence fact that changes decisions

The licence is AGPL-3.0, and for a self-hosted server application that is the most consequential line in the metadata. The AGPL was written so that users of a modified network service, not just distributors of the code, are covered by the source-sharing obligation. For a team that plans to run DeepNotes internally, modify it, and keep the modified version off the internet, that obligation reaches further than a permissive licence would.

None of this is legal advice, and the details depend on how you distribute and how you offer the service, but the practical point is narrow: if you fork it for internal use and hand it to people outside your organisation, read the AGPL text carefully before you do. For personal use, evaluation and unmodified deployment, the licence creates no obstacle.

The other cost of this project is maturity. The last push was on 2026-06-02, and the recent releases are v1.0.25 from 2024-02-02, v1.0.24 from 2023-12-28 and v1.0.23 from 2023-12-26. So the tagged releases are more than two years old while the default branch, dev, has seen commits as recently as June 2026. That is a real signal about which code you should evaluate: the dev branch is where the work is, and the tags are not where it is.

The default branch being dev also matters for contribution. Any pull request goes against a moving target, and the tooling reflects a serious project setup, with husky, commitlint, standard-version, syncpack and a vitest configuration in place.

## Comparing the canvas model with a plain text editor

The alternative is a markdown or plain text editor with a folder tree, and the difference is not cosmetic. A text editor stores one document per file, gives you search, and asks you to decide where a note lives before you write it. DeepNotes inverts that: you place something on a canvas, and you nest pages into each other, so the structure is created by writing rather than by filing.

For a linear body of work, a research note with a clear outline, or code documentation, the text editor wins on search, diffing, version control and the sheer number of tools that read plain text. Canvas software is also harder to keep in version control, harder to diff, and harder to move between tools, and the AGPL question only arises in one of the two worlds.

For spatial thinking, the canvas wins, and the two extra capabilities are what make it collaborative rather than merely visual. Realtime collaboration with a group is the feature the topic tags and the collab-server and realtime-server services are built around, and end-to-end encryption keeps the content private while it is shared. That combination is the reason to accept the licence and the operational overhead.

One honest limitation: the README does not describe the encryption scheme, the key management or the export path in any detail, and it does not document a rollback or migration procedure. If you are adopting this for data you cannot afford to lose, the lifeline storage promise in the feature list should be checked against your own backup plan before you rely on it.

## Conclusion

Adopt DeepNotes when you want a visual, infinitely nestable notebook where notes are encrypted on the client and shared live with a team, and skip it when you need a plain text first tool, since the canvas model adds UI weight that a markdown editor does not. Before building on it, run the single clone-and-build command with docker-compose up -d, confirm the app only answers on http://localhost:60379 as the documentation states, and check the licence carefully, since AGPL-3.0 obliges you to publish source for modified network use while the last push was on 2026-06-02.

## FAQ

### How do I run DeepNotes locally?

Clone the repository, copy template.env to .env, install with pnpm, build with pnpm run repo:build and start the services with docker-compose up -d. The documentation notes that on Windows you should use WSL or Git Bash.

### Which URL do I use to open the DeepNotes app during development?

With the SPA or SSR build you must access the app through http://localhost:60379 by default, and other URLs will not work. The host and ports can be changed in the .env file.

### What databases and services does DeepNotes need?

The docker-compose.yml defines a postgres 15.3 service with the database name deepnotes and an init.sql mounted into the initdb hook, plus a keydb service using the eqalpha/keydb:alpine_x86_64_v6.3.3 image with keydb.conf mounted. Both publish their standard ports and set restart: always.

### Which frameworks does DeepNotes use for collaboration and editing?

The project credits Yjs for realtime collaboration, Tiptap for the rich text editor, Vue.js for reactivity and the component system, Quasar as the cross-platform frontend framework, and KeyDB and Redis for shared memory and communication.

### Can I run DeepNotes as a desktop or mobile app?

Yes. The development scripts include dev:spa, dev:ssr, dev:electron, dev:android and dev:ios, with matching build scripts in package.json. The Android target requires Android Studio and the iOS target requires Xcode.

## Sources

- [DeepNotesApp/DeepNotes on GitHub](https://github.com/DeepNotesApp/DeepNotes)
- [License: AGPL-3.0](https://github.com/DeepNotesApp/DeepNotes/blob/dev/LICENSE)
- [Project website](https://deepnotes.app)
- [README](https://github.com/DeepNotesApp/DeepNotes/blob/dev/README.md)
- [Releases](https://github.com/DeepNotesApp/DeepNotes/releases)

---

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