The 1.0 foundation ships today.
Explore the Rust VDOM, Django-template compatibility, streaming primitives, and recovery work hardened into djust 1.0 — a stable foundation for real-time Django applications.
What are you trying to build?
Start with the problem you need to solve, then jump into the implementation detail when you’re ready.
Keep updates small
Use Rust diffing and automatic query planning when full-page work starts to hurt.
Keep your templates
Add reactivity without replacing Django templates, forms, URLs, or domain logic.
Ship with guardrails
Keep security defaults, client escape hatches, and a deployment path in the same stack.
Make the page feel live
Stream work, show presence, and push server-side changes into connected browsers.
01. Rust VDOM Engine
Traditional Django templates re-render the entire string for every request. djust compiles templates into a Virtual DOM tree in Rust.
- Sub-millisecond PatchingRust handles the hot path: dependency-aware rendering, VDOM diffing, and compact patches for changed nodes.
- Smart DiffingWe track variable dependencies. If you only change
{{ count }}, we only check that node.
Rendering Performance (100 items)
{% extends "base.html" %} {% block title %}Dashboard{% endblock %} {% block content %} <div class="stats"> <h1>Welcome, {{ user.name }}</h1> <!-- This updates independently --> <div>Active Users: {{ active_count }}</div> <!-- Loop updates are optimized --> {% for item in items %} <div>{{ item.name }}</div> {% endfor %} </div> {% endblock %}
02. Unified Templates
Don't learn a new syntax. djust supports standard Django template inheritance.
The entire page—base template, child template, and included components—is compiled into a single VDOM tree. This means you can update a variable in the navbar (defined in `base.html`) from a view rendering `child.html`.
How it works:
- Parser resolves
{% extends %}and merges blocks. - Merged template is compiled to Rust VDOM.
- State changes trigger a diff of the entire tree.
- Patches are sent for any changed node, anywhere in the tree.
03. ORM JIT Compiler
The #1 performance killer in Django apps is the N+1 query problem. djust solves it automatically.
Our compiler analyzes your templates to see exactly which fields you use (e.g., {{ book.author.name }}). It then automatically injects the optimal select_related and prefetch_related calls into your QuerySet.
- Zero N+1 QueriesForgot
select_related? No problem. We fix it for you. - Zero Data LeaksIf a field isn't in the HTML, it's never fetched from the DB.
{% for book in books %} {{ book.author.name }} {% endfor %}
{% for book in books %} {{ book.author.name }} {% endfor %}
JOIN authors ON ...
04. Python-First State Management
Complex UI patterns usually require JavaScript. djust provides Python decorators that handle them for you.
Search & Autocomplete
Automatically delays the server request until the user stops typing. No more flooding your database with partial queries.
@debounce(0.5) def search(self, query): self.results = DB.search(query)
Instant Feedback
Updates the UI immediately in the browser, then validates on the server. If the server rejects it, the UI rolls back automatically.
@optimistic def toggle_like(self): self.liked = not self.liked
Component Sync
Synchronize state between multiple components purely on the client-side, without a server roundtrip.
@client_state(['tab']) def set_tab(self, tab): self.tab = tab
05. Security by Default
WebSocket-based frameworks open new attack surfaces. djust locks them down out of the box so you don't have to think about it.
- WebSocket Event HardeningThree-layer defense: event name guard,
@event_handlerallowlist, and server-side rate limiting. - Built-in Security Utilities
safe_setattr()blocks prototype pollution,sanitize_for_log()prevents log injection, DEBUG-aware error handling. - Per-IP Connection LimitsPrevents resource exhaustion from a single client opening hundreds of WebSocket connections.
06. Real-Time Streaming
Stream data to the browser as it generates. Perfect for LLM responses, live logs, and progress indicators — no polling required.
- Token-by-Token OutputStream LLM responses, logs, or any async data directly to the browser as it generates.
- Multiple Stream TargetsUse
stream_to()to push updates to different DOM elements simultaneously.
from djust import LiveView from djust.streaming import StreamingMixin class ChatView(StreamingMixin, LiveView): template_name = 'chat.html' async def ask_ai(self, prompt): self.stream_start('response') async for token in llm.stream(prompt): self.stream_text('response', token) self.stream_done('response')
from djust import LiveView, PresenceMixin class DocView(LiveView, PresenceMixin): presence_key = 'doc:{doc_id}' def mount(self, request, **kwargs): self.doc_id = kwargs['doc_id'] self.track_presence( meta={'name': request.user.username} ) def handle_presence_join(self, presence): self.viewers = self.list_presences() def handle_presence_leave(self, presence): self.viewers = self.list_presences()
07. Live Collaboration & Presence
Build collaborative features without third-party services. Know who's online, track cursors, and broadcast changes — all built in.
- Who's OnlineBuilt-in presence tracking shows connected users in real-time with automatic join/leave detection and heartbeat cleanup.
- Broadcast Updates
broadcast_to_presence(event, payload)pushes to every connected client in the presence group — no pub/sub client required. - Live Cursors
LiveCursorMixinbroadcasts cursor positions for Google Docs-style collaboration.
08. Server Push
Push updates from anywhere in your backend — Celery tasks, management commands, webhooks — directly to the browser without the user lifting a finger.
- Background to BrowserPush state updates from Celery tasks, management commands, or any background process directly to connected clients.
- Async SupportUse
apush_to_view()in async contexts for non-blocking push operations.
from djust import push_to_view # From a Celery task @app.task def process_upload(view_id, file_id): result = heavy_processing(file_id) push_to_view(view_id, { 'progress': 100, 'result': result, })
<div dj-hook="Chart"> <canvas id="myChart"></canvas> </div> <script> djust.hooks.Chart = { mounted() { this.chart = new Chart(this.el, data); }, updated() { this.chart.update(); } }; </script>
09. JavaScript Hooks
When you need client-side power, hooks give you full lifecycle control over DOM elements without leaving the djust ecosystem.
- Full Lifecycle Control
mounted,updated,destroyed,disconnected,reconnectedcallbacks for DOM elements. - Push EventsHooks can push events back to the server and receive events from it via
pushEvent()andhandleEvent().
10. Two-Way Data Binding
Bind form inputs to server state with a single attribute. No JavaScript event handlers, no manual serialization — just dj-model.
- Automatic Sync
dj-modelbinds form inputs to server state. Changes propagate instantly without writing event handlers. - Smart ModifiersUse
.lazyfor on-blur updates or.debounce-300for throttled typing — one attribute, zero boilerplate.
<form> <input dj-model="name" placeholder="Your name"> <textarea dj-model.lazy="bio"> </textarea> <input dj-model.debounce-300="search" placeholder="Search..."> <p>Hello, {{ name }}!</p> </form>
See it, build it, ship it.
Try the live interaction, build your first LiveView, then deploy the same Django app when it’s ready.