{}

Extend

This track is for developers extending the framework — writing new widgets, composing existing ones into higher-level building blocks, or packaging a set of widgets as a reusable library. The shape is the same whether the widget is a one-off helper in your app or the start of a published library: a Go struct, a Draw method, and (often) a sliver of CSS or JS alongside.

Topics

Widget anatomy

The Widget interface, embedding WidgetBase, the typed-builder pattern with generics, and how Children / Draw / Drawn / Shown fit together.

Composing existing widgets

Most useful widgets are built from existing ones. Wrapping a Form + InputText pair into a self-contained search box, for example, takes a dozen lines.

Assets & CSS

Registering CSS, JS, and dynamic handlers with the AssetRegistry. Material design tokens, theme-friendly class names, and the bespa-namespaced URL convention.

State-aware widgets

Implementing Drawn / Shown / RedrawIfChanged so a custom widget plays correctly with the incremental-redraw protocol. Common pitfalls and the placeholder-span trick.

Custom form inputs

The InputWidget contract, the hidden-input rule, and the JS bridge for inputs backed by a third-party library — with richedit as a worked example.

Packaging as a library

Structuring a widget package: factory type, function aliases, type aliases, asset embedding, and how the framework's default factory composes your library in.

Material theming

How widget CSS should reference --md-sys-* tokens so it themes for free, and how canvas-rendered widgets resolve those tokens at draw time and re-render on theme change.

Reading the source

Every package under the framework root is a worked example of building a widget library: basic/ for primitives, form/ for input widgets, chart/ for an external-library wrapper, code/ for a server-side-processing widget. Pick whichever matches what you want to build and read it end-to-end — a typical widget is under 200 lines of Go.