Custom widget
Custom widgets let you run your own plugin's UI directly inside Port dashboards and entity pages. A plugin is a self-contained HTML file, write it in your IDE, build it, and upload it to Port using the Port plugins CLI. Uploaded plugins are listed in the Plugins Manager. For details, see Plugins.
Only plugins uploaded to your organization are listed in the Plugins Manager and available when you create a custom widget. Upload them with the Port plugins CLI.
Why use custom widgets?
When built-in widgets aren't enough - a deployment calendar, an incident timeline, a production readiness panel - custom widgets let you bring those interfaces directly into Port, leveraging Port's hosting, authentication, secured environment, and rich context.
Widget properties
| Field | Type | Description | Default | Required |
|---|---|---|---|---|
Title | string | Custom widget title. | — | true |
Icon | string | Custom widget icon. | — | false |
Description | string | Custom widget description. | — | false |
Plugin | string | The plugin to display. Choose from your organization's uploaded plugins. | — | true |
Param Values | object | Key-value pairs for the plugin's custom parameters. Each parameter has a type (string, number, boolean, object, array, or blueprint) and a value. Which parameters are required is defined by the plugin's configuration. | — | false |
For blueprint type parameters, use the blueprint's identifier as the value.
UI preview
When creating or editing a custom widget, Port renders a live preview using the real widget context, so you can see how the widget will look before saving.
You can turn on the toggle in the preview section to use development mode. When enabled, it overrides the plugin URL and postMessage URL to localhost:9000 so you can develop and test your plugin locally.
Please note: In development mode, CORS prevents the plugin from sending browser requests to the API.
How Port communicates with your plugin
The widget communicates with the plugin via postMessage. Port sends context and tokens to the plugin, and the plugin can send messages to the Port host when the parent page must perform an action on its behalf.
Port token
Listen for the PORT_TOKEN event to receive an authenticated token for making Port API calls from within the widget:
Plugin data
Port sends context to the plugin via the PLUGIN_DATA event. The payload includes:
- User - the logged-in user's data.
- Page - the page identifier and any filters applied on the page (
identifier,pageFilters). - Entity - on entity pages, an object containing the current entity's data.
- Params - the parameter values configured for the widget.
- Base URL - Port's URL for Port API calls from the plugin (the React SDK exposes this as
portApiBaseUrl). - Theme - optional host theme data (including CSS variables) for styling the plugin to match Port.
How your plugin can communicate with Port
Your plugin can send the following message types to the Port host:
Request token
Send this message when the plugin initializes inside the iframe to request a Port API token from the host. The host responds with the PORT_TOKEN event.
{ "type": "REQUEST_PORT_TOKEN" }
Open URL
Send this message when the plugin needs the host to open a URL in a new tab or at the top level. Use this mechanism instead of window.open(), which Port blocks for security reasons.
{ "type": "OPEN_URL", "data": { "url": "https://example.com" } }
Open AI chat
Open the Port AI side chat with a prefilled prompt. The user sends the message manually. Requires @port-labs/plugins-sdk 0.2.0+ on the plugin and a matching Port host.
{
"type": "OPEN_AI_CHAT",
"data": {
"body": "Which services are unhealthy?",
"chatMode": "ask"
}
}
chatMode is optional (possible values: ask, build, or plan. Defaults to ask). See chat modes for details.
Show run-action dialog
Open the Port run-action modal for a self-service action. Requires @port-labs/plugins-sdk 0.3.0+.
{
"type": "SHOW_RUN_ACTION_DIALOG",
"data": {
"actionIdentifier": "my_action",
"entityIdentifier": "entity-id",
"initialData": { "property": "value" }
}
}
entityIdentifier and initialData are optional. If entityIdentifier is omitted, the host uses the current page entity when available.
Show run-workflow dialog
Open the Port workflow trigger modal. Requires @port-labs/plugins-sdk 0.3.0+.
{
"type": "SHOW_RUN_WORKFLOW_DIALOG",
"data": {
"workflowIdentifier": "my_workflow",
"triggerIdentifier": "my_trigger",
"initialData": { "inputKey": "value" }
}
}
triggerIdentifier and initialData are optional. You can also pass a compound workflow/trigger id in workflowIdentifier (for example my_workflow/my_trigger).
Using Terraform
To add a custom widget with Terraform, include a widget object with type set to custom-widget in the widgets configuration.
See Port's Terraform provider for how to pass widget definitions on your page resource.
Example:
{
"icon": "<YOUR_ICON>",
"pluginId": "<YOUR_PLUGIN_ID>",
"title": "<YOUR_WIDGET_TITLE>",
"description": "<YOUR_DESCRIPTION>",
"paramValues": {
"<PARAM_NAME>": {
"value": <PARAM_VALUE>,
"type": "<PARAM_TYPE>"
}
},
"type": "custom-widget",
"id": "<YOUR_WIDGET_ID>"
}
pluginId, title, type, and id are required (type must be custom-widget).