SpawnDev.SpawnJS.RazorRenderer 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package SpawnDev.SpawnJS.RazorRenderer --version 1.0.0
                    
NuGet\Install-Package SpawnDev.SpawnJS.RazorRenderer -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SpawnDev.SpawnJS.RazorRenderer" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SpawnDev.SpawnJS.RazorRenderer" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="SpawnDev.SpawnJS.RazorRenderer" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SpawnDev.SpawnJS.RazorRenderer --version 1.0.0
                    
#r "nuget: SpawnDev.SpawnJS.RazorRenderer, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SpawnDev.SpawnJS.RazorRenderer@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SpawnDev.SpawnJS.RazorRenderer&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=SpawnDev.SpawnJS.RazorRenderer&version=1.0.0
                    
Install as a Cake Tool

SpawnDev.SpawnJS.RazorRenderer

NuGet

💜 Built and maintained by one independent developer — no company, no overhead, just code. If SpawnDev.SpawnJS.RazorRenderer saves you time, please consider sponsoring its development ». Sponsorship is what keeps it alive and maintained.

Interactive Blazor components in .NET WebAssembly without the Blazor JS runtime.

Razor components render straight to the real DOM through SpawnJS - @onclick, @bind, StateHasChanged, component lifecycle and EventCallbacks all work - and mount into any element or shadow root. That means you can drop a real, interactive Blazor component onto any page (even one you don't control, even loaded from a CDN link) with full DOM and CSS isolation, and no Blazor circuit.

How it is different from Blazor WebAssembly

Blazor's own renderer serializes each render batch and ships it to JavaScript, where Web.JS walks the edits and mutates the DOM. SpawnDomRenderer is a Microsoft.AspNetCore.Components.RenderTree.Renderer that consumes the same RenderBatch in C# and applies every edit to the DOM directly through SpawnJS's typed interop. The component model is genuine Blazor - only the renderer is ours, and there is no Blazor JavaScript runtime or SignalR circuit involved.

Setup

using SpawnDev.SpawnJS.RazorRenderer;

// .NET WASM app (SpawnJS host - no Blazor bootstrap)
builder.Services.AddSpawnJSRuntime(out var JS);
builder.Services.AddRazorRenderer();   // registers the SpawnDomRenderer singleton

Mount a component into any element:

var renderer = app.Services.GetRequiredService<SpawnDomRenderer>();
using var document = JS.Get<Document>("document");

var host = document.CreateElement<HTMLDivElement>("div");
document.Body!.Append(host);

await renderer.RenderComponentAsync<App>(host);           // App is your root .razor component
// with parameters:
await renderer.RenderComponentAsync<App>(host, new() { ["Title"] = "Hello" });

One renderer hosts many root components; each mount gets its own component id.

Shadow root (DOM + CSS isolation)

RenderComponentAsync takes any Node, and ShadowRoot is a Node, so mounting into a shadow root gives you full encapsulation from the host page for free - host-page CSS cannot reach in, your component's CSS cannot leak out, and events fire correctly across the boundary (listeners are attached per element, so there is no shadow-retargeting problem a document-level delegator would have).

var host = document.CreateElement<HTMLDivElement>("div");
document.Body!.Append(host);
var shadow = host.AttachShadow(new AttachShadowRootOptions { Mode = "open" }); // or "closed"
await renderer.RenderComponentAsync<App>(shadow);

⚠️ Requirement: the host project must import the Web directive namespace

@onclick, @bind and the other event directives are only recognized when Microsoft.AspNetCore.Components.Web is in the Razor @using scope. If it is missing, the Razor compiler emits them as literal attributes (@onclick="..." ends up as a real DOM attribute) and events silently do nothing - the app compiles cleanly, boots, and renders. Make sure the project hosting your components has an _Imports.razor containing at least:

@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Components.Web

What works today

  • Elements, text, attributes, nested components, regions, keyed reorders, markup blocks (MarkupString)
  • @onclick and the mouse/keyboard/focus events; @bind / @bind:event
  • StateHasChanged re-render, component lifecycle, parameter flow into child components
  • EventCallbacks and typed EventArgs (MouseEventArgs, KeyboardEventArgs, ChangeEventArgs, ...)
  • Mounting into a plain element or an open/closed shadow root

Not yet ported from Blazor's renderer (contributions welcome): the full special-property set beyond <input> value/checked (select/textarea/option), MathML namespace, <option> deferred-value ordering, cross-render active-element focus preservation, <script> execution inside markup, and event delegation (listeners are currently per element, which is correct but not yet optimized).

Requirements

  • .NET 10 WebAssembly
  • SpawnDev.SpawnJS
  • Microsoft.AspNetCore.Components.Web (referenced transitively; the Blazor SDK is used only to compile .razor)

The SpawnDev Crew

  • LostBeard (Todd Tanner) - Captain, library author, keeper of the vision
  • Riker - First Officer, implementation lead on consuming projects
  • Data - Operations Officer, deep-library work, test rigor, root-cause analysis
  • Tuvok - Security/Research Officer, design planning, documentation, code review
  • Geordi - Chief Engineer, library internals, GPU kernels, backend work
  • Seven - Wasm backend, GPU kernels, fail-loud verification

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 0 8/5/2026
1.0.0 37 8/5/2026