janalis / collaborate
Live collaboration for Symfony admin forms: shared drafts, presence and cursors over Mercure or the bundled WebSocket server, with EasyAdmin and Drupal bridges.
Requires
- php: ^8.4
- doctrine/dbal: ^4.2
- doctrine/doctrine-bundle: ^2.13 || ^3.0
- doctrine/orm: ^3.3
- psr/clock: ^1.0
- psr/log: ^3.0
- symfony/cache: ^7.4 || ^8.0
- symfony/clock: ^7.4 || ^8.0
- symfony/config: ^7.4 || ^8.0
- symfony/console: ^7.4 || ^8.0
- symfony/dependency-injection: ^7.4 || ^8.0
- symfony/deprecation-contracts: ^3.5
- symfony/event-dispatcher: ^7.4 || ^8.0
- symfony/form: ^7.4 || ^8.0
- symfony/framework-bundle: ^7.4 || ^8.0
- symfony/http-foundation: ^7.4 || ^8.0
- symfony/http-kernel: ^7.4 || ^8.0
- symfony/property-access: ^7.4 || ^8.0
- symfony/rate-limiter: ^7.4 || ^8.0
- symfony/routing: ^7.4 || ^8.0
- symfony/security-bundle: ^7.4 || ^8.0
- symfony/security-csrf: ^7.4 || ^8.0
- symfony/translation-contracts: ^3.5
- symfony/twig-bundle: ^7.4 || ^8.0
Requires (Dev)
- carthage-software/mago: ^1.30
- easycorp/easyadmin-bundle: ^5.0
- gedmo/doctrine-extensions: ^3.13
- infection/infection: ^0.35.8
- minishlink/web-push: ^11.0
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^12.5
- ratchet/pawl: ^0.4.3
- ratchet/rfc6455: ^0.4.1
- react/event-loop: ^1.6
- react/http: ^1.12
- react/socket: ^1.17
- react/stream: ^1.4
- symfony/asset-mapper: ^7.4 || ^8.0
- symfony/browser-kit: ^7.4 || ^8.0
- symfony/css-selector: ^7.4 || ^8.0
- symfony/http-client: ^7.4 || ^8.0
- symfony/mercure: ^0.8 || ^0.9 || ^0.10
- symfony/mercure-bundle: ^0.5 || ^0.6 || ^0.7
- symfony/messenger: ^7.4 || ^8.0
- symfony/monolog-bundle: ^3.10 || ^4.0
- symfony/process: ^7.4 || ^8.0
- symfony/translation: ^7.4 || ^8.0
- symfony/yaml: ^7.4 || ^8.0
Suggests
- ext-ev: An event loop for collaborate:hub:serve beyond about 1000 connections (or ext-event, or ext-uv)
- ext-pcntl: Graceful shutdown of collaborate:hub:serve on SIGTERM (or ext-ev / ext-event)
- easycorp/easyadmin-bundle: Shared drafts on EasyAdmin edit and new forms, and live refresh of saved lists (collaborate.bridge: easyadmin)
- gedmo/doctrine-extensions: Locale-specific draft fields for Gedmo translatable properties
- minishlink/web-push: ^11.0 for web push (notifications.web_push), over Symfony's HTTP client and a PSR-17 implementation such as nyholm/psr7
- ratchet/rfc6455: ^0.4.1, with react/http: the WebSocket hub server
- react/http: ^1.12 with react/socket ^1.17, react/stream ^1.4 and ratchet/rfc6455 ^0.4.1: the WebSocket hub server (collaborate.hub.transport: websocket, bin/console collaborate:hub:serve)
- symfony/asset-mapper: Serves the bundle's JavaScript and reads the pinned CKEditor version
- symfony/http-client: Required by the websocket hub transport (the application publishes over HTTP), and by Mercure's subscriptions API for notifications.web_push.skip_online
- symfony/mercure-bundle: Required by the mercure hub transport (collaborate.hub.transport: mercure, the default), with a Mercure hub
Provides
None
Conflicts
- minishlink/web-push: <11.0
- ratchet/rfc6455: <0.4.1
- react/http: <1.12
- react/socket: <1.17
- symfony/mercure: <0.8
- symfony/mercure-bundle: <0.5
Replaces
None
- dev-main
- v0.5.1
- v0.5.0
- v0.4.1
- v0.4.0
- v0.3.4
- v0.3.3
- v0.3.2
- v0.3.1
- v0.3.0
- v0.2.4
- v0.2.3
- v0.2.2
- v0.2.1
- v0.2.0
- v0.1.2
- v0.1.1
- v0.1.0
- dev-fix/release-notes-unwrap
- dev-screenshots/refresh
- dev-feature/drupalorg-page
- dev-docs/drupalorg-release-notes
- dev-fix/release-publish-checkout
- dev-fix/changelog-unreleased
- dev-fix/drupal-split-known-hosts
- dev-feature/drupal-publishing
- dev-feature/bridges
- dev-fix/report-incompatible-halt
- dev-fix/silent-alone-newcomer-state
- dev-chore/web-push-11
- dev-fix/push-when-unfocused
- dev-fix/push-endpoint-allowlist
- dev-feat/notifications
This package is auto-updated.
Last update: 2026-11-10 18:42:07 UTC
README
collaborate
Live collaboration for Symfony and Drupal admin pages.
Shared form drafts · presence and cursors · saved-view refresh · notifications · over Mercure or WebSockets, no Node service
Documentation · Getting started · Configuration · Rich text · EasyAdmin · Drupal · drupal.org
janalis/collaborate is a Symfony bundle that lets several people work on
the same admin page at once:
- Shared drafts. Editors of the same record share one durable draft. Text, rich text (CKEditor 5's own operations and transformations, undo included), choices and collections stay in sync. Save goes through the form's usual validation and persistence; a conflicting save elsewhere opens a review, and Discard resets the draft for everyone.
- Presence and cursors. The header shows who else is on the page; their pointers, carets, selections and the field each one is in are drawn in their color.
- Saved-view refresh. Lists and detail pages reload when a save elsewhere changes what they show.
- Notifications. A bell on every page, topics each user subscribes to, Messenger delivery, and web push when no page of the application is open.
It runs on PHP and a hub: a Mercure hub
(FrankenPHP's built-in hub works), or the WebSocket server the bundle ships
(bin/console collaborate:hub:serve, on ReactPHP). Draft content lives in
your database (MariaDB, MySQL, PostgreSQL or SQLite); the hub only carries
invalidations and presence, never form content. The bundle is a
framework-level core plus admin bridges: EasyAdmin's, loaded when its
bundle is registered, and a Drupal module (janalis/collaborate_drupal)
for Drupal's administration. Without either, a small form-context service
is all a page needs.
Install
composer require janalis/collaborate
Requirements: PHP 8.4+, Symfony 7.4 or 8, Doctrine ORM 3 on MariaDB,
MySQL 8, PostgreSQL 13+ or SQLite 3.35+, Symfony AssetMapper, and a hub: symfony/mercure-bundle and a
Mercure hub, or the bundled
WebSocket server
(react/http, react/socket, react/stream, ratchet/rfc6455).
See Installation
for the routes, the tables, the purge cron and the hub.
Quick start
// config/routes/collaborate.php return static function (RoutingConfigurator $routes): void { $routes->import('@CollaborateBundle/config/routes.php')->prefix('/admin'); };
# config/packages/collaborate.yaml collaborate: drafts: enabled: true rich_text: block_prefixes: [rich_text] # form types rendered as CKEditor fields
{# in the admin layout #} {{ collaborate_presence() }} {# where the avatars go, e.g. the header #} {{ collaborate_layer() }} {# once, before </body> #}
// the page's script, before anything that wraps window.fetch import '@janalis/collaborate/easyadmin.js';
With EasyAdmin, edit and new pages then share drafts. Rich-text editors get
the Collaborate CKEditor plugin and the draft's configuration from
sessionFor(field); see
Getting started
and Rich text and scripts.
Configuration
Every option lives under the collaborate key, with defaults that work on a
standard admin: who a user is and what they may edit, the hub and its
topics, cursor timing, draft limits, compaction, purge and locks, and the
saved-view refresh. See
Configuration
for the full reference and
Identity and access
for the two services most applications provide.
Contributing
Contributions are welcome: bug reports with the smallest page or form that shows the problem, fixes and tests. Read CONTRIBUTING.md and the contributor guide.
make install # Composer, npm and the test applications' assets make verify # composer validate, mago fmt/lint/analyze, PHPUnit, Vitest
License
MIT.
