From arbiter-skills
Wires the Blazor IDispatcher abstraction from Arbiter.Dispatcher across render modes (WebAssembly, Server Interactive, Auto) with MessagePack/JSON/Server transports and component state helpers.
How this skill is triggered — by the user, by Claude, or both
Slash command
/arbiter-skills:arbiter-dispatcherThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Unified `IDispatcher` abstraction so Blazor components depend on a single interface regardless of render mode. The right transport is chosen at startup:
Unified IDispatcher abstraction so Blazor components depend on a single interface regardless of render mode. The right transport is chosen at startup:
| Render mode | Implementation | Transport |
|---|---|---|
| WebAssembly | MessagePackDispatcher / JsonDispatcher | HTTP POST → /api/dispatcher/send |
| Server Interactive | ServerDispatcher | Direct in-process IMediator |
# Server (host) project
dotnet add package Arbiter.Dispatcher.Server
# Client (WASM and/or shared component library)
dotnet add package Arbiter.Dispatcher.Client
Server host project
using Arbiter.Dispatcher;
using Arbiter.Dispatcher.Server;
builder.Services.AddCommandQuery();
builder.Services.AddServerDispatcher(); // in-process IDispatcher for Server Interactive
builder.Services.AddDispatcherService(); // dispatcher HTTP endpoint for WASM clients
var app = builder.Build();
app.MapDispatcherService().RequireAuthorization();
WebAssembly client project
using Arbiter.Dispatcher;
// MessagePack is recommended (faster, smaller payloads)
builder.Services.AddMessagePackDispatcher((sp, client) =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
});
// Or JSON if MessagePack interop is a problem:
// builder.Services.AddJsonDispatcher((sp, client) => { ... });
For Blazor Auto render mode, register both — each render environment resolves the right IDispatcher:
// Host project
builder.Services.AddServerDispatcher();
builder.Services.AddDispatcherService();
// WASM client project
builder.Services.AddMessagePackDispatcher((sp, client) =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
});
// Low-level
var user = await dispatcher.Send<EntityIdentifierQuery<int, UserReadModel>, UserReadModel>(
new EntityIdentifierQuery<int, UserReadModel>(principal, id), ct);
// High-level — IDispatcherDataService wraps the common CRUD shapes
var user = await dataService.Get <int, UserReadModel>(id);
var page = await dataService.Page <UserReadModel>(entityQuery);
var saved = await dataService.Save <int, UserUpdateModel, UserReadModel>(id, updateModel);
@inject ModelStateEditor<int, UserReadModel, UserUpdateModel> Store
@implements IDisposable
@code {
[Parameter] public int Id { get; set; }
[Parameter] public bool IsCreate { get; set; }
protected override async Task OnInitializedAsync()
{
Store.OnStateChanged += HandleStateChanged;
if (IsCreate) Store.New();
else await Store.Load(Id);
}
private void HandleStateChanged(object? s, EventArgs e) => InvokeAsync(StateHasChanged);
public void Dispose() => Store.OnStateChanged -= HandleStateChanged;
}
<!--
Store.Model bound to the edit form (TUpdateModel)
Store.IsBusy load/save/delete in progress
Store.IsDirty unsaved changes
Store.Save() Store.Delete() Store.Cancel()
-->
Lighter-weight helpers if you don't need the full edit lifecycle:
ModelStateManager<TModel> — single-model holder with change notifications.ModelStateLoader<TKey, TModel> — load-only flow.ModelStateEditor<TKey, TReadModel, TUpdateModel> — full load/edit/save/delete.Register them once per closed type:
services.AddScoped<ModelStateEditor<int, UserReadModel, UserUpdateModel>>();
npx claudepluginhub loresoft/arbiter --plugin arbiter-skillsExplains Blazor component model: render modes (SSR, Interactive Server/WebAssembly/Auto), lifecycle methods, parameters, EventCallbacks, and communication via cascading values. For .NET web app developers.
Building Blazor apps. Hosting models, render modes, routing, streaming rendering, prerender.
Routes to the correct Arbiter .NET library specialist skill based on the user's needs — Mediation, CommandQuery, Mapping, Dispatcher, Communication, Services, OpenTelemetry, or Messaging.ServiceBus.