Native JSON UI for Plugins
Bedrock Server Manager allows plugins to define native UI pages using a simple JSON schema. This eliminates the need for plugin developers to write frontend code (React, HTML, CSS) while still providing a rich, interactive user interface that matches the application’s look and feel.
How it Works
Instead of serving HTML or Jinja2 templates, your plugin defines a FastAPI route that returns a JSON response. This route is tagged with plugin-ui-native. The frontend detects this tag and renders the JSON using a dynamic component renderer.
Basic Example
Here is a minimal example of a plugin that adds a native UI page:
from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse
from bedrock_server_manager import PluginBase
class MyPlugin(PluginBase):
def on_load(self, **kwargs):
self.router = APIRouter(tags=["My Plugin"])
@self.router.get(
"/my_plugin/ui",
response_class=JSONResponse,
name="My Plugin UI",
tags=["plugin-ui-native"] # <--- This tag enables the Native UI renderer
)
async def get_ui(request: Request):
return JSONResponse(content={
"type": "Container",
"children": [
{
"type": "Text",
"props": {"content": "Hello from Native UI!", "variant": "h1"}
},
{
"type": "Card",
"props": {"title": "My Card"},
"children": [
{"type": "Text", "props": {"content": "This is content inside a card."}}
]
}
]
})
def get_fastapi_routers(self, **kwargs):
return [self.router]
Available Components
The JSON schema supports a wide range of components. Each component is an object with type, props, and optional children.
Layout
Container: Main wrapper.
Card: Boxed container with an optional
title.Row: Horizontal layout.
Column: Vertical layout.
Divider: Horizontal line separator.
Typography
Text: Renders text.
content: The text to display.variant:h1,h2,h3, orbody.
Basic Inputs
Input: Text input.
Select: Dropdown menu.
Switch: Toggle switch.
Checkbox: Checkbox input.
Button: Clickable button.
label: Text on the button.icon: Name of the Lucide icon (e.g., “Save”, “Play”).variant:primary,secondary,danger.onClickAction: Action definition (see Actions below).
FileUpload: File selection input.
Display & Media
Badge: Status label.
content: Text.variant:primary,secondary,success,danger,warning.
CodeBlock: Displays code or logs with a copy button.
content: The code/text.title: Optional header.
Image: Displays an image.
Link: External or internal link.
iframe: Embeds external content.
Interactive
Accordion: Collapsible section.
Modal: Dialog popup.
id: Unique ID to control visibility.title: Header text.children: Content inside the modal.
Data & Monitoring
Table: Displays tabular data.
StatCard: Dashboard metric card.
label: Title of the metric.value: The value to display.icon: Icon name.trend:up,down, orneutral.
StatusIndicator: Dot with status text.
status:running(green),stopped(red),warning(orange).
LogViewer: Scrolling log display.
lines: Array of log strings.height: Height in pixels (default 200).
Chart: Data visualization (Area, Line, Bar).
type:area,line,bar.data: Array of data objects.xAxis: Key for the X-axis (e.g., “time”).series: Array of objects defining lines/bars (dataKey,color,name).
Actions
Components like Button can trigger actions via the onClickAction prop.
API Call
Sends a POST request to a backend endpoint.
{
"type": "api_call",
"endpoint": "/api/my_plugin/submit",
"includeFormState": true, // Sends current input values
"refresh": true, // Refreshes the UI after success
"closeModal": true // Closes any open modal
}
Modal Control
Opens or closes a modal by ID.
{
"type": "open_modal",
"modalId": "my_modal_id"
}
{
"type": "close_modal"
}
Real-time Updates (WebSockets)
You can subscribe to WebSocket topics to update components like Charts, StatCards, and LogViewers in real-time.
Define Subscriptions: Add
websocketSubscriptionsto the root of your JSON response.{ "websocketSubscriptions": ["my_plugin:stats", "server_log:{server}"], "type": "Container", ... }
{server}is automatically replaced with the currently selected server name.
Bind Components: Pass
socketTopicto components.Chart: Appends new data points from the socket message to the chart history.
LogViewer: Appends new log lines.
StatCard: Updates the value. Use
dataKeyto specify which field in the socket message to display (e.g.,process_info.cpu_percent).
{ "type": "StatCard", "props": { "label": "CPU", "socketTopic": "my_plugin:stats", "dataKey": "cpu_usage" } }
Icons
The system uses Lucide React icons. You can use any valid Lucide icon name in props like icon. Common icons include: Activity, AlertCircle, CheckCircle2, Info, Terminal, Save, Trash2, Plus, X, Upload, Download, Play, Square, RotateCcw.