SmarterReactTemplateTagManager
Vite-generated React manifest.json loader and asset collector base class for Django templatetags.
This module provides a reusable base class and supporting types for managing Vite-generated React manifest.json files and collecting frontend assets for React apps in Django projects. It is designed to be instantiated as a singleton representing a specific React app, enabling Django templates to include the correctly-sequenced JavaScript and CSS assets built by Vite for each app.
Key Features
Loads and caches the manifest.json for each React app from the static files directory, validated against the Pydantic model
ViteManifest.Recursively collects CSS and JS dependencies for the entry point, including all imports.
Returns the JS and CSS assets for the entry point as a
ReactAppAssets, for use in Django template tags.Designed as a base class to be instantiated for each React app; singletons are used to register template tags per app.
Main Classes and Functions
SmarterReactTemplateTagManager: Base class for managing Vite-generated React manifest loading and asset collection for a React app.
reactapp_build_assets: The JS and CSS assets for the configured entry point.
smarter.lib.django.templatetags.smarter_react_contract: the Pydantic models of the manifest and of the assets.
Usage Example
In a Django template, use the registered template tag for your app to get asset paths:
{% load react_dashboard %}
{% dashboard_react_assets as assets %}
{% for css_file in assets.css %}
<link class="smarter" rel="stylesheet" href="{% static 'react/smarter-dashboard/' %}{{ css_file }}">
{% endfor %}
Example React manifest.json
A typical React manifest.json looks like this:
{
"_rolldown-runtime.js": {
"file": "assets/rolldown-runtime.js",
"name": "rolldown-runtime"
},
"_xterm-TdnZ7DQy.css": {
"file": "assets/xterm-TdnZ7DQy.css",
"src": "_xterm-TdnZ7DQy.css"
},
"_xterm.js": {
"file": "assets/xterm.js",
"name": "xterm",
"imports": [
"_rolldown-runtime.js"
],
"css": [
"assets/xterm-TdnZ7DQy.css"
]
},
"index.html": {
"file": "assets/index.js",
"name": "index",
"src": "index.html",
"isEntry": true,
"imports": [
"_rolldown-runtime.js",
"_xterm.js"
],
"css": [
"assets/index-DvLY75bJ.css"
]
}
}
- class smarter.lib.django.templatetags.smarter_react_templatetag_manager.SmarterReactTemplateTagManager(app_name, templatetag_name)[source]
Bases:
SmarterHelperMixinBase class for per-React-app singleton managers that load and analyze Vite-generated React manifest.json files in order to generate ordered lists of JS and CSS assets.
This class is intended to be instantiated once per React app, providing a long-lived singleton that manages loading and caching the React manifest.json and collecting all required JS and CSS assets for the app’s entry point.
After instantiation, the only public attribute used is reactapp_build_assets, which returns ordered lists of the JS and CSS assets for the configured entry point. Its value is cached for the effective lifetime of the object instance (until server reboot).
This design ensures that asset collection is efficient and consistent, and that Django templates can reliably include the dependency-ordered asset files for each React app.
- __init__(app_name, templatetag_name)[source]
Initialize the SmarterReactTemplateTagManager.
- app_name: str
- find_entry_key()[source]
Locate the key of the manifest’s entry point, the chunk with
"isEntry": true.Example entry:
"index.html": { "file": "assets/index.js", "name": "index", "src": "index.html", "isEntry": true, "imports": [ "_rolldown-runtime.js", "_xterm.js" ], "css": [ "assets/index-DvLY75bJ.css" ] }
- property manifest: ViteManifest | None[source]
Load, validate and cache the app’s manifest.json.
A manifest.json that is missing, isn’t JSON, or doesn’t match
ViteManifestis logged, and is cached as None, until the server restarts.- Returns:
The manifest, or None if it couldn’t be loaded.
- Return type:
Optional[ViteManifest]
- property manifest_path: str
The path of the app’s Vite-generated manifest.json in the static files directory.
- Returns:
The manifest.json’s path.
- Return type:
- property reactapp_build_assets: ReactAppAssets[source]
The JS and CSS files of the app’s entry point, including all of its imports, in load order.
The entry point’s own files come first, followed by those of its imports, depth first. The result is cached for the lifetime of the manager.
- Returns:
The entry point’s JS and CSS files. Both lists are empty if there is no manifest.
- Return type:
Example output:
{ "js": [ "assets/index-CZK_Bxxh.js", "assets/rolldown-runtime-B3igc2qu.js", "assets/xterm-D5XSfLrr.js" ], "css": [ "assets/index-58MXwt-L.css", "assets/xterm-kHJ-D0s7.css" ] }
- templatetag_name: str
Contract
The Pydantic models of the Vite manifest.json that the manager reads, and of the
assets that each React app’s template tag returns.
SmarterReactTemplateTagManager
reads and returns.
ViteManifestis a Vite-generated Reactmanifest.json: a map ofViteManifestChunkkeyed by source path. The manager validates the file against it when it loads it, and collects an entry point’s assets with its methods.ReactAppAssetsis what every<app>_react_assetstemplate tag returns: the ordered JS and CSS files that a Django template includes for a React app.
The manifest is a third-party shape. ViteManifestChunk declares the
fields that Vite documents, and allows extra fields, which newer Vite (or
Rolldown) versions add, so that a Vite upgrade doesn’t break page rendering.
Smarter’s own addition, the _custom entry that every package’s
vite.config.ts writes after the build, is a ReactAppBuildInfo.
- smarter.lib.django.templatetags.smarter_react_contract.BUILD_INFO_KEY = '_custom'
The key of the build information that each React package’s
vite.config.tsadds to its manifest.json.
- class smarter.lib.django.templatetags.smarter_react_contract.ReactAppAssets(**data)[source]
Bases:
BaseModelThe ordered JS and CSS files of a React app’s entry point, which a Django template includes.
Every
<app>_react_assetstemplate tag returns one. Templates read its attributes, e.g.{% for css_file in assets.css %}.Example:
{ "js": [ "assets/index-CZK_Bxxh.js", "assets/rolldown-runtime-B3igc2qu.js", "assets/xterm-D5XSfLrr.js" ], "css": [ "assets/index-58MXwt-L.css", "assets/xterm-kHJ-D0s7.css" ] }
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.lib.django.templatetags.smarter_react_contract.ReactAppBuildInfo(**data)[source]
Bases:
BaseModelThe build information that each React package’s
vite.config.tsadds to its manifest.json, as_custom.Example:
"_custom": { "buildTime": "2026-10-12T01:09:47.988Z", "version": "0.3.0", "buildEnv": "production" }
- model_config = {'extra': 'forbid', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- smarter.lib.django.templatetags.smarter_react_contract.ReactAssetType
The kinds of asset that a React app’s entry point loads.
alias of
Literal[‘js’, ‘css’]
- class smarter.lib.django.templatetags.smarter_react_contract.ViteManifest(**data)[source]
Bases:
BaseModelA React app’s Vite-generated
manifest.json: its chunks, keyed by source path, and Smarter’s build information.In the file, the build information is the
_customentry, beside the chunks. Validating a manifest.json splits it out intobuild_info, and dumping the model puts it back, somodel_dump(by_alias=True)has the file’s shape.See the example in
smarter.lib.django.templatetags.smarter_react_templatetag_manager.- build_info: ReactAppBuildInfo | None
- chunks: dict[str, ViteManifestChunk]
- collect_assets(key, asset_type, seen=None)[source]
Recursively collect the JS or CSS files of a chunk and of its static imports.
A chunk’s own files come first, followed by those of each of its
imports, depth first, in the order they are listed. Each chunk is visited once, so circular imports terminate.- Parameters:
- Returns:
The asset file paths, relative to the app’s static directory.
- Return type:
- entry_key()[source]
Find the key of the manifest’s entry point, the first chunk with
"isEntry": true.
- join_build_info(handler)[source]
Dump the manifest in the shape of manifest.json, with the build information as its
_customentry.
- model_config = {'extra': 'forbid'}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.lib.django.templatetags.smarter_react_contract.ViteManifestChunk(**data)[source]
Bases:
BaseModelOne entry of a Vite-generated
manifest.json: a chunk, or a static asset.See https://vite.dev/guide/backend-integration. Extra fields are allowed, because Vite and Rolldown add their own.
Example:
"index.html": { "file": "assets/index.js", "name": "index", "src": "index.html", "isEntry": true, "imports": ["_rolldown-runtime.js", "_xterm.js"], "css": ["assets/index-DvLY75bJ.css"] }
- model_config = {'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].