diff --git a/README.md b/README.md
index fc70e19..1cd4ea6 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,7 @@ Make the Tag Helpers and toolkit types available to Razor views in `_ViewImports
```html
@using Ramstack.HtmxToolkit
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Ramstack.HtmxToolkit
```
@@ -67,21 +68,27 @@ Render the configuration metadata in the document `
`:
```
-Map the companion script endpoint in `Program.cs`:
+On ASP.NET Core 9 or later, enable static assets and associate them with the endpoints that render views in `Program.cs`:
```csharp
-app.MapHtmxToolkitScript();
+app.MapStaticAssets();
+app.MapRazorPages().WithStaticAssets();
```
-Load HTMX first, then the toolkit script in the layout:
+For MVC, apply `.WithStaticAssets()` to the controller endpoint builder instead; a hybrid Razor Pages and MVC
+application applies it to each endpoint set. On ASP.NET Core 6–8, enable static files:
+
+```csharp
+app.UseStaticFiles();
+```
+
+The NuGet package includes the toolkit script as a static web asset. Load it after HTMX in the layout:
```html
-
+
```
-The default script URL contains a content hash, so the script can be cached indefinitely. When the script changes, its URL changes automatically.
-
You can now generate an HTMX URL from ASP.NET Core route information:
```html
@@ -444,20 +451,15 @@ builder.Services.AddHtmxToolkit(options =>
});
```
-Instead of mapping an endpoint, the companion script can be embedded directly:
+Use the readable script during development with:
```html
-
+
```
-Pass `debug: true` to `HtmxToolkitScript` or `HtmxToolkitScriptPath` to use the readable script during development.
-A custom endpoint path is also supported:
+Load HTMX before the toolkit; if deferring execution, apply `defer` to both scripts.
-```csharp
-app.MapHtmxToolkitScript("/assets/htmx-toolkit.js");
-```
+See [Antiforgery and Toolkit script](docs/articles/antiforgery.md) for static asset and caching details.
## Compatibility Notes
@@ -506,9 +508,7 @@ Idiomorph library before the first morph swap:
-
+
```
diff --git a/docs/api-overwrites/tag-helpers.md b/docs/api-overwrites/tag-helpers.md
index 45d38bd..eaf34eb 100644
--- a/docs/api-overwrites/tag-helpers.md
+++ b/docs/api-overwrites/tag-helpers.md
@@ -32,17 +32,3 @@ example:
- |-
[!code-razor[](../snippets/tag-helpers/ConfigTagHelper.cshtml)]
---
-
----
-uid: Ramstack.HtmxToolkit.HtmlHelperExtensions.HtmxToolkitScriptPath(Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper,System.Boolean)
-example:
- - |-
- [!code-razor[](../snippets/tag-helpers/ToolkitScript.cshtml)]
----
-
----
-uid: Ramstack.HtmxToolkit.Hosting.EndpointRouteBuilderExtensions.MapHtmxToolkitScript(Microsoft.AspNetCore.Routing.IEndpointRouteBuilder)
-example:
- - |-
- [!code-csharp[](../snippets/tag-helpers/MapToolkitScriptEndpoint.cs)]
----
diff --git a/docs/articles/antiforgery.md b/docs/articles/antiforgery.md
index 0ad69cf..e77b89c 100644
--- a/docs/articles/antiforgery.md
+++ b/docs/articles/antiforgery.md
@@ -16,17 +16,45 @@ Otherwise, it is added to the request parameters under the configured form-field
## Configure the layout
-Map the script endpoint in `Program.cs`:
+Enable static files in `Program.cs`:
```csharp
-using Ramstack.HtmxToolkit.Hosting;
-
var app = builder.Build();
-app.MapHtmxToolkitScript();
+app.UseStaticFiles();
app.MapRazorPages();
```
+On ASP.NET Core 9 or later, use `MapStaticAssets()` and associate the asset collection with the page endpoints
+instead to enable build-time compression and fingerprinted URLs:
+
+```csharp
+app.MapStaticAssets();
+app.MapRazorPages().WithStaticAssets();
+```
+
+For MVC, apply `.WithStaticAssets()` to the controller endpoint builder, for example:
+
+```csharp
+app.MapStaticAssets();
+app.MapDefaultControllerRoute().WithStaticAssets();
+```
+
+A hybrid Razor Pages and MVC application applies it to each endpoint set that renders views:
+
+```csharp
+app.MapStaticAssets();
+app.MapRazorPages().WithStaticAssets();
+app.MapControllers().WithStaticAssets();
+```
+
+`MapControllers()` covers attribute-routed controllers; with conventional or area routing, apply
+`.WithStaticAssets()` to each `MapControllerRoute` or `MapAreaControllerRoute` call.
+
+> [!NOTE]
+> ASP.NET Core reads the asset collection from the current endpoint's metadata. An endpoint without it still
+> renders a working URL: the resolver falls back to a `?v=...` version instead of a fingerprinted URL.
+
Render configuration metadata in `
`, then load HTMX before the Toolkit script:
```html
@@ -37,7 +65,7 @@ Render configuration metadata in `
`, then load HTMX before the Toolkit scr
@RenderBody()
-
+
```
@@ -79,42 +107,47 @@ No token input is required in this form because the layout metadata and Toolkit
When a boosted navigation returns a new full document, the Toolkit script reads antiforgery metadata from that response
and updates the token used for later requests. Ensure the returned document contains ``.
-## Script endpoint and caching
+## Static web assets and caching
-The default endpoint path contains a content hash:
+The NuGet package includes both script variants as ASP.NET Core static web assets:
```text
-/htmxtoolkit/{content-hash}
+/_content/Ramstack.HtmxToolkit/htmx-toolkit.min.js
+/_content/Ramstack.HtmxToolkit/htmx-toolkit.js
```
-It returns the minified script with `Cache-Control: public,max-age=31536000`. A new embedded script receives a new default URL.
+Reference the minified file from the layout with an app-relative path:
-Pass a custom path when routing conventions require one:
-
-```csharp
-app.MapHtmxToolkitScript("/assets/htmx-toolkit.js");
+```html
+
```
-When using a stable custom path, account for cache invalidation in deployment or proxy configuration.
+This form requires `@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers` in `_ViewImports.cshtml`.
+ASP.NET Core resolves the `~` path and applies content-based versioning:
-Request the readable script while diagnosing browser behavior:
+- On ASP.NET Core 9 or later, when the current endpoint's asset collection contains the script, the framework
+ selects the fingerprinted URL, such as `htmx-toolkit.min.{fingerprint}.js`. In production, `MapStaticAssets()`
+ serves fingerprinted assets with long-lived, immutable caching and supports precompressed Gzip and Brotli
+ representations.
+- Otherwise, `asp-append-version="true"` appends a `?v=...` version computed and cached from the file content.
+ This includes ASP.NET Core 6–8 and applications using `UseStaticFiles()`.
-```html
-
-```
+Both forms account for the application's path base. When the file changes, its versioned URL changes. Cache
+headers are managed by the application's static asset or static file configuration; adding `?v=...` does not
+itself set a cache lifetime.
-The debug URL adds `?debug` and the endpoint returns the unminified asset.
+Static web assets work with both project references and NuGet packages. On publish, ASP.NET Core copies
+the scripts into the application's `wwwroot/_content/Ramstack.HtmxToolkit` directory.
-## Inline the script
-
-Applications that cannot map the endpoint can render the embedded asset inside a script element:
+Request the readable script while diagnosing browser behavior:
```html
-
+
```
-Inlining removes a request but changes the content security policy and repeats the script in every full document.
-Prefer the cacheable endpoint for most applications.
+If you use `defer`, apply it to both HTMX and the Toolkit script so their execution order is preserved.
## Disable automatic antiforgery
@@ -135,6 +168,6 @@ The Toolkit script can still be used for morph compatibility after antiforgery m
- Antiforgery protects cookie-authenticated state-changing requests; it does not replace authentication or authorization.
- A custom `hx-header-*` value is client-controlled and must not be trusted as proof of identity.
- Cross-origin permissions still require correct ASP.NET Core CORS and credential configuration.
-- An inline Toolkit script may require a CSP nonce or hash. The endpoint form works naturally with a policy that allows scripts from the application's origin.
+- The Toolkit static web asset works with a CSP policy that allows scripts from the application's origin.
If a protected request returns 400, see [Troubleshooting](troubleshooting.md#post-returns-http-400).
diff --git a/docs/articles/getting-started.md b/docs/articles/getting-started.md
index b6f251b..6b0dccd 100644
--- a/docs/articles/getting-started.md
+++ b/docs/articles/getting-started.md
@@ -14,7 +14,7 @@ This example assumes HTMX 2.x, which is the toolkit default.
## 2. Register HtmxToolkit
-Register Razor Pages and the toolkit in `Program.cs`, then map the companion script endpoint:
+Register Razor Pages and the toolkit in `Program.cs`, and enable static files:
```csharp
using Ramstack.HtmxToolkit.Hosting;
@@ -27,7 +27,6 @@ builder.Services.AddHtmxToolkit();
var app = builder.Build();
app.UseStaticFiles();
-app.MapHtmxToolkitScript();
app.MapRazorPages();
app.Run();
@@ -36,17 +35,32 @@ app.Run();
No configuration delegate is required for HTMX 2.x. To use another major version,
see [Choose an HTMX version](choosing-version.md).
+The setup above works on ASP.NET Core 6 or later. On ASP.NET Core 9 or later, use the following instead of
+`UseStaticFiles()` and `MapRazorPages()` to enable build-time compression and fingerprinted asset URLs:
+
+```csharp
+app.MapStaticAssets();
+app.MapRazorPages().WithStaticAssets();
+```
+
+> [!NOTE]
+> In a hybrid Razor Pages and MVC application, call `.WithStaticAssets()` on every endpoint set that renders
+> views, for example `app.MapControllers().WithStaticAssets()` as well.
+
## 3. Enable the Razor helpers
Add the namespace and Tag Helpers to `Pages/_ViewImports.cshtml`:
```html
@using Ramstack.HtmxToolkit
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Ramstack.HtmxToolkit
```
-The `@using` directive makes `Html.HtmxToolkitScriptPath()` and toolkit types available.
-The `@addTagHelper` directive enables attributes such as `hx-page`, `hx-route-*`, and the `` element.
+The `@using` directive makes toolkit types available.
+The first `@addTagHelper` directive enables the standard ASP.NET Core Tag Helpers used by the layout snippet
+(`~` path resolution and `asp-append-version`). The second enables attributes such as `hx-page` and `hx-route-*`,
+as well as the `` element.
## 4. Configure the layout
@@ -64,13 +78,15 @@ Render the configuration metadata in `
`. Load HTMX first and the Toolkit s
@RenderBody()
-
+