This is a pre-release. djust 1.0.0 has shipped since: read the djust 1.0.0 release notes.
Before you upgrade, read the upgrade guide.
v1.0.0 — the stability milestone. After the v0.9.x audit-driven bake, djust 1.0 makes its SemVer commitment: code written against the public API keeps working across every 1.x release. 1.0 is a consolidation release — there are no breaking changes from 0.9.7; an app that runs on 0.9.7 runs on 1.0 unchanged. The milestone shipped in six units: the Rust template-engine is / is not fix, the published API-stability + deprecation policy, a pre-1.0 dependency security sweep, framework-wide accessibility (the new Y system-check category plus built-in component ARIA), an ADR reconciliation pass, and this 1.0 documentation pass.
Added
- API-stability + deprecation policy published —
docs/API_STABILITY.md(v1.0.0 milestone, unit 2). The canonical, authoritative statement of djust's 1.0 SemVer commitment. Defines the public API surface SemVer covers (top-leveldjustexports, thedjust.decoratorsdecorators, publicLiveView/LiveComponent/Componentmethods, the mixins re-exported from the top-level package, registered template tags/filters, documented config keys, and the snapshot-pinned WebSocket wire protocol) and what is explicitly not covered (underscore-prefixed names,djust.mixins.*internal-composition mixins, Rust crate internals, debug/dev-server/hot-reload internals). Documents the deprecation process —DeprecationWarningannouncement,.. deprecated::docstring marker,### DeprecatedCHANGELOG entry, mandatory migration path — and the support window: a symbol deprecated in1.Yis removed no earlier than2.0.0, with a>= 1.1.0removal floor for the three pre-1.0 legacy symbols (@event,LiveViewForm, the_legacytheming module). A user-facing companion guide ships atdocs/website/guides/api-stability.md, linked from the docs-site nav. This is unit 2 of the 6-unit v1.0.0 (Release Readiness) milestone — the policy is foundational and gates what the 1.0 docs pass documents. - Internal
warn_deprecateddeprecation helper —djust._deprecation(v1.0.0 milestone, unit 2). A single, standardized way djust emits a runtimeDeprecationWarning.warn_deprecated(what, *, since, removed_in, instead=None, stacklevel=2)builds a consistent message naming the deprecated thing, the version it was deprecated in, a concrete earliest-removal version, and the migration path — mechanically enforcing the deprecation policy's "name a concrete removal version" and "name a replacement" rules. The module is underscore-prefixed and therefore framework-internal — it is itself covered by the policy's "underscore-prefixed names are internal" clause and is not a new public API symbol. The three existingDeprecationWarningcall sites (@event,LiveViewForm, the_legacytheming module) now route through it. Yaccessibility system-check category —Y001/Y002(v1.0.0 milestone, unit 4). A new system-check category (mnemonic: a11Y) that regex-scans project template files for the two highest-value, lowest-false-positive accessibility defects. Y001 flags an interactive<button>/<a href>whose visible content is icon-only (an HTML entity,<svg>, or an<i>/<span>icon wrapper) and which has noaria-label/aria-labelledby/title— a screen-reader user hears nothing for such a control. Y002 flags an<img>tag with noaltattribute (WCAG 1.1.1, Level A);alt=""(decorative image) is correct and not flagged. Both emit aDjustWarning(never an error, so a stray false positive cannot failmanage.py check) with the file path and line number, and both are suppressible viaDJUST_CONFIG['suppress_checks'](or Django'sSILENCED_SYSTEM_CHECKS). Templates that show literal HTML inside{% verbatim %}blocks are skipped. The category is the foundation — the scan plumbing exists, so addingY003+ (heading order, form-label association,langattribute) later is a single-function-body change. Implemented as acheck_accessibilityfunction inpython/djust/checks.py; covered bypython/djust/tests/test_accessibility_checks.py.- Framework-wide component ARIA support — built-in roles, states, and accessible names for the interactive component library (v1.0.0 milestone, unit 4). Eight interactive and feedback components now emit the ARIA markup a keyboard or screen-reader user needs, making them correct to assistive technology out of the box.
modalgetsrole="dialog"+aria-modal="true",aria-labelledbyto the title, andaria-label="Close"on the close button.tabsgetsrole="tablist"/role="tab"/role="tabpanel"witharia-selectedandaria-controls/aria-labelledbypairing.accordiongetsaria-expanded/aria-controlson triggers androle="region"/aria-labelledbyon panels.dropdowngetsaria-haspopup="menu",aria-expanded,aria-controls, androle="menu".alertgetsrole="alert"(error/warning) orrole="status"(info/success) andaria-label="Dismiss".paginationgetsaria-label="Pagination"on the nav,aria-current="page"on the active page, andaria-labels on page/arrow buttons.data_tablegets keyboard-focusable (tabindex="0") sortable column headers.toastgetsrole/aria-live(assertive for errors, polite otherwise) andaria-label="Dismiss". Decorative glyphs and icons are markedaria-hidden="true". All changes are add-only ARIA attributes — no class was renamed and no element added, removed, or reparented, so downstream CSS/JS selectors are unaffected (the one structural addition is a benign<span class="data-table-sort-glyph" aria-hidden="true">wrapper around the data_table sort glyph; downstream CSS targets the<th>, which is unchanged). ARIA pairingids are derived deterministically from existing kwargs, keeping VDOMdj-idstable. New guide atdocs/website/guides/accessibility.md; component-markup guarantees covered bypython/djust/components/tests/test_component_aria.py.
Fixed
- Stale and vague deprecation-warning messages corrected (#1483-adjacent, v1.0.0 milestone, unit 2). The
LiveViewFormdeprecation warning said the class would be "removed in djust 0.4" — a version long past (djust is at 0.9.7) — making the message actively misleading. It now names the policy-compliant>= 1.1.0removal floor. The@eventdecorator and the_legacytheming module previously named no concrete removal version ("a future release" / no version at all); both now name the>= 1.1.0floor. Additionally, all three deprecation warnings now point at the caller's frame rather than djust's own internal frame — thestacklevelvalues were corrected for the newwarn_deprecatedwrapper depth (including the metaclass-chain frames Django'sDeclarativeFieldsMetaclassadds for theLiveViewForm.__init_subclass__path), sopython -Wand pytest report the warning at the application code that triggered it. - Rust template renderer now supports Django's
is/is notidentity operators in{% if %}conditions (#1483).{% if x is None %}and{% if x is not None %}previously fell through every operator branch inevaluate_conditionto the defaultOk(false), so they silently evaluated false for all values — templates using this Django-standard syntax always took the{% else %}branch even when the condition was true. The renderer now implementsis/is notwith Python identity semantics: identity holds only for the singletonsNone,True, andFalse; arbitrary equal values (5 is 5,"a" is "a") are NOT treated as identical (CPython interning is an implementation detail templates must not rely on). Templates that previously fell through to the{% else %}branch — e.g.{% if some_value is not None %}for a non-Nonevalue — will now correctly take the{% if %}branch. This brings the Rust template engine to parity with the Django (Python) engine, which has supportedis/is notnatively since Django 4.0. Regression coverage inTestIsIdentityOperators(python/tests/test_template_conditions.py) plus Rust unit tests incrates/djust_templates/src/renderer.rs.
Security
- Pre-1.0 dependency security sweep (v1.0.0 milestone, unit 3). Refreshed
uv.lockto patched versions resolving all 8 open Dependabot advisories: Django 5.2.14 (1 medium + 2 low), urllib3 2.7.0 (2 high), ujson 5.12.1 (1 high), python-multipart 0.0.29 (1 high), and Twisted 26.4.0 (1 high). All 5 high-severity advisories are closed. The change is lockfile-only — no runtime API,pyproject.toml, or source change — and the full test suite (including the WebSocket/Channels paths exercised by the Twisted 25→26 major bump) passes.