HCL Component Reference

View plugins describe their UI using HCL component blocks. The platform parses the HCL and renders it to HTML using its built-in component library. Plugins never produce HTML or JavaScript directly.

Syntax

component "unique-name" {
  type = "component-type"
  # attributes specific to the component type
}

Components can be nested inside other components:

component "container" {
  type  = "section"
  title = "My Section"

  component "child" {
    type    = "text"
    content = "Nested inside the section."
  }
}

Components

text

Displays a paragraph of text.

Attribute Type Default Description
content string "" The text to display
style string "body" Text style: "body", "heading", "muted", "code"

Styles:

Style Appearance
body Standard gray text (14px)
heading Large white bold text (18px)
muted Small gray text (14px, dimmed)
code Monospace emerald text (12px)
component "title" {
  type    = "text"
  content = "Dashboard"
  style   = "heading"
}

chat

A full WebSocket-powered chat interface. Connects to the plugin's stream endpoint for real-time bidirectional communication.

Attribute Type Default Description
stream string "" WebSocket stream URL path (e.g. /api/v1/workspaces/{id}/views/{plugin}/stream)
placeholder string "Type a message..." Input placeholder text
button_label string "Send" Submit button label
component "conversation" {
  type         = "chat"
  stream       = "/api/v1/workspaces/abc-123/views/my-plugin/stream"
  placeholder  = "Ask me anything..."
  button_label = "Send"
}

The chat component:


form

A form that submits data via fetch to a plugin's HandleRoute endpoint.

Attribute Type Default Description
action string "#" URL to submit the form to
method string "POST" HTTP method (POST, PUT, etc.)
title string "" Optional form heading
submit_label string "Submit" Submit button text

Children: field blocks

component "create-task" {
  type         = "form"
  action       = "/api/v1/workspaces/abc-123/views/my-plugin/routes/tasks"
  method       = "POST"
  title        = "Create Task"
  submit_label = "Create"

  field "title" {
    type        = "text"
    label       = "Task Title"
    placeholder = "Enter a title..."
    required    = true
  }

  field "priority" {
    type  = "select"
    label = "Priority"

    option "low" {
      value = "low"
      label = "Low"
    }
    option "high" {
      value = "high"
      label = "High"
    }
  }

  field "description" {
    type        = "textarea"
    label       = "Description"
    placeholder = "Optional details..."
  }
}

Field Types

Type Description
text Single-line text input
textarea Multi-line text input
select Dropdown with option children
email Email input
password Password input
number Numeric input

Field Attributes

Attribute Type Default Description
type string "text" Input type
label string field name Display label
placeholder string "" Placeholder text
required string "false" "true" to make required

Option Attributes (for select fields)

Attribute Type Default Description
value string option name Form value
label string option name Display label

table

A data table that fetches rows from a JSON API endpoint.

Attribute Type Default Description
source string "" URL to fetch JSON data from
refresh string "" Auto-refresh interval (e.g. "5s", "1m")

Children: column blocks

component "task-list" {
  type    = "table"
  source  = "/api/v1/workspaces/abc-123/views/my-plugin/routes/tasks"
  refresh = "10s"

  column "id" {
    label = "ID"
  }

  column "title" {
    label = "Title"
  }

  column "status" {
    label = "Status"
  }
}

The source URL should return JSON in one of these formats:

[{"id": "1", "title": "Task 1", "status": "open"}]

or:

{"items": [{"id": "1", "title": "Task 1", "status": "open"}]}

Column names must match the JSON object keys.

Column Attributes

Attribute Type Default Description
label string column name Column header text

stat-group

A row of metric/stat cards.

Children: stat blocks

component "metrics" {
  type = "stat-group"

  stat "total" {
    label = "Total Tasks"
    value = "42"
  }

  stat "completed" {
    label = "Completed"
    value = "38"
  }

  stat "pending" {
    label = "Pending"
    value = "4"
  }
}

Stat Attributes

Attribute Type Default Description
label string stat name Small label text
value string "-" Large value text

code

Displays a code block with syntax highlighting-ready formatting.

Attribute Type Default Description
content string "" The code to display
component "example" {
  type    = "code"
  content = "curl -X GET https://api.example.com/tasks"
}

alert

A colored notification banner.

Attribute Type Default Description
message string "" Alert text
level string "info" Alert level: "info", "warning", "error", "success"

Level colors:

Level Color
info Blue
warning Amber
error Red
success Emerald
component "notice" {
  type    = "alert"
  message = "Plugin connected successfully."
  level   = "success"
}

section

A container card that groups other components.

Attribute Type Default Description
title string "" Optional section heading

Children: Any component blocks

component "config-section" {
  type  = "section"
  title = "Configuration"

  component "status" {
    type    = "text"
    content = "All systems operational."
  }

  component "hint" {
    type    = "alert"
    message = "Changes take effect after restart."
    level   = "warning"
  }
}

button-group

A row of action buttons that trigger API calls.

Children: button blocks

component "actions" {
  type = "button-group"

  button "refresh" {
    label  = "Refresh"
    action = "/api/v1/workspaces/abc-123/views/my-plugin/routes/refresh"
    method = "POST"
    style  = "default"
  }

  button "deploy" {
    label  = "Deploy"
    action = "/api/v1/workspaces/abc-123/views/my-plugin/routes/deploy"
    method = "POST"
    style  = "primary"
  }

  button "reset" {
    label  = "Reset"
    action = "/api/v1/workspaces/abc-123/views/my-plugin/routes/reset"
    method = "POST"
    style  = "danger"
  }
}

Button Attributes

Attribute Type Default Description
label string button name Button text
action string "#" URL to call when clicked
method string "POST" HTTP method
style string "default" Button style: "default", "primary", "danger"

Button styles:

Style Appearance
default Gray border, gray text
primary Emerald border, emerald text
danger Red border, red text

html

Raw HTML escape hatch. Use sparingly — prefer structured components.

Attribute Type Default Description
content string "" Raw HTML string (injected directly, not escaped)
component "custom" {
  type    = "html"
  content = "<div class='my-custom-widget'>Custom content</div>"
}

Warning: The content is injected as raw HTML. Ensure you trust the source.


searchable-select

A dropdown with a built-in text filter. Used automatically by the Settings page for fields with options or api_source, and available in form components.

Attribute Type Default Description
name string required Form field name
options string "" Comma-separated static options
api_source string "" URL for dynamic options (fetched on keystroke)
value string "" Currently selected value
placeholder string "Select..." Placeholder text

Static options are filtered client-side on keystroke. API options (api_source) trigger a debounced GET {url}?q={query} on keystroke.

Expected API response format:

[{"value": "us-east-1", "label": "US East (N. Virginia)"}]

The platform proxies API select requests through /api/v1/settings/{plugin}/options/{field}?q= to avoid CORS issues.


Composing Views

A typical view combines multiple components:

component "header" {
  type    = "text"
  content = "Task Manager"
  style   = "heading"
}

component "stats" {
  type = "stat-group"

  stat "open" {
    label = "Open"
    value = "12"
  }

  stat "closed" {
    label = "Closed"
    value = "45"
  }
}

component "notice" {
  type    = "alert"
  message = "3 tasks are overdue."
  level   = "warning"
}

component "tasks" {
  type   = "table"
  source = "/api/v1/workspaces/ws-123/views/task-mgr/routes/tasks"

  column "title" {
    label = "Title"
  }

  column "status" {
    label = "Status"
  }

  column "assignee" {
    label = "Assignee"
  }
}

component "actions" {
  type = "button-group"

  button "sync" {
    label  = "Sync Tasks"
    action = "/api/v1/workspaces/ws-123/views/task-mgr/routes/sync"
    method = "POST"
    style  = "primary"
  }
}