# Desktop Django Starter > Minimal reference starter for packaging a Django app inside Electron with a runnable development slice today, a staged packaged-backend slice for bundled-runtime validation, a sign/notarization-aware GitHub packaging slice for desktop artifacts, a minimal Electron connected updater path, plus experimental Tauri and Positron shells for local comparison work. This repository is designed for both human readers and coding agents. Use this documentation when you need the smallest credible architecture for running Django as a local desktop app, or when you need a reusable workflow for wrapping an existing Django project in Electron without importing a product-sized codebase. Important constraints: - Keep the example generic, minimal, and server-rendered. The current themed presentation layer ("Flying Stable") is a demo; the underlying architecture is what matters. - Treat `djdesk` as reference material for packaging and lifecycle patterns only. - Windows support matters. Electron remains the baseline release lane; Tauri now has a GitHub-hosted Tauri artifact workflow plus a prepared, unverified Windows NSIS path, but it still does not claim release parity. Its Tauri-served shell assets use only a minimal localhost-aware CSP for the local splash/bootstrap surface, not a release-grade hardening claim for the Django UI. The hosted NSIS path still needs a real live Windows install/run test before making a stronger claim, and the current config keeps Tauri's default `downloadBootstrapper` WebView2 installer behavior rather than an offline-ready embedded runtime. - Electron and Tauri currently bind Django to `127.0.0.1` on a random port, while Positron serves the same Django app from an in-process WSGI server on a random localhost port. Electron uses a per-session shell-to-Django auth token by passing `DESKTOP_DJANGO_AUTH_TOKEN` to Django and injecting `X-Desktop-Django-Token` only for the exact local Django origin. Tauri and Positron pass the same setting to Django and open their web views through a bootstrap URL that validates the token, sets an HttpOnly same-origin cookie, and redirects to the app without the token. The token does not replace CSRF and is not exposed through preload, a shell bridge, or normal page JavaScript. - Packaged Django keeps SQLite under per-user app data as `app.sqlite3` and now teaches a stronger desktop baseline with `transaction_mode=IMMEDIATE`, a 20-second timeout, WAL, `synchronous=NORMAL`, and modest cache/mmap pragmas. - The packaged shells now seed a small Flying Stable pony roster only when the per-user `app.sqlite3` does not exist yet; clearing the stable later must leave it empty rather than re-seeding. - Electron on Windows currently shuts down backend child processes with explicit forced process-tree termination via `taskkill /t /f`, not a graceful drain or broader production orphan-control approach. - The update story must include air-gapped/manual installs, not only connected environments. Electron has an implemented minimal connected updater path through `electron-updater`, and the repo now records a real signed/notarized macOS packaged update dry run from installed `0.1.2` to published `v0.1.4` that proved detection, download, restart/install, and `app.sqlite3` persistence. It is still not a release-validated updater lane because a real Windows NSIS packaged update dry run is still missing. Tauri now has an experimental connected updater path through `tauri-plugin-updater`, and Positron is manual-only for updates in this repo, with no connected updater or hosted artifact lane. - Electron lives under `shells/electron/`, the experimental Tauri port lives under `shells/tauri/`, and the experimental Positron port lives under `shells/positron/`, while shared icon source art lives under `assets/brand/`; regenerate the Electron PNG and macOS ICNS with `npm --prefix shells/electron run icons`, the Tauri icon set with `npm --prefix shells/tauri run icons`, and the Positron icons with `just positron-icons`. ## Docs - [Documentation index](index.html): Starting point for the published docs. - [Specification](specification.html): Main product and technical specification for the starter. - [Architecture](architecture.html): Runtime contract, repo shape, startup model, shutdown notes, and release/update direction. - [Decisions](decisions.html): Scope and tradeoff decisions captured locally for this repo. - [Release](release.html): Packaging secrets, Electron and Tauri artifact workflows, installer artifacts, Electron updater metadata, Tauri updater payloads, checksum files, and connected/offline promotion guidance. - [Backlog](backlog.html): Explicit follow-on work structured for implementation handoff. - [Done](done.html): Completed backlog entries after they are implemented. - [Agent use](agent-use.html): Guidance for coding agents consuming this repo. - [Electron shell](shells/electron.html): Baseline shell scope and responsibilities. - [Tauri shell](shells/tauri.html): Experimental Tauri shell scope, commands, and support boundaries. - [Positron shell](shells/positron.html): Experimental Positron shell scope, commands, and support boundaries. - [Design guide](design-guide.html): Presentation-layer design decisions for the current Flying Stable demo. ## Wrapping - `scripts/wrap`: Front-door command for wrapping a target Django project. Run from inside the target repo; requires an existing checkout of this starter. Runs preflight checks by default; `--run` invokes the agent. - Packaged CLI: `uvx desktop-django-starter init` saves a user-level default harness and optional model under `~/.config/dds/config.toml` on Unix-like systems. `uvx desktop-django-starter wrap --run` then resolves the harness in this order: explicit CLI flags, saved config, then auto-detect when exactly one supported harness is installed. If no config exists yet and stdin is a TTY, `wrap --run` launches the same setup flow inline; non-interactive runs fail clearly instead of prompting. Current `dds` builds stream concise Claude progress when you choose the `claude` harness. Use `--harness` and `--model` to override the saved defaults, for example `--harness pi --model openai-codex/gpt-5.4`; `--agent` remains available as a backward-compatible alias. - `skills/wrap-existing-django-in-electron/SKILL.md`: Reusable workflow for adapting an existing Django project to run inside an Electron shell. - `skills/wrap-existing-django-in-electron/prompt.md`: Prompt template for unattended agent-driven wrapping. - `skills/wrap-existing-django-in-electron/run-log.md`: Run results from agent wrapping iterations, with git refs to the skill and prompt version used. ## Optional - `.github/workflows/ci.yml`: Current cross-platform CI scaffold using GitHub-hosted runners. - `.github/workflows/desktop-packages.yml`: On-demand GitHub Actions packaging workflow for macOS, Windows, and Linux artifacts, Electron updater metadata, checksum manifests, optional signing inputs, and optional draft GitHub Release publication. - `.github/workflows/tauri-packages.yml`: Experimental GitHub-hosted Tauri packaging workflow using `tauri-action` in build-only mode with installer artifacts, updater payloads, `.sig` files, and checksum manifests. - `tests/test_docs.py`: Minimal smoke tests for the documentation scaffold. - `tests/test_example_app.py`: Backend behavior checks for the demo CRUD slice ("My Ponies"). - `tests/test_tasks_demo.py`: Backend tests for the real async task demo ("Stable Routines"), including enqueueing, reconciliation, and status transitions. - `tests/test_health.py`: Readiness endpoint coverage. - `src/tasks_demo/`: Background task visualization demo ("Stable Routines") with animated pulse-ring indicators, polling-based live updates, and a SQLite-backed `django_tasks` plus `django_tasks_db` worker flow (optional post-v1 extension).