In Development Release Notes
The development release notes are generated by AI and may contain errors.
Version 2026.11
Section titled “Version 2026.11”This release upgrades htmx to version 4, makes Pegasus’s custom middleware async-capable, fixes a Vite config warning, and upgrades Python and JavaScript dependencies.
htmx 4
Section titled “htmx 4”Pegasus now uses htmx 4. htmx 4 is a major rewrite with a lot of breaking changes, so if you’ve written your own htmx code, read the upgrading notes below before you upgrade.
- Upgraded
htmx.orgto version 4. The websockets extension now ships with htmx, so the separatehtmx-ext-wspackage has been removed. - Updated all of Pegasus’s htmx templates and JavaScript to the htmx 4 syntax. This includes the employee demo, the htmx paginators, the app error banner, and the AI chat and group chat plugins.
- Pegasus keeps the htmx 2 behavior of ignoring 4xx and 5xx responses. htmx 4 swaps error responses into the
page by default; Pegasus’s
htmx.jsturns that off. Individual elements can still opt in to swapping error responses withhx-status(for example,hx-status:422="swap:innerHTML"). - Fixed a bug where the chat UI could get stuck on “Connecting…” if the websocket opened before the page’s JavaScript was ready. htmx 4 initializes sooner than htmx 2 did, which made this more likely.
- Group chat now bundles htmx with the rest of your front end, instead of loading an old version of htmx from a CDN on projects that didn’t otherwise use htmx.
- Removed a redundant CSRF token hook from the htmx object demo. The
hx-headerson<body>already handles this. - Upgraded the Pegasus CLI to version 0.17, which generates apps
for htmx 4. The CLI now stops with an error if you run
startappin a project that still uses htmx 2 (you can skip the check with--force).
Async-capable middleware
Section titled “Async-capable middleware”Pegasus’s custom middleware now supports both sync and async requests natively. Before, Django had to switch between sync and async contexts around each one when serving requests under ASGI.
TeamsMiddlewareis now async-capable. It also now leaves the current team context alone ifprocess_viewnever ran, for example on a 404 where URL resolution fails.HealthCheckMiddleware,UserLocaleMiddleware, andUserTimezoneMiddlewarenow use Django’sMiddlewareMixin, which makes them work with both sync and async requests. Their logic moved intoprocess_request/process_responsehooks.- Added tests for the locale and timezone middleware under async requests, and for the team context on async and unresolved requests.
Other changes
Section titled “Other changes”- Upgraded Python and JavaScript dependencies, including several major version upgrades of front end build tools.
- Narrowed the GitHub social login scope from
usertouser:email. Theuserscope gave your app read/write access to the user’s whole GitHub profile, and login only needs their public profile and email addresses. - Renamed
vite.config.tstovite.config.mts. This fixes a warning in Vite 8.3 about the config using ESM syntax in a file Node would load as CommonJS, which Vite’s upcoming native config loader won’t support.- The config now uses
import.meta.dirnameinstead of__dirname, which isn’t available in ES modules. - The TypeScript
modulesetting intsconfig.jsonis nowes2020(wases6) so that type checking allowsimport.meta.
- The config now uses
- Added
terser-webpack-pluginas an explicit dev dependency on Webpack builds.webpack.config.jsuses it, but it was only installed as a dependency of Webpack, which Webpack 5.108 no longer includes. tsconfig.jsonnow lists the folders TypeScript should check (assets,api-client, and the root config files), instead of listing the folders it should skip.- Ran
npm audit fixto address security advisories in Vite, PostCSS, nanoid, js-yaml, and others. - The GitLab CI front end jobs now use the same Node version as the rest of the project (Node 24, was Node 22).
- Upgraded
mcp-alchemy, which the AI chat’s database tool and the AI coding assistant MCP config use, to a version that works withmcp2.x. - Fixed the
api-clientfolder not being removed from projects built without the API client. - Improved the built-in
resolve-pegasus-conflictsskill based on feedback from real upgrades:- It now catches colliding migrations and unexpected changes to user fields, flags package upgrades that get lost when taking Pegasus’s lock files, and handles a few more edge cases during the merge.
- It now reads the release notes for the versions you’re upgrading across and follows their upgrade guidance.
- The check for unexpected migrations now runs even when the merge has no conflicts.
- The instructions were reorganized to follow the order of the work and trimmed down.
Upgrading
Section titled “Upgrading”htmx 4
Section titled “htmx 4”If you only use the htmx code that ships with Pegasus, you shouldn’t need to do anything. If you’ve generated apps with the Pegasus CLI or written your own htmx code, you’ll need to migrate them. The htmx team’s What’s New in htmx 4 guide covers the full list of changes. Here are the ones most likely to affect a Pegasus project:
- Attribute inheritance is now explicit. In htmx 2, attributes like
hx-targetandhx-swapon a parent element applied to all of its children. In htmx 4 you have to add:inherited(e.g.hx-target:inherited="this") for that to happen. This is the change that’s easiest to miss, because templates that rely on it won’t error. They’ll just target the wrong element. - The
HX-Targetrequest header now includes the tag name, e.g.div#page-contentinstead ofpage-content. Any view that checksrequest.htmx.targetneeds to be updated.HX-Trigger-Name(request.htmx.trigger_name) was removed. - Event names changed to a colon-separated style (e.g.
htmx:afterSwapis nowhtmx:after:swap). Check anyaddEventListenercalls andhx-on/hx-triggerattributes that use htmx events. - Websockets use new attributes and events.
hx-ext="ws"+ws-connectis nowhx-ws:connect,ws-sendis nowhx-ws:send, and the event payloads have a different shape. See the hx-ws extension docs. You can also removehtmx-ext-wsfrom yourpackage.json. - Error responses aren’t swapped. As described above, Pegasus keeps the htmx 2 behavior. If you want htmx 4’s
default instead, remove the
noSwapconfig andhtmx:before:swaplistener fromassets/javascript/htmx.js. - If you have a lot of htmx code and want to migrate gradually, the htmx-2-compat extension restores the htmx 2 event names and implicit inheritance.
Apps generated with the Pegasus CLI
Section titled “Apps generated with the Pegasus CLI”Apps you generated with an older version of the CLI use htmx 2 syntax. If you don’t update them, their links, forms and pagination will swap content into the wrong place. Two changes fix them:
- In each of the app’s templates (
<app>_home.html, and<model>_list.html,<model>_detail.html, and<model>_form.htmlfor each model), change thepage-contentwrapper fromhx-target="#page-content"tohx-target:inherited="#page-content". - In each model’s list view in
views.py, changerequest.htmx.target == "page-content"torequest.htmx.target == "div#page-content".
To find everything that needs changing, run this from your project root:
grep -rnE --exclude-dir=node_modules 'hx-target="#page-content"|htmx\.target == "page-content"' .Apps you generate after upgrading will use the htmx 4 syntax automatically. If you need to generate an app in a
project that hasn’t been upgraded yet, install an older version of the CLI with pip install 'pegasus-cli<0.17'.
Other changes
Section titled “Other changes”-
If you have TypeScript files outside
assets/orapi-client/that you want type checked, add their folders to theincludelist intsconfig.json. -
If your app calls the GitHub API with the user’s login token and needs more than their profile and email, add the scopes you need back to the GitHub entry in
SOCIALACCOUNT_PROVIDERSinsettings.py. -
If you’ve customized
vite.config.ts, move your changes intovite.config.mtsand replace any uses of__dirnamewithimport.meta.dirname. Then delete the oldvite.config.tsfile. -
If you’ve customized any of the middleware listed above, you’ll need to merge your changes into the new structure.
