Lesson 5.3: UI extension — semantic kinds
Difficulty: Intermediate | Duration: 15 min | Prerequisites: Lesson 5.1; .NET 10 SDK
Runnable scaffold. This lesson ships
start/(the[BowireExtension]descriptor is complete + discovered, but the JSviewer.mountonly renders a placeholder) andcompleted/(the JS reads the paired lat/lon fromctx.interpretationsand renders a coordinate card with an OpenStreetMap link). The C# is identical between the two — the work is entirely in the embedded JS bundle. It's an offline-safe, dependency-free stand-in for the shippedKuestenlogik.Bowire.MapMapLibre widget: samecoordinate.wgs84kind, same mechanism, no 800 KB renderer. Both build againstKuestenlogik.Bowire2.1.0.
Overview
Protocol plugins extend what Bowire can talk to. UI extensions extend how Bowire renders a response. When a response field carries a semantic kind — a tag like coordinate.wgs84 — Bowire can auto-mount a purpose-built widget (a map, a chart, a hex viewer) over it instead of showing raw JSON.
How it works
- A field is annotated with a semantic kind (e.g.
coordinate.wgs84for a lat/long pair). - A UI extension declares which kind it handles via the
[BowireExtension]attribute and implementsIBowireUiExtension. - Auto-discovery (the same
[BowireExtension]assembly scan that finds field-detectors) mounts the widget wherever a matching kind appears — no per-response wiring.
The canonical example: a coordinate.wgs84 field auto-renders a map widget with a pin, instead of { "lat": 53.55, "lon": 9.99 }.
Steps
1. Add the extension
In a plugin assembly (scaffolded as in Lesson 5.1), implement IBowireUiExtension and tag it:
[BowireExtension]
public sealed class MapWidgetExtension : IBowireUiExtension
{
public string SemanticKind => "coordinate.wgs84";
// render contract: emit the widget markup/props for a matching field
}
[BowireExtension] opts the type into the auto-discovery scan (the same mechanism protocol/field-detector extensions use), so no manual registration is needed.
2. Tag the data
A field surfaces the widget when its semantic kind resolves to coordinate.wgs84 — either declared by the protocol's schema, or inferred by a field-detector (Bowire ships a WGS84 coordinate detector). When the workbench renders a response containing that field, your widget mounts automatically.
3. Verify
Invoke a method whose response carries a coordinate. Instead of raw JSON, the response pane shows the map with a pin. Remove the extension (or its assembly) and the field degrades gracefully back to JSON — extensions are additive.
Ship UI extensions in the same NuGet as a protocol plugin, or standalone. The
Kuestenlogik.Bowire.Mappackage is the shipped map-widget extension — a real reference.
Key Takeaways
- Semantic kinds drive rendering — a tag like
coordinate.wgs84picks a widget. [BowireExtension]+IBowireUiExtension= auto-discovered UI extension; no per-response wiring.- Additive + graceful — no matching extension → the field falls back to JSON.
What's Next
Continue: → Lesson 5.4: Plugin lifecycle