Changelog
Note
Tetra is still early in its development, and we can make no promises about API stability at this stage.
The intention is to stabilise the API prior to a v1.0 release, as well as implementing some additional functionality. After v1.0 we will move to using Semantic Versioning.
[0.9.3] – 2026-03-20
Fixed
- fix smaller errors in forms and form validation, improve error messages
[0.9.2] – 2026-03-18
Added
- Client-side Routing: Implement full client-side routing that informs the server of new routes. (Note: This feature is highly experimental and not meant for production).
- Nested Routes: Improved
Routerto be nestable and delegate routes to sub-routers. - Router Registry: Introduced a global router registry with
reverseandreverse_lazysupport for components. - Allow
BasicComponentto include simple JavaScript (without Alpine/state access). - Pass Tetra endpoint from server config to client instead of using hardcoded URLs.
- Add "ws" hint when debugging navigation in the browser console.
Changed
- Breaking change: Exclude context from saved component state per default to reduce state size and improve security.
- Rename
router_urltorouter_urlsfor consistency. - Remove compiled JavaScript assets from VCS to reduce repository noise.
- Improve error messages when template HTML files are missing or when
StateExceptionis raised.
Fixed
- Fix order of finding HTML templates, CSS, and JS files for components when base classes are involved.
- Handle Django empty patterns returning
/by converting to an empty string in the router. - Fix
ReactiveComponentauto-generatedkeysupport. - Fix template resolution and JS discovery for directory-based components.
- Fix return annotations and various typos/whitespace issues.
- Ensure only the "default" library in Tetra is discovered to avoid conflicts.
- Refactored tests and improved error handling in templates.
[0.9.1] – 2026-02-17
Fixed
- WebSocket connections are now only established when a page actually renders a ReactiveComponent, not just when such classes exist in the codebase.
- When ReactiveModels change, they now only update the instance channel, not the * collection* channel.
[0.9.0] – 2026-02-17
Added
- Introduce
group_registryfor group validation and improve subscription handling - Introduce online status tracking
- Offline Queue System: Automatic queueing and replay of component method calls when network is unavailable.
- Stale Component State Handling: Components now gracefully handle cases where database objects their reference have been deleted/changed by another client.
Changed
- JSON-based internal Calling Endpoint: Component method calls now use a unified JSON-based HTTP endpoint at
/__tetra__/call/instead of the previous component-specific URLs, providing a more consistent API structure. - Pickling/Unpickling now checks variables against a "safe list" of types.
- rename Alpine store
tetra_statustotetraStatus
Removed
- Remove deprecated
@public.subscribedecorator
[0.8.5] – 2026-02-01
Added
- Improve subscription response handling
- Raise ProtocolError for invalid Tetra protocol version
Changed
- Rename
component.data_updatedtocomponent.data_changed
[0.8.4] – 2026-02-01
Fixed
- Fix error where another client could keep a stale component when two components are deleted locally.
- Fix
ReactiveComponentsubscription by template tag attr
Changed
- Rename
component.data_updatedtocomponent.data_changedmessage type and Dispatcher/TetraConsumer method across backend and frontend
[0.8.3] – 2026-02-01
Added
- Component Addition via WebSocket: Added
ComponentDispatcher.component_createdand client-side support for adding components dynamically via WebSockets.
Fixed
- use actual user model for auto-subscribe channel name, instead of "user."
- fix component key generation when
keyis not explicitly provided in template tag. - fix test compatibility with custom user models and playwright environments.
- skip updates for focused fields to preserve user input during data updates
[0.8.2] - 2026-02-31
Added
- Reactive Models: Introduced
ReactiveModelto enable automatic WebSocket updates when Django models are saved or deleted. - Add support for a request sender id to filter server-side change events.
Fixed
- Fixed signal connection reliability for
ReactiveModelacross various inheritance scenarios. - Ensured WebSocket scripts are only included when both reactive components/models are used and WebSocket support is detected.
[0.8.1] - 2026-01-31
Fixed
- Fixed
TypeErrorin_handleAutofocuswhenthis.$rootis undefined (e.g. if the component was removed from the DOM before the next tick). - Support enums (TextChoices, IntChoices!) and FileFields in pydantic validation.
- Make client side redirects faster: don't render the component DOM before redirecting.
Added
- allow component classes in
routes
Changed
- delegate rendering of components to
BaseRendererandComponentRendererclasses - more robust schemata state validation using Pydantic's TypeAdapters for component attributes
- Implementation of the Tetra Unified Protocol (Phase 1 & 2) for both HTTP method calls and WebSockets. This unifies communication into a consistent JSON envelope, moving metadata like Django messages from headers into the response body. Removed
T-ResponseandT-Messagesheaders in favor of the unified protocol and inline script injection. - Removed all fallbacks and support for the legacy communication protocol.
[0.8.0] - 2026-01-26
Changed
- Enhanced middleware efficiency by implementing a fast path for non-Tetra requests, including tests.
- BasicComponents now don't use a Metaclass anymore, but
__init_subclass__()
[0.7.3] - 2026-01-25
Fixed
- Another fix (try?) for file upload vulnerabilities: don't include uploaded file names to form.data when invalid form is rendered. This one is tricky.
[0.7.2] - 2026-01-20
Fixed: improve file handling security and add tests for file upload vulnerabilities
[0.7.1] - 2026-01-14
Added
- Incremental build support for libraries. Tetra now detects changes in component source files (Python, JS, and CSS) and skips
esbuildif no changes are detected. - Added
--forceflag totetrabuildmanagement command (viabuildfunction update) to bypass incremental build check and perform a full rebuild.
Changed
- Improved
STATIC_ROOTmanagement during builds: it is now only cleared whenforce=Trueis used, while individual library directories are still cleaned when they are rebuilt.
[0.7.0] - 2026-01-13
Added
AppRouterandLinkcomponent for dynamic routing/navigation within a container. (Note: Highly experimental).- Support for trailing slashes in routes when Django's
APPEND_SLASHis enabled. - Support for optional arguments in Router
loadmethod. - New routing documentation and comprehensive tests.
- Bundle esbuild within Tetra (auto-download), remove npm dependency.
- rename decorator
@public.subscribeto@public.listenfor consistency.
Fixed
- Memory leak bug when watching files recursively in root directory.
- Ensure all attributes are set when unpickling a component.
- Improved handling of conditional node branches for
{% slot %}tags. - Safely patch
Template.compile_nodelistto preserve the original method.
[0.6.10] - 2026-01-10
Added
- Configurable component module names via settings and constants.
mypyadded to dev dependencies.- Tests for importing Tetra without
channelsandReactiveComponenthandling.
[0.6.9] - 2026-01-10
Fixed
- Ensure Tetra is importable without
channelswhen noReactiveComponentis used. npm installin Makefile.
Changed
- Use
uv runfor tests in Makefile. - Use
publishinstead ofpublish-prodin Makefile.
[0.6.8] - 2026-01-10
Added
- Loading indicators for buttons now work independently. Each button has its own indicator that only shows while that specific button's action is running. When a button finishes its task, only its indicator turns off, while other buttons' indicators keep running if their tasks are still in progress.
- Refactored pytest fixtures and test views to be reusable in other packages that use Tetra.
Fixed
- postpone template compiling to time when all libraries are loaded, so component referrals of not yet loaded components work.
[0.6.7] - 2026-01-06
Added
- DownloadButton demo component
- accept dynamic root tags in components (like `<{{ tag }}>) in checks
Removed
- remove
ViewMixinfrom public API - it's not worth all the problems it creates.
[0.6.6] - 2026-01-05
Added
- add
ViewMixinto allow components to be used as standalone Django views withas_view(). - include security-filtered GET parameter retrieval in
ViewMixin, with automatic injection intoload().
Fixed
- fix a bug that prevented the TetraConsumer from working with channels when DEBUG==False
Added
- allow "page" components to be used as full Django views
[0.6.5] - 2026-01-04
[0.6.3] - 2026-01-04
[0.6.4] - 2026-01-04
Changed
- introduced some complicated workarounds for websockets not working properly, introducing a few new bugs... pfff..
[0.6.2] - 2026-01-04
Fixed
- correctly add all js, scripts, staticfiles etc into the pypi package
[0.6.1] - 2026-01-04
Fixed
- TetraConsumer now is stricter with allowing user and group subscriptions.
Added
- Code coverage
[0.6.0] - 2026-01-02
Changed
- BREAKING change: rename
tx-indicatortot-indicatorHTML class
Fixed
- build_sh.sh does now produce output code in
src/directory structure.
[0.5.3] - 2025-12-20
Fixed
- fix "optional" channels dependency blocking tetra when not using channels. Only import channels if websockets are needed in project
- components in subdir apps are now found correctly by label
Changed
- change to a
src/based directory structure - Django 6.0 compatibility
Changed
- switch to playwright in ui component testing
[0.5.2] - omitted. Don't ask.
[0.5.1] - 2025-10-03
Fixed
- use encrypted wss scheme when connecting to server using https
- some smaller bugfixes
Changed
- clear static files before building libraries
- get rid of Blacknoise in demo project
[0.5.0] - 2025-10-02
Changed
- introduce websocket-enhanced
ReactiveComponents
[0.4.0] - 2025-08-04
Changed
- rename
request.tetra.current_url_abs_pathtocurrent_url_full_pathto better adhere to naming standards.current_url_abs_pathis deprecated. - BREAKING CHANGE remove the
@tag for component rendering. Use the component name alone. - BREAKING CHANGE disable
{% <app>.<library>.<component_name> /%}reference. Only allow{% [<library_name>.]<component_name> / %} - BREAKING CHANGE rename
@vtag tolivevar - BREAKING CHANGE
blockinside components renamed toslot - refactoring of internal Component and Library methods
Added
request.tetra.current_url_paththat holds the path without query params- a
tetratemplate variable that holds the TetraDetails of a request, or possible equivalents of the current main request. - Client URL pushes are now anticipated and reflected on the server before rendering the component on updates
[0.3.1] - 2025-04-19
- BREAKING CHANGE rename all
tetra:*events to kebab-case:before-request,after-request,component-updated,component-before-removeetc. This was necessary because camelCase Events cannot be used properly inx-on:attributes - HTMX attributes are forced to lowercase, which breaks the event capture.
[0.3.0] - 2025-04-18
Added
- beforeRequest, afterRequest events
- add support for loading indicators (=spinners)
- add support for file downloads in component methods
Changed
- BREAKING CHANGE rename all
tetra:*events to camelCase:componentUpdated,componentBeforeRemoveetc.
Fixed
- fix file uploads for FormComponent (using multipart/form-data)
[0.2.1] - 2025-03-29
- fix a small bug that could early-delete temporary uploaded files
[0.2.0] - 2025-03-27
Added
- DynamicFormMixin for dynamically updatable FormComponents
- Improved demo site
- Added debug logging handler
- Improved component import error handling
- Allow component names to be dynamic
@vshortcut templatetag for "live" rendering of frontend variables- Better support for Django models
- Experimental FormComponent and ModelFormComponent support with form validation
- Definable extra context per component class
reset()method for FormComponentpush_url()andreplace_url()component methods for manipulating the URL in the address barrecalculate_attrs()method for calculated updates to attributes before and after component methodsrequest.tetrahelper for current_url, current_abs_path and url_query_params, like in HTMX- add life cycle Js events when updating/removing etc. components
- add a special response indicator for Tetra responses.
- Integration of Django messages into Tetra.
<!-- HTML comments -->at begin of components are possible now
Removed
- BREAKING CHANGE
ready()method is removed and functionally replaced withrecalculate_attrs()
Changed
- BREAKING CHANGE: registering libraries is completely different. Libraries are directories and automatically found. The library automatically is the containing module name now. Explicit "default = Library()" ist disregarded.
- Components should be referenced using PascalCase in templates now
- Component tags: replace
**contextwith__all__when passing all context in template tags - More verbose error when template is not enclosed in HTML tags
- Improved component import error handling
- Improved demo site
[0.1.1] - 2024-04-10
Changed
- New package name: tetra
- Add conditional block check within components
- Update Alpine.js to v3.13.8
- Switch to pyproject.toml based python package
- Improve demo project: TodoList component,- add django-environ for keeping secrets, use whitenoise for staticfiles
- Give users more hints when no components are found
- MkDocs based documentation
- Format codebase with Black
Added
- Basic testing using pytest
Fixed
- Correctly find components
[0.0.5] - 2022-06-13
Changed
- This is the last package with the name "tetraframework", transition to "tetra"
- Provisional Python 3.8 support
Fixed
- Windows support
[0.0.4] - 2022-06-22
- Cleanup
[0.0.3] - 2022-05-29
Added
_parentclient attribute added, this can be used to access the parent component mounted in the client._redirectclient method added, this can be used to redirect to another url from the public server methods.self.client._redirect("/test")would redirect to the/testurl._dispatchclient method added, this is a wrapper around the Alpine.jsdispatchmagic allowing you to dispatch events from public server methods. These bubble up the DOM and be captured by listeners on (grand)parent components. Example:self.client._dispatch("MyEvent", {'some_data': 123})._refreshpublic method added, this simply renders the component on the server updating the dom in the browser. This can be used in combination with_parentto instruct a parent component to re-render from a child components public method such as:self.client._parent._updateHtml()
Changed
- Built in Tetra client methods renamed to be prefixed with an underscore so that they are separated from user implemented methods:
updateHtmlis now_updateHtmlupdateDatais now_updateDataremoveComponentis now_removeComponentreplaceComponentAndStateis now_replaceComponent