Quick Start Guide

From git clone to a running real-time app in under 2 minutes. No JavaScript required.

🎮
Want to see it first? Try the live demo →
start.djust.org is a real, multi-user djust app running in your browser — click reactions, vote in a poll, post to a guestbook, and watch it sync for everyone in real time. No install. The Python behind each interaction is shown right on the page.
Fastest start

Clone the starter

djust-start is a minimal, opinionated djust project — everything wired up so you go from git clone to a running app with a live counter on :8000 in under 2 minutes.

# Clone the starter and step in
git clone https://github.com/djust-org/djust-start.git myapp
cd myapp

# Install dependencies and start the dev server
make install
make dev

The server comes up on http://localhost:8000 with a working live counter — click the buttons and watch it update in real time, no full page reload.

View the djust-start repo Prereqs: Python 3.10+, uv, make.
Ready to ship?

Deploy this app with djust deploy.

Sign in once, run the CLI from your project directory, and get a managed djustlive URL with deploy preflight checks.

From your project rootFirst deploy: sign in once
djust deploy login
djust deploy
djust deploy status

The deploy flow checks production settings, waits for rollout completion, and returns the live URL.

Before deploy
Confirm environment variables and production settings.
During deploy
Deploy doctor catches common configuration risks.
After deploy
Use status to check the rollout and live URL.
Existing Django app

Add djust to an existing app.

Follow the same path step by step when you already have a Django project and want to add real-time interactions without a frontend rewrite.

Prerequisites

Python 3.10+
Check: python --version
Django 4.2+
Or we'll install it for you
Basic Django knowledge
Views, templates, URLs
1

Install djust

Install djust with uv. This keeps the environment reproducible and installs Django and other dependencies.

# Create and activate a virtual environment
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Install djust
uv pip install djust
2

Create a Django Project

Create a new Django project or use an existing one.

# Create new Django project
django-admin startproject myproject
cd myproject

# Create an app
python manage.py startapp counter
3

Configure Django Settings

Add djust and Channels to your INSTALLED_APPS in settings.py

# myproject/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'channels',  # Required for WebSocket
    'djust',     # djust framework
    'counter',   # Your app
]

# Required: point Django at your ASGI application
ASGI_APPLICATION = 'myproject.asgi.application'

# Channel layer (in-memory for development)
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels.layers.InMemoryChannelLayer'
    }
}
4

Setup ASGI Routing

Configure WebSocket routing in asgi.py

# myproject/routing.py
from django.urls import path
from djust.websocket import LiveViewConsumer

websocket_urlpatterns = [
    path('ws/live/', LiveViewConsumer.as_asgi()),
]

# myproject/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import myproject.routing

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(myproject.routing.websocket_urlpatterns)
    ),
})
5

Create Your First LiveView

Create a simple counter with real-time updates in counter/views.py

# counter/views.py

from djust import LiveView
from djust.decorators import event_handler

class CounterView(LiveView):
    template_name = 'counter/counter.html'

    def mount(self, request, **kwargs):
        self.count = 0

    def get_context_data(self, **kwargs):
        return {'count': self.count}

    @event_handler()
    def increment(self, **kwargs):
        self.count += 1

    @event_handler()
    def decrement(self, **kwargs):
        self.count -= 1

    @event_handler()
    def reset(self, **kwargs):
        self.count = 0
6

Create the Template

Create counter/templates/counter/counter.html

<!-- counter/templates/counter/counter.html -->
{% load djust_tags %}
<!DOCTYPE html>
<html>
<head>
    <title>Counter Example</title>
    {% djust_scripts %}
</head>
<body dj-view="{{ dj_view_id }}">
    <div dj-root style="text-align: center; padding: 2rem;">
        <h1>Counter: {{ count }}</h1>
        <button dj-click="decrement">-</button>
        <button dj-click="reset">Reset</button>
        <button dj-click="increment">+</button>
    </div>
</body>
</html>
Note:dj-view on <body> establishes the WebSocket connection. dj-root marks the reactive region that gets patched on updates. Both are required.
7

Configure URLs

Add the URL pattern to myproject/urls.py

# myproject/urls.py

from django.contrib import admin
from django.urls import path
from counter.views import CounterView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', CounterView.as_view(), name='counter'),
]
8

Run the Development Server

Start the server and see your counter in action!

uvicorn myproject.asgi:application --reload
Important: Use uvicorn (or daphne), not manage.py runserver — the standard Django dev server is WSGI-only and does not support WebSockets.
Success!
Open http://localhost:8000 in your browser. Click the buttons and watch the counter update in real-time!

How It Works

1
Initial Load
When you visit the page, Django renders the template with count = 0 and sends full HTML to the browser.
2
WebSocket Connection
The djust client JavaScript establishes a WebSocket connection to the server, creating a live session.
3
User Clicks Button
When you click "increment", the client sends an event to the server: {"event": "increment"}
4
Server Updates State
The server calls self.increment(), updating self.count = 1
5
VDOM Diff (Rust)
djust's Rust engine re-renders the template and compares it to the previous version, generating minimal patches in <100μs.
6
Client Updates DOM
The client receives patches like [{path: [2,0], text: "1"}] and updates only the counter number. No full page reload!

Directive Quick Reference

Browse all directives

Now that your first view works, here's the dj-* vocabulary you'll reach for next.

Event attributes
dj-click      dj-submit
dj-change     dj-input
dj-blur       dj-focus
dj-keydown    dj-keyup
dj-poll       dj-copy
dj-confirm    dj-model
dj-mounted    dj-shortcut
dj-click-away
Navigation
dj-patch      # swap dj-root
dj-navigate   # SPA nav + history
dj-prefetch   # warm cache on hover
Window & document scoping
dj-window-keydown
dj-window-scroll   # 150ms throttle
dj-window-resize   # 150ms throttle
dj-window-click
dj-document-keydown
dj-document-click
Rate limiting
dj-debounce="300"  # ms
dj-debounce="blur" # until blur
dj-throttle="500"  # ms
Loading states
dj-loading          # toggle class
dj-loading.hide     # hide
dj-loading.show     # spinner
dj-loading.disable  # disable
dj-disable-with="…"
dj-lock
UI feedback & connection
dj-cloak            # hide til live
dj-scroll-into-view
.dj-connected       # body class
.dj-disconnected    # body class

Need Help?

Stuck on something? Check out the full documentation or browse working examples.