Cover both paths off the legacy Django store end to end: the lazy seed on
first access, and the migrate endpoint replaying every S3 version. The tests
need no database — the admin JWT short-circuits document authorization, so a
fixture is an S3 object on a random uuid — and read the timeline through
yhub 0.5.0's `Accept: application/json`, which spares python a lib0 decoder.
CI grows a valkey service and starts a collaboration server alongside the
backend test job; the tests skip themselves when nothing answers on the new
COLLABORATION_API_URL setting, so `make test` without the dev stack still
passes.
Writing them turned up three things worth fixing in the server.
Backend reads now seed too. getAccessType short-circuited on the admin token
before reaching the legacy store, so a server-side read of an unmigrated
document answered with an empty one, and a create-ydoc against it would have
written a second lineage beside the content the first user access was about
to seed in.
Seeding no longer decides access; the backend's answer alone does. A legacy
object that cannot be migrated — it does not decode, or it exceeds the size
we load — opens as a new document instead of denying, since no retry can fix
it and refusing would leave the document unopenable by anyone. The cause is
logged once per attempt with the bucket, key and stack, and every later access
logs that it admitted a caller without migrating.
That made the failure classifier dangerous, so it is inverted. It was an
allowlist of retryable errors — eight socket errnos — which left every way S3
can refuse (AccessDenied on a rotated key, NoSuchBucket, a region redirect)
counting as "this object is unusable". Denying, that was survivable; opening
empty, one misscoped credential would fork every document touched during the
window. Now only a failure raised while interpreting bytes we already hold is
permanent, marked at the throw site, and everything else answers a retryable
503. Guessing wrong that way costs a retry; the other way costs the document.
The admin seed is also fenced to the org and to main, like the user path
above it. The legacy store is branchless — {docid}/file is main — and the
bookkeeping is per document, so seeding ?branch=draft would have written
main's content into an orphan room and left the real one permanently empty.
Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
Chat on Matrix • Documentation • Try Docs • Contact us
La Suite Docs: Collaborative Text Editing
Docs, where your notes can become knowledge through live collaboration.
Docs is an open-source collaborative editor that helps teams write, organize, and share knowledge together - in real time.
What is Docs?
Docs is an open-source alternative to tools like Notion or Google Docs, focused on:
- Real-time collaboration
- Clean, structured documents
- Knowledge organization
- Data ownership & self-hosting
Built for public organizations, companies, and open communities.
Why use Docs?
Writing
- Rich-text & Markdown editing
- Slash commands & block system
- Beautiful formatting
- Offline editing
- Optional AI writing helpers (rewrite, summarize, translate, fix typos)
Collaboration
- Live cursors & presence
- Comments & sharing
- Granular access control
Knowledge management
- Subpages & hierarchy
- Searchable content
Presentations
- Simple structure, based on delimiter (
---) - Full screen option
- PDF exports
- Keyboard navigation
- Start presention from a block
- Presentation link
Export/Import
- Import to
.docxand.md - Export to
.docx,.odt,.pdf
AI features
Docs has optional AI features. They're model agnostic and gateway agnostic. You can either run your own or just use your AI provider. The config only requires an API key and a URL.
V1: You select, AI replaces
This version features a simple select and replace workflow. Your selection is the context and the instruction for the model. The AI feedback replaces your selection and is designed is optimized for Docs formatting.
V2: AI toolbar, AI cursor (beta)
This version uses BlockNote AI integration. It features:
- an AI toolbar at selection in which you can prompt, accept, reject and iterate AI feedback
- an AI cursor, which interacts with the document, just as another collaborator in your document
- document context is used on top of the selection
Interoperability
Docs comes with a resource server API and a server to server API which allows for awesome integrations.
A concrete example: Meet's transcriptions
If you're running a Meet instance, with simple config (DJANGO_SERVER_TO_SERVER_API_TOKENS) you can push your meeting transcript to Docs and give access to the user who requested it.
Try Docs
Experience Docs instantly - no installation required.
Self-hosting
Docs supports Kubernetes, Docker Compose, and community-provided methods such as Nix and YunoHost.
Get started with self-hosting: Installation guide
Warning
Some advanced features (for example:
Export as PDF) rely on XL packages from Blocknote. These packages are licensed under GPL and are not MIT-compatibleYou can run Docs without these packages by building with:
PUBLISH_AS_MIT=trueThis builds an image of Docs without non-MIT features.
More details can be found in environment variables
Local Development (for contributors)
Run Docs locally for development and testing.
Warning
This setup is intended for development and testing only. It uses Minio as an S3-compatible storage backend, but any S3-compatible service can be used.
Prerequisites
- Docker
- Docker Compose
- GNU Make
Verify installation:
docker -v
docker compose version
If you encounter permission errors, you may need to use
sudo, or add your user to thedockergroup.
Bootstrap the project
The easiest way to start is using GNU Make:
make bootstrap FLUSH_ARGS='--no-input'
This builds the app-dev and frontend-dev containers, installs dependencies, runs database migrations, and compiles translations.
It is recommended to run this command after pulling new code.
Start services:
make run
Default credentials (development only):
username: impress
password: impress
Frontend development mode
For frontend work, running outside Docker is often more convenient:
make frontend-development-install
make run-frontend-development
Backend only
Starting all services except the frontend container:
make run-backend
Tests & Linting
make frontend-test
make frontend-lint
Backend tests can be run without docker. This is useful to configure PyCharm or VSCode to do it.
Removing docker for testing requires to overwrite some URL and port values that are different in and out of
Docker. env.d/development/common contains all variables, some of them having to be overwritten by those in
env.d/development/common.test.
Demo content
Create a basic demo site:
make demo
More Make targets
To check all available Make rules:
make help
Django admin
Create a superuser:
make superuser
Admin UI: http://localhost:8071/admin
Contributing
This project is community-driven and PRs are welcome.
Roadmap
Curious where Docs is headed?
Explore upcoming features, priorities and long-term direction on our public roadmap.
License 📝
This work is released under the MIT License (see LICENSE).
While Docs is a public-driven initiative, our license choice is an invitation for private sector actors to use, sell and contribute to the project.
Credits ❤️
Stack
Docs is built on top of Django Rest Framework, Next.js, ProseMirror, BlockNote.js, HocusPocus, and Yjs. We thank the contributors of all these projects for their awesome work!
We are proud sponsors of BlockNotejs and Yjs.
Gov ❤️ open source
Docs is the result of a joint initiative led by the French 🇫🇷 (DINUM) Government and German 🇩🇪 government (ZenDiS).
We are always looking for new public partners (we are currently onboarding the Netherlands 🇳🇱), feel free to contact us if you are interested in using or contributing to Docs.





