Home Features Docs Blog Examples FAQ
Documentation

Progressive Web App (PWA) Support

Add offline support, service workers, and installability with PWAMixin

Progressive Web App (PWA) Support

djust provides built-in PWA support for offline-first applications with automatic synchronization, service worker generation, and offline-aware template directives.

What You Get

  • Service worker integration -- Automatic caching of HTML responses and static assets
  • Offline state management -- IndexedDB/LocalStorage abstraction via mixins
  • Optimistic UI updates -- Immediate feedback with sync when online
  • Offline directives -- dj-offline-hide, dj-offline-show, dj-offline-disable
  • Automatic manifest generation -- PWA manifest with customizable settings

Quick Start

1. Enable PWA in Your Templates

{% load djust_pwa %}
<!DOCTYPE html>
<html>
<head>
    {% djust_pwa_head name="My App" theme_color="#007bff" %}
</head>
<body>
    {% djust_offline_indicator offline_text="You're offline" %}
    {% djust_offline_styles %}

    <div dj-offline-hide>Only shown when online</div>
    <div dj-offline-show>Only shown when offline</div>
    <button dj-offline-disable dj-click="submit">Submit</button>
</body>
</html>

2. Use PWA Mixins in Your Views

from djust import LiveView
from djust.pwa.mixins import PWAMixin, OfflineMixin

class MyView(OfflineMixin, LiveView):
    template_name = 'app.html'

    def mount(self, request):
        self.enable_offline()
        self.items = self.load_offline_state('items', [])

    def add_item(self, name):
        self.items.append(name)
        self.save_offline_state('items', self.items)
        self.sync_when_online()

3. Generate the Service Worker

python manage.py generate_sw

PWA Mixins

PWAMixin

Base mixin for PWA functionality:

Method Description
enable_offline(storage='indexeddb') Enable offline mode with specified storage backend
disable_offline() Disable offline functionality
is_offline_enabled() Check if offline mode is enabled

OfflineMixin

Enhanced offline state management (extends PWAMixin):

Method Description
save_offline_state(key, data) Save data for offline access
load_offline_state(key, default=None) Load saved offline data
sync_when_online() Queue current state for sync when connection returns
handle_online() Called when connection is restored

SyncMixin

Automatic background synchronization (extends OfflineMixin):

Method Description
queue_sync(action, data) Queue an action for background sync
process_sync_queue() Process all queued sync actions

Template Tags

{% djust_pwa_head %}

Complete PWA setup in one tag (manifest + service worker registration):

{% djust_pwa_head name="My App" theme_color="#007bff" %}

{% djust_pwa_manifest %}

Generate the PWA manifest link:

{% djust_pwa_manifest name="My App" short_name="App"
   theme_color="#007bff" background_color="#ffffff" display="standalone" %}

{% djust_sw_register %}

Register the service worker:

{% djust_sw_register sw_url="/sw.js" scope="/" %}

{% djust_offline_indicator %}

Visual offline status banner:

{% djust_offline_indicator offline_text="You're offline" show_when="offline" %}

Offline Directives

Directive Behavior
dj-offline-hide Hide element when offline
dj-offline-show Show element only when offline
dj-offline-disable Disable form element when offline
dj-offline-queued Show visual feedback for queued actions
<div dj-offline-hide>
    <button dj-click="save_to_server">Save</button>
</div>
<div dj-offline-show>
    <p>Changes will sync when you're back online.</p>
</div>

Service Worker Configuration

# settings.py
DJUST_PWA = {
    'MANIFEST': {
        'name': 'My Application',
        'short_name': 'MyApp',
        'theme_color': '#007bff',
        'background_color': '#ffffff',
        'display': 'standalone',
        'icons': [
            {'src': '/static/icons/icon-192.png', 'sizes': '192x192', 'type': 'image/png'}
        ]
    },
    'SERVICE_WORKER': {
        'CACHE_NAME': 'djust-v1',
        'STRATEGY': 'cache-first',  # or 'network-first'
        'URLS_TO_CACHE': ['/static/css/app.css', '/static/js/app.js'],
        'OFFLINE_URL': '/offline/',
        'EXCLUDE_PATTERNS': [r'/admin/', r'/api/websocket/']
    }
}

Example: Offline Todo App

from djust import LiveView
from djust.pwa.mixins import OfflineMixin

class TodoView(OfflineMixin, LiveView):
    template_name = 'todos.html'

    def mount(self, request):
        self.enable_offline()
        self.todos = self.load_offline_state('todos', [])

    def add_todo(self, text):
        todo = {'id': len(self.todos), 'text': text, 'done': False}
        self.todos.append(todo)
        self.save_offline_state('todos', self.todos)
        self.sync_when_online()

    def toggle_todo(self, todo_id):
        for todo in self.todos:
            if todo['id'] == todo_id:
                todo['done'] = not todo['done']
        self.save_offline_state('todos', self.todos)
        self.sync_when_online()

Management Commands

# Basic generation
python manage.py generate_sw

# Custom output path
python manage.py generate_sw --output static/custom-sw.js

# Include static file collection
python manage.py generate_sw --collect-static

# Custom version
python manage.py generate_sw --version 2.1.0

Adding PWA to an Existing App

  1. Add {% load djust_pwa %} to your base template
  2. Include {% djust_pwa_head %} in your <head>
  3. Mix PWAMixin or OfflineMixin into your LiveViews
  4. Run python manage.py generate_sw
  5. Deploy with HTTPS (required for service workers in production)

Browser Support

Browser Support
Chrome / Edge Full
Firefox Full
Safari Partial (no background sync)
Mobile Safari Full with install prompt

Best Practices

  • Service workers require HTTPS in production (localhost is exempt for development).
  • Use network-first strategy for dynamic content and cache-first for static assets.
  • Validate data in the sync queue before sending to the server.
  • Consider authentication token expiry when designing offline flows.
  • Test offline behavior in Chrome DevTools (Application > Service Workers > Offline).