Skip to content

Commit 8bd8224

Browse files
committed
feat(dashboard): expand documentation and features for contributor system and Go-JS bridge
- Introduced new documentation for the Go-JS bridge, detailing how to call Go functions from the dashboard UI using Alpine.js. - Added comprehensive guides on the contributor system, including local and remote contributors, manifest structure, and registration processes. - Enhanced the configuration documentation to include all available options and their descriptions. - Updated the main dashboard documentation to reflect the new extensibility features and improved user experience. - Added a README for the dashboard extension, outlining its capabilities and providing a quick start guide. These changes significantly enhance the usability and clarity of the dashboard extension, making it easier for developers to implement and extend its functionality.
1 parent 64a9f57 commit 8bd8224

8 files changed

Lines changed: 1237 additions & 231 deletions

File tree

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
title: Bridge
3+
description: Go-JS bridge for calling Go functions from the dashboard UI via Alpine.js
4+
---
5+
6+
import { Callout } from 'fumadocs-ui/components/callout';
7+
8+
## Overview
9+
10+
The dashboard includes a **Go-JS bridge** powered by ForgeUI's bridge system. It enables the dashboard UI to call Go functions directly from the browser using Alpine.js magic helpers (`$go`, `$goBatch`, `$goStream`) or the `ForgeBridge` JavaScript client.
11+
12+
The bridge is enabled by default (`EnableBridge: true`) and provides 8 built-in dashboard functions. Extensions can register custom functions to expose any Go logic to the dashboard UI.
13+
14+
## How It Works
15+
16+
1. Go functions are registered with the bridge (server-side)
17+
2. The browser calls functions via `POST {basePath}/bridge/call` or SSE streaming via `GET {basePath}/bridge/stream/`
18+
3. Alpine.js magic helpers abstract the HTTP calls into simple async functions
19+
4. Responses are JSON-encoded and returned to the browser
20+
21+
## Built-in Functions
22+
23+
The dashboard registers these functions automatically:
24+
25+
| Function | Parameters | Returns | Cache | Description |
26+
|---|---|---|---|---|
27+
| `dashboard.getOverview` | none | `*collector.OverviewData` | 10s | Application overview: health, uptime, metrics |
28+
| `dashboard.getHealth` | none | `*collector.HealthData` | 5s | Health check results |
29+
| `dashboard.getMetrics` | none | `*collector.MetricsData` | 10s | Current metric values |
30+
| `dashboard.getServices` | none | `[]collector.ServiceInfo` | 10s | Registered services list |
31+
| `dashboard.getServiceDetail` | `{name: string}` | `*collector.ServiceDetail` | none | Detailed info for a specific service |
32+
| `dashboard.getHistory` | none | `collector.HistoryData` | 5s | Historical data points |
33+
| `dashboard.getMetricsReport` | none | `*collector.MetricsReport` | 10s | Comprehensive metrics report |
34+
| `dashboard.refresh` | none | `*collector.OverviewData` | none | Force data refresh and return overview |
35+
36+
## Registering Custom Functions
37+
38+
### Via Extension API
39+
40+
```go
41+
dashExt := ext.(*dashboard.Extension)
42+
43+
err := dashExt.RegisterBridgeFunction("myapp.getUsers", func(ctx bridge.Context, params GetUsersParams) (*UsersResult, error) {
44+
// Query database, call service, etc.
45+
users, err := userService.List(ctx.Context(), params.Limit)
46+
if err != nil {
47+
return nil, err
48+
}
49+
return &UsersResult{Users: users}, nil
50+
}, bridge.WithDescription("List application users"))
51+
```
52+
53+
### Via DashboardBridge
54+
55+
```go
56+
db := dashExt.DashboardBridge()
57+
58+
err := db.Register("myapp.getStats", func(ctx bridge.Context, params EmptyParams) (*Stats, error) {
59+
return collectStats(), nil
60+
},
61+
bridge.WithDescription("Get application statistics"),
62+
bridge.WithFunctionCache(10 * time.Second),
63+
)
64+
```
65+
66+
### Function Signature
67+
68+
Bridge function handlers follow the pattern:
69+
70+
```go
71+
func(ctx bridge.Context, params T) (R, error)
72+
```
73+
74+
- `ctx` -- bridge context with request metadata and a `Context()` method for the standard `context.Context`
75+
- `params T` -- any struct that can be JSON-decoded from the request. Use `struct{}` for no parameters.
76+
- `R` -- any type that can be JSON-encoded as the response
77+
- `error` -- returned errors are sent to the client as error responses
78+
79+
### Function Options
80+
81+
| Option | Description |
82+
|---|---|
83+
| `bridge.WithDescription(desc)` | Human-readable description of the function |
84+
| `bridge.WithFunctionCache(ttl)` | Cache responses for the given duration. Subsequent calls within the TTL return the cached result. |
85+
86+
## JavaScript Client Usage
87+
88+
### Alpine.js Magic Helpers
89+
90+
In any Alpine.js component within the dashboard, use the `$go` magic helper:
91+
92+
```javascript
93+
// Single function call
94+
const overview = await $go('dashboard.getOverview')
95+
96+
// With parameters
97+
const detail = await $go('dashboard.getServiceDetail', { name: 'api-gateway' })
98+
99+
// Custom function
100+
const users = await $go('myapp.getUsers', { limit: 50 })
101+
```
102+
103+
### Batch Calls
104+
105+
Call multiple functions in a single HTTP request:
106+
107+
```javascript
108+
const [overview, health, metrics] = await $goBatch([
109+
{ fn: 'dashboard.getOverview' },
110+
{ fn: 'dashboard.getHealth' },
111+
{ fn: 'dashboard.getMetrics' },
112+
])
113+
```
114+
115+
### Streaming
116+
117+
For long-running operations, use streaming over SSE:
118+
119+
```javascript
120+
await $goStream('myapp.streamLogs', { service: 'api' }, (chunk) => {
121+
console.log('received:', chunk)
122+
})
123+
```
124+
125+
## Bridge Endpoints
126+
127+
| Method | Path | Description |
128+
|---|---|---|
129+
| POST | `{basePath}/bridge/call` | Call a bridge function. Request body: `{"fn": "name", "params": {...}}`. Response: `{"data": ..., "error": null}` |
130+
| GET | `{basePath}/bridge/stream/` | Streaming responses via SSE |
131+
132+
These endpoints are served automatically by ForgeUI when the bridge is enabled.
133+
134+
<Callout type="info">
135+
CSRF protection at the forge router level handles security for bridge calls. The bridge itself has CSRF disabled (`bridge.WithCSRF(false)`) to avoid double-checking.
136+
</Callout>
137+
138+
## Disabling the Bridge
139+
140+
```go
141+
dashboard.NewExtension(
142+
dashboard.WithBridge(false),
143+
)
144+
```
145+
146+
When disabled, `DashboardBridge()` returns `nil`, `RegisterBridgeFunction()` returns an error, and bridge endpoints are not mounted.
Lines changed: 196 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,221 @@
11
---
22
title: Configuration
3-
description: Config reference, YAML example, and options for Dashboard
3+
description: Full config reference with all options, YAML example, validation rules, and functional options
44
---
55

6-
## YAML Configuration Example
6+
import { Callout } from 'fumadocs-ui/components/callout';
7+
8+
## YAML Configuration
79

810
```yaml title="config.yaml"
911
extensions:
1012
dashboard:
11-
basePath: "/dashboard"
12-
enableAuth: false
13-
enableRealtime: true
14-
enableExport: true
15-
exportFormats:
13+
# Server
14+
base_path: "/dashboard"
15+
title: "Forge Dashboard"
16+
17+
# Features
18+
enable_realtime: true
19+
enable_export: true
20+
enable_search: true
21+
enable_settings: true
22+
enable_discovery: false
23+
enable_bridge: true
24+
25+
# Data collection
26+
refresh_interval: "30s"
27+
history_duration: "1h"
28+
max_data_points: 1000
29+
30+
# Proxy / Remote contributors
31+
proxy_timeout: "10s"
32+
cache_max_size: 1000
33+
cache_ttl: "30s"
34+
35+
# SSE
36+
sse_keep_alive: "15s"
37+
38+
# Security
39+
enable_csp: true
40+
enable_csrf: true
41+
42+
# Theming
43+
theme: "auto" # "auto", "light", "dark"
44+
custom_css: ""
45+
46+
# Discovery
47+
discovery_tag: "forge-dashboard-contributor"
48+
discovery_poll_interval: "60s"
49+
50+
# Export
51+
export_formats:
1652
- "json"
1753
- "csv"
1854
- "prometheus"
19-
refreshInterval: "30s"
20-
historyDuration: "1h"
21-
maxDataPoints: 1000
22-
theme: "auto" # "auto", "light", "dark"
23-
title: "Forge Dashboard"
2455
```
2556
2657
The extension loads config from `extensions.dashboard` first, falling back to `dashboard`.
2758

2859
## Programmatic Configuration
2960

61+
All options use the functional options pattern:
62+
3063
```go
3164
ext := dashboard.NewExtension(
3265
dashboard.WithBasePath("/admin/dashboard"),
66+
dashboard.WithTitle("Admin Panel"),
3367
dashboard.WithRealtime(true),
3468
dashboard.WithExport(true),
35-
dashboard.WithRefreshInterval(15 * time.Second),
36-
dashboard.WithHistory(2*time.Hour, 2000),
69+
dashboard.WithSearch(true),
70+
dashboard.WithSettings(true),
71+
dashboard.WithBridge(true),
72+
dashboard.WithRefreshInterval(30 * time.Second),
73+
dashboard.WithHistoryDuration(2 * time.Hour),
74+
dashboard.WithMaxDataPoints(2000),
75+
dashboard.WithTheme("auto"),
76+
dashboard.WithCSP(true),
77+
dashboard.WithCSRF(true),
3778
)
3879
```
3980

40-
## Config Struct Reference
41-
42-
| Field | Type | Default | Description |
43-
|---|---|---|---|
44-
| `BasePath` | `string` | `"/dashboard"` | HTTP base path |
45-
| `EnableAuth` | `bool` | `false` | Require authentication |
46-
| `EnableRealtime` | `bool` | `true` | Enable WebSocket updates |
47-
| `EnableExport` | `bool` | `true` | Enable data export endpoints |
48-
| `ExportFormats` | `[]string` | `["json","csv","prometheus"]` | Available export formats |
49-
| `RefreshInterval` | `time.Duration` | `30s` | Real-time update interval |
50-
| `HistoryDuration` | `time.Duration` | `1h` | Metric history window |
51-
| `MaxDataPoints` | `int` | `1000` | Max data points in history |
52-
| `Theme` | `string` | `"auto"` | Dashboard theme |
53-
| `Title` | `string` | `"Forge Dashboard"` | Dashboard page title |
81+
## Config Reference
82+
83+
### Server
84+
85+
| Field | Type | Default | Option | Description |
86+
|---|---|---|---|---|
87+
| `BasePath` | `string` | `"/dashboard"` | `WithBasePath()` | HTTP base path for all dashboard routes |
88+
| `Title` | `string` | `"Forge Dashboard"` | `WithTitle()` | Page title shown in browser tab and header |
89+
90+
### Features
91+
92+
| Field | Type | Default | Option | Description |
93+
|---|---|---|---|---|
94+
| `EnableRealtime` | `bool` | `true` | `WithRealtime()` | SSE real-time event stream |
95+
| `EnableExport` | `bool` | `true` | `WithExport()` | Data export endpoints (JSON, CSV, Prometheus) |
96+
| `EnableSearch` | `bool` | `true` | `WithSearch()` | Federated cross-contributor search |
97+
| `EnableSettings` | `bool` | `true` | `WithSettings()` | Aggregated settings page |
98+
| `EnableDiscovery` | `bool` | `false` | `WithDiscovery()` | Auto-discover remote contributors via service discovery |
99+
| `EnableBridge` | `bool` | `true` | `WithBridge()` | Go-JS bridge function system |
100+
101+
### Data Collection
102+
103+
| Field | Type | Default | Option | Description |
104+
|---|---|---|---|---|
105+
| `RefreshInterval` | `time.Duration` | `30s` | `WithRefreshInterval()` | How often to collect metrics and health data |
106+
| `HistoryDuration` | `time.Duration` | `1h` | `WithHistoryDuration()` | How long to retain historical data points |
107+
| `MaxDataPoints` | `int` | `1000` | `WithMaxDataPoints()` | Maximum number of data points in history |
108+
109+
### Proxy / Remote Contributors
110+
111+
| Field | Type | Default | Option | Description |
112+
|---|---|---|---|---|
113+
| `ProxyTimeout` | `time.Duration` | `10s` | `WithProxyTimeout()` | Timeout for requests to remote contributors |
114+
| `CacheMaxSize` | `int` | `1000` | `WithCacheMaxSize()` | Max entries in the fragment proxy LRU cache |
115+
| `CacheTTL` | `time.Duration` | `30s` | `WithCacheTTL()` | Time-to-live for cached remote fragments |
116+
117+
### SSE
118+
119+
| Field | Type | Default | Option | Description |
120+
|---|---|---|---|---|
121+
| `SSEKeepAlive` | `time.Duration` | `15s` | `WithSSEKeepAlive()` | Interval for SSE keep-alive pings |
122+
123+
### Security
124+
125+
| Field | Type | Default | Option | Description |
126+
|---|---|---|---|---|
127+
| `EnableCSP` | `bool` | `true` | `WithCSP()` | Add Content-Security-Policy headers |
128+
| `EnableCSRF` | `bool` | `true` | `WithCSRF()` | CSRF token protection for forms and bridge calls |
129+
130+
### Theming
131+
132+
| Field | Type | Default | Option | Description |
133+
|---|---|---|---|---|
134+
| `Theme` | `string` | `"auto"` | `WithTheme()` | Theme mode: `auto`, `light`, or `dark` |
135+
| `CustomCSS` | `string` | `""` | `WithCustomCSS()` | Custom CSS injected into the dashboard |
136+
137+
### Discovery
138+
139+
| Field | Type | Default | Option | Description |
140+
|---|---|---|---|---|
141+
| `DiscoveryTag` | `string` | `"forge-dashboard-contributor"` | `WithDiscoveryTag()` | Service discovery tag to filter contributors |
142+
| `DiscoveryPollInterval` | `time.Duration` | `60s` | `WithDiscoveryPollInterval()` | How often to poll for new remote contributors |
143+
144+
### Export
145+
146+
| Field | Type | Default | Option | Description |
147+
|---|---|---|---|---|
148+
| `ExportFormats` | `[]string` | `["json","csv","prometheus"]` | `WithExportFormats()` | Supported export formats |
149+
150+
### Internal
151+
152+
| Field | Type | Default | Option | Description |
153+
|---|---|---|---|---|
154+
| `RequireConfig` | `bool` | `false` | `WithRequireConfig()` | Require config from ConfigManager (fail if missing) |
155+
156+
## Functional Options
157+
158+
All options are available as `ConfigOption` functions:
159+
160+
```go
161+
// Server
162+
dashboard.WithBasePath(path string)
163+
dashboard.WithTitle(title string)
164+
165+
// Features
166+
dashboard.WithRealtime(enabled bool)
167+
dashboard.WithExport(enabled bool)
168+
dashboard.WithSearch(enabled bool)
169+
dashboard.WithSettings(enabled bool)
170+
dashboard.WithDiscovery(enabled bool)
171+
dashboard.WithBridge(enabled bool)
172+
173+
// Data collection
174+
dashboard.WithRefreshInterval(interval time.Duration)
175+
dashboard.WithHistoryDuration(duration time.Duration)
176+
dashboard.WithMaxDataPoints(maxPoints int)
177+
178+
// Proxy
179+
dashboard.WithProxyTimeout(timeout time.Duration)
180+
dashboard.WithCacheMaxSize(size int)
181+
dashboard.WithCacheTTL(ttl time.Duration)
182+
183+
// SSE
184+
dashboard.WithSSEKeepAlive(interval time.Duration)
185+
186+
// Security
187+
dashboard.WithCSP(enabled bool)
188+
dashboard.WithCSRF(enabled bool)
189+
190+
// Theming
191+
dashboard.WithTheme(theme string)
192+
dashboard.WithCustomCSS(css string)
193+
194+
// Discovery
195+
dashboard.WithDiscoveryTag(tag string)
196+
dashboard.WithDiscoveryPollInterval(interval time.Duration)
197+
198+
// Export
199+
dashboard.WithExportFormats(formats []string)
200+
201+
// Advanced
202+
dashboard.WithConfig(config Config) // Set complete config
203+
dashboard.WithRequireConfig(required bool) // Require config from ConfigManager
204+
```
205+
206+
## Validation Rules
207+
208+
The config is validated during `Register()`. The following constraints apply:
209+
210+
| Field | Rule |
211+
|---|---|
212+
| `BasePath` | Must not be empty |
213+
| `RefreshInterval` | Minimum 1 second |
214+
| `MaxDataPoints` | Minimum 10 |
215+
| `Theme` | Must be `light`, `dark`, or `auto` |
216+
| `ProxyTimeout` | Minimum 1 second |
217+
| `CacheMaxSize` | Must not be negative |
218+
219+
<Callout type="warn">
220+
If validation fails, `Register()` returns an error and the dashboard will not start.
221+
</Callout>

0 commit comments

Comments
 (0)