Before you upgrade, read Removed below.
Security
- Fix 25 CodeQL code-scanning alerts in client.js and debug-panel.js — Added UNSAFE_KEYS guard to VDOM SetAttr/RemoveAttr patches (rejects
__proto__,constructor,prototypekeys), replaced direct property assignment withObject.defineProperty()in debug panel state cloning, converted template literal logs to format strings to prevent log injection, and added XSS suppression comments for trusted server-rendered HTML. (#597)
Removed
whitenoisedependency — djust'sASGIStaticFilesHandlerindjust.asgi.get_application()already handles static file serving at the ASGI layer, making WhiteNoise middleware redundant. Removedwhitenoisefrom dependencies, scaffolded projects, and the demo project. Removed system checkC006(daphne without WhiteNoise). (#584)
Added
{% dj_flash %}template tag in Rust renderer — RegisteredDjFlashTagHandlerso the flash container renders correctly when templates are processed by the Rust engine. Previously, the tag was only registered as a Django template tag and silently dropped by the Rust renderer. (#590)See
docs/website/guides/flash-messages.md.Navigation lifecycle events and CSS class —
djust:navigate-start/djust:navigate-endCustomEvents and.djust-navigatingCSS class on[dj-root]duringdj-navigatetransitions. Enables CSS-only page transitions without monkey-patchingpageLoading. (#585)See
docs/website/core-concepts/events.md.manage.py djust_doctordiagnostic command -- checks Rust extension, Python/Django versions, Channels, Redis, templates, static files, routing, and ASGI server in one command. Supports--json,--quiet,--check NAME, and--verboseflags.Enhanced VDOM patch error messages -- patch failures now include patch type,
dj-id, parent element info, and suggested causes (third-party DOM modification,{% if %}block changes). InDEBUG_MODE, a console group with full patch detail is shown. Batch failure summaries include which patch indices failed.See
docs/website/guides/flash-messages.md.DEBUG-mode enriched WebSocket errors --
send_errorincludesdebug_detail(unsanitized message),traceback(last 3 frames), andhint(actionable suggestion) whensettings.DEBUG=True.handle_mountlists available LiveView classes when class lookup fails.See
docs/website/guides/error-overlay.md.Debug panel warning interceptor -- intercepts
console.warncalls matching[LiveView]prefix and surfaces them as a warning badge on the debug button. Configurable auto-open viaLIVEVIEW_CONFIG.debug_auto_open_on_error.See
docs/website/advanced/debug-panel.md.Latency simulator in debug panel -- test loading states and optimistic updates with simulated network delay. Presets (Off/50/100/200/500ms), custom value, jitter control, localStorage persistence, and visual badge on the debug button. Latency is injected on both WebSocket send and receive for full round-trip simulation. Only active when
DEBUG_MODE=true.See
docs/website/advanced/debug-panel.md.Form recovery on reconnect — After WebSocket reconnects, form fields with
dj-changeordj-inputautomatically fire change events to restore server state. Compares DOM values against server-rendered defaults and only fires for fields that differ. Usedj-no-recoverto opt out individual fields. Fields insidedj-auto-recovercontainers are skipped (custom handler takes precedence). Works over both WebSocket and SSE transports.Reconnection backoff with jitter — Exponential backoff with random jitter (AWS full-jitter strategy) prevents thundering herd on server restart. Min delay 500ms, max delay 30s, increased from 5 to 10 max attempts. Attempt count shown in reconnection banner (
dj-reconnecting-bannerCSS class) and exposed viadata-dj-reconnect-attemptattribute and--dj-reconnect-attemptCSS custom property on<body>. Banner and attributes cleared on successful reconnect or intentional disconnect.See
docs/website/guides/reconnection.md.page_title/page_metadynamic document metadata — Updatedocument.titleand<meta>tags from any LiveView handler via property setters (self.page_title = "...",self.page_meta = {"description": "..."}). Uses side-channel WebSocket messages (no VDOM diff needed). Supportsog:andtwitter:meta tags with correctpropertyattribute. Works over both WebSocket and SSE transports.dj-copyenhancements — Selector-based copy (dj-copy="#code-block"copies the element'stextContent), configurable feedback text (dj-copy-feedback="Done!"), CSS class feedback (dj-copy-classadds a custom class for 2s, defaultdj-copied), and optional server event (dj-copy-event="copied"fires after successful copy for analytics). Backward compatible with existing literal copy behavior.dj-auto-recoverattribute for reconnection recovery — After WebSocket reconnects, elements withdj-auto-recover="handler_name"automatically fire a server event with serialized DOM state (form field values anddata-*attributes from the container). Enables the server to restore custom state lost during disconnection. Does not fire on initial page load. Supports multiple independent recovery elements per page.dj-debounce/dj-throttleHTML attributes — Apply debounce or throttle to anydj-*event attribute (dj-click,dj-change,dj-input,dj-keydown,dj-keyup) directly in HTML:<button dj-click="search" dj-debounce="300">. Takes precedence overdata-debounce/data-throttle. Supportsdj-debounce="blur"to defer until element loses focus (Phoenix parity).dj-debounce="0"disables default debounce ondj-input. Each element gets its own independent timer.Connection state CSS classes —
dj-connectedanddj-disconnectedclasses are automatically applied to<body>based on WebSocket/SSE transport state. Enables CSS-driven UI feedback for connection status (e.g., dimming content, showing offline banners). Both classes are removed on intentional disconnect (TurboNav). Phoenix LiveView'sphx-connected/phx-disconnectedequivalent.dj-cloakattribute for FOUC prevention — Elements withdj-cloakare hidden (display: none !important) until the WebSocket/SSE mount response is received, preventing flash of unconnected content. CSS is injected automatically by client.js — no user stylesheet changes needed. Phoenix LiveView'sphx-no-feedbackequivalent.Page loading bar for navigation transitions — NProgress-style thin loading bar at the top of the page during TurboNav and
live_redirectnavigation. Always active by default. Exposed aswindow.djust.pageLoadingwithstart(),finish(), andenabledfor manual control. Disable viawindow.djust.pageLoading.enabled = falseor CSS override.See
docs/website/guides/navigation.md.dj-scroll-into-viewattribute for auto-scroll on render — Elements withdj-scroll-into-vieware automatically scrolled into view after DOM updates (mount, VDOM patch). Supports scroll behavior options:""(smooth/nearest, default),"instant","center","start","end". One-shot per DOM node — uses WeakSet tracking so the same element isn't re-scrolled on every patch, but VDOM-replaced fresh nodes scroll correctly.See
docs/website/core-concepts/events.md.dj-window-*/dj-document-*event scoping — Bind event listeners onwindowordocumentwhile using the declaring element for context extraction (component_id, dj-value-* params). Supportsdj-window-keydown,dj-window-keyup,dj-window-scroll,dj-window-click,dj-window-resize,dj-document-keydown,dj-document-keyup,dj-document-click. Key modifier filtering (e.g.,dj-window-keydown.escape="close_modal") works the same asdj-keydown. Scroll and resize events default to 150ms throttle. Phoenix LiveView'sphx-window-*equivalent, plusdj-document-*as a djust extension.See
docs/website/core-concepts/events.md.dj-click-awayattribute — Fire a server event when the user clicks outside an element:<div dj-click-away="close_dropdown">. Uses capture-phase document listener sostopPropagation()inside the element doesn't prevent detection. Supportsdj-confirmfor confirmation dialogs anddj-value-*params from the declaring element.dj-shortcutattribute for declarative keyboard shortcuts — Bind keyboard shortcuts on any element with modifier key support:<div dj-shortcut="ctrl+k:open_search:prevent, escape:close_modal">. Supportsctrl,alt,shift,metamodifiers, comma-separated multiple bindings, andpreventmodifier to suppress browser defaults. Shortcuts are automatically skipped when the user is typing in form inputs (override withdj-shortcut-in-inputattribute). Event params includekey,code, andshortcut(the matched binding string)._targetparam in form change/input events — When multiple form fields share onedj-changeordj-inputhandler, the_targetparam now includes the triggering element'sname(orid, ornull), letting the server know which field changed. Fordj-submit, includes the submitter button's name if available. Matches Phoenix LiveView's_targetconvention.See
docs/website/core-concepts/events.md.dj-disable-withattribute for submit buttons — Automatically disable submit buttons during form submission and replace their text with a loading message:<button type="submit" dj-disable-with="Saving...">Save</button>. Prevents double-submit and gives instant visual feedback. Works with bothdj-submitforms anddj-clickbuttons. Original text is restored after server response.dj-lockattribute for concurrent event prevention — Disable an element until its event handler response arrives from the server:<button dj-click="save" dj-lock>Save</button>. Prevents rapid double-clicks from triggering duplicate server events. For non-form elements (e.g.,<div>), applies adjust-lockedCSS class instead of thedisabledproperty. All locked elements are unlocked on server response.See
docs/website/core-concepts/events.md.dj-mountedevent for element lifecycle — Fire a server event when an element withdj-mounted="handler_name"enters the DOM after a VDOM patch:<div dj-mounted="on_chart_ready" dj-value-chart-type="bar">. Does not fire on initial page load (only after subsequent patches). Includesdj-value-*params from the mounted element. Uses a WeakSet to prevent duplicate fires for the same DOM node.See
docs/website/core-concepts/events.md.Priority-aware event queue for broadcast and async updates — Server-initiated broadcasts (
server_push) and async completions (_run_async_work) are now tagged withsource="broadcast"andsource="async"respectively, and the client buffers them during pending user event round-trips (same as tick buffering from #560).server_pushnow acquires the render lock and yields to in-progress user events to prevent version interleaving. Client-side pending event tracking upgraded from single ref toSet-based tracking, supporting multiple concurrent pending events. Buffer flushes only when all pending events resolve.manage.py djust_gen_live— Model-to-LiveView scaffolding generator — Generate a complete CRUD LiveView scaffold from a model name and field definitions:python manage.py djust_gen_live blog Post title:string body:text. Creates views.py (with@event_handlerCRUD operations), urls.py (usinglive_session()routing), HTML template (withdj-*directives), and tests.py. Supports--dry-run,--force,--no-tests,--api(JSON mode) options. Handles all Django field types including FK relationships. Search usesQobjects for OR logic across text fields.See
docs/guides/scaffolding.md.on_mounthooks for cross-cutting mount logic — Module-level hooks that run on every LiveView mount, declared via@on_mountdecorator andon_mountclass attribute. Use cases: authentication checks, telemetry, tenant resolution, feature flags. Hooks run after auth checks, beforemount(). Return a redirect URL string to halt the mount pipeline. Hooks are inherited via MRO (parent-first, deduplicated). Includes V009 system check for validation. Phoenixon_mountv0.17+ parity.See
docs/website/guides/on-mount-hooks.md.put_flash(level, message)andclear_flash()for ephemeral flash notifications — Phoenixput_flashparity. Queue transient messages (info, success, warning, error) from any event handler; they are flushed to the client over WebSocket/SSE after each response. Includes{% dj_flash %}template tag with auto-dismiss and ARIArole="status"/role="alert"support. (#568)See
docs/website/guides/flash-messages.md.handle_paramscalled on initial mount —handle_params(params, uri)is now invoked aftermount()on the initial WebSocket connect, not just on subsequent URL changes. This matches Phoenix LiveView'shandle_params/3contract and eliminates the need to duplicate URL-parsing logic betweenmount()andhandle_params(). Views that don't overridehandle_paramsare unaffected (default is a no-op).See
docs/website/core-concepts/liveview.md.dj-value-*— Static event parameters — Pass static values alongside events withoutdata-*attributes or hidden inputs:<button dj-click="delete" dj-value-id:int="{{ item.id }}" dj-value-type="soft">. Supports type-hint suffixes (:int,:float,:bool,:json,:list), kebab-to-snake_case conversion, and prototype pollution prevention. Works with all event types:dj-click,dj-submit,dj-change,dj-input,dj-keydown,dj-keyup,dj-blur,dj-focus,dj-poll. Phoenix LiveView'sphx-value-*equivalent.See
docs/website/core-concepts/events.md.
Fixed
True/False/Noneliterals resolved as empty string in custom tag args —get_value()didn't recognize Python boolean/None literals, so{% tag show_labels=False %}producedshow_labels=(empty string) instead ofshow_labels=False. Now handlesTrue/true,False/false, andNone/noneas literal values. (#602)Flash and page_metadata not delivered over HTTP POST fallback —
put_flash()andpage_title/page_metaside-channel commands were only flushed over WebSocket. HTTP POST responses now drain_pending_flashand_pending_page_metadataand include them as_flashand_page_metadataarrays in the JSON response. (#590)Custom tag args containing lists/objects serialized as
[List]/[Object]—Value::ListandValue::Objectin custom tag arguments were stringified via theDisplaytrait, destroying structured data before it reached Python handlers. Now serialized as JSON viaserde_json. (#589)Django filters not applied in custom tag arguments —
{% tag key=var|length %}rendered the literal string instead of the computed value because arg resolution usedcontext.get()(plain lookup) instead ofget_value()(filter-aware). (#591){% if %}inside HTML tag after{{ variable }}emits<!--dj-if-->comment —is_inside_html_tag()only checked the immediately preceding token, missing tag context when{{ variable }}tokens appeared between the tag opening and{% if %}. Addedis_inside_html_tag_at()that scans all preceding tokens. (#580)Tick/event version mismatch silently drops user input — Server-initiated ticks could collide with user events, causing VDOM version divergence that silently discarded patches. Added server-side
asyncio.Lockto serialize tick and event render operations, priority yielding so ticks skip during user events, client-side tick patch buffering during pending event round-trips, and monotonic event ref tracking for request/response matching. (#560)Focus lost during VDOM patches — When the server pushed VDOM patches (e.g., updating a counter while the user was typing), the focused input/textarea lost focus, cursor position, selection range, and scroll position. Added
saveFocusState()/restoreFocusState()around theapplyPatches()cycle to capture and restoreactiveElement,selectionStart/selectionEnd, andscrollTop/scrollLeft. Element matching uses id → name → dj-id → positional index. Broadcast (remote) updates correctly skip focus restoration.VDOM patching fails when
{% if %}blocks add/remove DOM elements — Comment node placeholders (<!--dj-if-->) emitted by the Rust template engine were excluded from client-side child index resolution (getSignificantChildrenandgetNodeByPath), causing path traversal errors and silent patch failures. Also added#commenthandling tocreateNodeFromVNodeso comment placeholders can be correctly created duringInsertChildpatches. (#559)