Editors comment on blocks of the live (or previewed) page, from the Wagtail userbar. Comments are ordinary Wagtail page comments: they show up in the page editor's comment sidebar, with replies, resolving and @mentions, and editor comments show up on the live page as pins.
- Add a Comment in the userbar: pick a block (top-level or nested) and write.
- Pins sit where you clicked; click one to read, reply, edit, delete or resolve.
@usernameand@[Group name]mention people and groups who can edit the page (highlight-only; nothing is sent).- Each comment links into the page editor at the block's panel.
Only users who can edit the page see any of it. Anonymous and non-editor responses are unchanged.
Python 3.12+, Django 4.2+, Wagtail 7.3+ (the first release whose userbar items carry
their own Media), wagtail-block-ids 0.2+, with Wagtail comments on
(WAGTAILADMIN_COMMENTS_ENABLED, the default).
Neither package is on PyPI yet, so install wagtail-block-ids from its tag alongside the release wheel:
uv add "wagtail-block-ids @ git+https://github.com/lincolnloop/wagtail-block-ids@v0.2.0" \
"wagtail-live-comments @ https://github.com/lincolnloop/wagtail-live-comments/releases/download/v0.1.0/wagtail_live_comments-0.1.0-py3-none-any.whl"INSTALLED_APPS = [
# ...
"wagtail.admin",
"wagtail",
"wagtail_live_comments",
]Then run python manage.py migrate. That's all: the endpoints register under the
Wagtail admin URLs (<admin>/live-comments/), and the userbar item brings its own
script, stylesheet and page config. No template changes.
Your page templates need {% wagtailuserbar %} and must render StreamField blocks with
{% include_block %} (or {{ block }}). A block can be commented on when its template
has a root element: the package adds data-block-id and data-block-type to that
element for editors.
| Setting | Default | Meaning |
|---|---|---|
WAGTAIL_LIVE_COMMENTS_ENABLED |
WAGTAILADMIN_COMMENTS_ENABLED |
Turn the feature off without turning off editor comments. |
WAGTAIL_LIVE_COMMENTS_LABEL_FIELDS |
("text", "title", "headline", "placeholder", "label", "fineprint", "body", "description", "eyebrow") |
Struct child names preferred as the field a comment pins to in the editor. |
- Block ids. For editors, live and preview serves render with
data-block-id/data-block-type/data-block-labelon the first tag of each block, nested stream and list children included. The marking comes from wagtail-block-ids; this package registers a marker for users who can comment and never asks for wrappers, so grid and flex layouts are untouched. - Comments. Creating a comment stores a Wagtail
Commentwhosecontentpathpoints at a field inside the block on the latest draft. No revision is created. The pin point is kept inCommentAnchor, because the page editor rewritesComment.positionon save. - Errors. Endpoints answer
{"ok": false, "error": "auth" | "stale_block" | "validation", "message": "..."}. If the answer isn't JSON (a CSRF failure or an expired admin session), the script reports a session error.
Both packages mark blocks through wagtail-block-ids, so each block is marked once
whatever order the apps are in. Where wagtail-inspect is active (previews, and editors'
live pages unless WAGTAIL_INSPECT_LIVE_PAGES is off), it asks for display:contents
wrappers around blocks with several root elements. A wrapper has no box of its own,
so pins on such blocks can be misplaced.
just install # uv sync --extra testing && bun install
just install-browsers # Playwright Chromium, once
just run # migrate, seed /demo/ and admin/admin, runserver
just test-all # backend, frontend (Bun) and E2E (Playwright)
just tox # backend across Django/Wagtail versions