Documentation
¶
Overview ¶
dashboard.go implements beacon's live home view: the source -> connector -> sink DAG templates/frag_dashboard.html renders, and the GET /frag/dashboard handler templates/dashboard.html polls every 5s (hx-trigger="load, every 5s") — see dashboard.html's comment for why it ships an empty container rather than rendering this fragment inline, the same "ships empty, fetches client-side" shape the overview pages use.
docspages.go implements beacon's onboard operator manual at GET /docs and GET /docs/{slug}: the markdown files embedded from docs/*.md, rendered to HTML once per file and cached (the embedded content never changes at runtime, so there is nothing to invalidate), and served inside templates/docs.html's sidebar + <article> layout — see pages.go's "docs" entry and ui.go's root-level route registrations. "/docs" is reserved from HTTP sink paths, so configured data endpoints cannot collide with the manual.
forms.go implements the Sources, Sinks, and Connectors CRUD pages: the page/fragment data types templates/sources.html, sinks.html, connectors.html, connector_detail.html, and every frag_*.html render against, the model<->form conversions, and the HTTP handlers Handler (ui.go) wires up at /sources, /sinks, /connectors, /frag/*.
Sources and sinks are handled by deliberately parallel, non-generic code (sourceX / sinkX pairs) rather than a shared generic implementation: the two entities' type-specific fields differ enough (source http_sse/ http_ws carries URL+Headers; sink http_sse/http_ws carries Path, and sink alone has tcp (Address) and file (FilePath/Format/MaxFileBytes/ MaxFiles) types with no source equivalent) that a generic abstraction would need almost as much per-kind branching as just writing both out, while being harder to follow — the same tradeoff internal/api/entities.go already made for its source/sink/connector route registration. Connectors have no type-specific fields at all (source_id/sink_id are plain selects, not a type switch), so their section below has no typeFields analogue — otherwise it follows the same form-view/toModel/handler shape.
Package ui is beacon's offline, server-rendered web UI mounted at /. Every asset it serves (htmx, the CEL autocomplete enhancement, and the compiled Tailwind/Basecoat stylesheet) is embedded in the binary via go:embed — beacon is an offline gateway appliance, so the UI must render with no network access beyond the browser talking to beacon itself. See assets/README.md for the asset inventory and internal/ui/styles/app.css for the theme source.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Handler ¶
func Handler(svc *config.Service, reg *stats.Registry, statuses func() []supervisor.Status, devices func() []bus.DeviceInfo, version string, log *slog.Logger, runtimeInfo ...RuntimeInfo) http.Handler
Handler returns beacon's web UI. svc, reg, and statuses are threaded through for the pages that use them: the Sources and Sinks pages read and write through svc and read live component state through statuses; the Connectors pages read and write through svc and read live per-connector counters/rates through reg (see forms.go's "--- Connectors ---" section); the dashboard (see dashboard.go) reads through svc, reg, AND statuses together — its DAG uses reg for rates/queue depth the same way the Connectors page does, its source/sink nodes use statuses the same way Sources/Sinks do, and a connector node's error badge uses statuses too (a connector has no reg-based error signal of its own).
version is beacon's own build version (see internal/app.Options.Version). Release builds use it as every vendored asset URL's "?v=" cache-busting query parameter: assets are served with a one-year immutable Cache-Control (see withImmutableCache), so without a cache-buster a binary upgrade that re-vendors an asset would keep serving browsers their stale cached copy. Development builds usually pass "dev", so assetCacheVersion replaces that non-unique value with a hash of the embedded UI assets; otherwise `go run` iterations would keep reusing /assets/app.css?v=dev while the browser quite correctly holds onto its immutable cached copy.
A nil log defaults to slog.Default(), the same convention as api.New and config.NewService; render failures are logged through it (see render.go).
The returned handler is an *http.ServeMux serving root-level UI routes such as GET /dashboard and GET /sources, plus GET /assets/. internal/app mounts it as the "/" fallback after registering the API, MCP, health, and metrics endpoints. sameOriginGuard protects its state-changing routes.
Types ¶
type RuntimeInfo ¶
type RuntimeInfo struct {
Inventory *inventory.Registry
CANDetails func() []sysinfo.CANInterface
}