Plugins
A plugin is a self-contained web UI, built from HTML, JavaScript, or a framework such as React, that you develop locally and upload to Port. Plugins power custom widgets that render inside dashboards and entity pages using the same catalog data and permissions as the rest of the platform.
You develop and build the plugin in your usual toolchain (for example VS Code, Cursor, or WebStorm), then upload a single compiled HTML file. Port hosts that file for you, there is no separate infrastructure to run. When a custom widget renders, Port serves the plugin, injects authentication, and passes context such as entity data, dashboard filters, page context, and user identity, so your code can call Port APIs safely.
Administrators upload, list, update, and delete plugins using the Port plugins CLI. You can define custom parameters (Params), those fields appear when someone creates or edits a custom widget, which lets a single plugin power different widgets. For example, different blueprints or date properties for a shared calendar-style UI.
Get started with plugin development
Sample repository
Use the port-plugin-sample repository on GitHub as a starting point. It shows a minimal plugin built with React and TypeScript, wired to @port-labs/plugins-sdk so you can copy patterns instead of bootstrapping from scratch.
When you run a production build in that project, the output is dist/index.html, a single self-contained file with inlined JavaScript and CSS. Upload that file with the Port plugins CLI.
Plugins SDK
@port-labs/plugins-sdk bridges postMessage between your plugin code and the Port web app. When Port serves your plugin, the host passes context such as the user, page, params, entity, optional theme data, and a JWT for Port API calls. On PLUGIN_DATA, the host sends baseUrl, and the React hook exposes it as portApiBaseUrl.
The package includes mergePageFilters for entity search with dashboard page filters, React helpers from @port-labs/plugins-sdk/react, and framework-agnostic patterns. For full API detail, see the plugins SDK package on npm.
Port blocks window.open() for plugins, so you cannot use it to open new windows or tabs from plugin code. If you need links, navigation, or similar behavior, use @port-labs/plugins-sdk 0.1.1 or newer.
Constraints when building plugins
Do not include API keys, passwords, or tokens in widget content or in your uploaded plugin file. They may be exposed to other users or widgets in your organization.
Content security policy (CSP)
Port serves your plugin inside the browser under a content security policy (CSP) that limits what the page can load and connect to. Design your bundle and network usage to stay within these rules.
-
Scripts and styles - Scripts and styles load only from the plugin origin.
'unsafe-inline'is allowed, so a single HTML file with inlined JavaScript and CSS works as expected. -
Asset loading (
default-src) - Thedefault-srcdirective is set to'self',https://*.getport.io, andhttps://*.port.io. This covers<img>,<video>,<audio>,<source>,@font-face, and similar resource types - asset URLs on those origins load, and every other host is blocked. -
Self-contained assets - To keep your bundle self-contained, you can embed images, fonts, and media directly in the plugin HTML file.
-
Blocked elements - Port blocks common embedding patterns that bypass normal resource loading rules:
object-src 'none'- Blocks<object>and<embed>elements, including common patterns for embedding external players or documents.frame-src 'none'- Blocks<iframe>, so you cannot embed another site's page, player, or document inside the plugin UI.
-
Network requests (
connect-src) -connect-srclimits scripted network APIs (fetch,XMLHttpRequest, WebSockets, and similar) to'self',https://*.getport.io, andhttps://*.port.io. Calls from the plugin to other hosts - for example, third-party analytics or public REST APIs - are blocked. -
Framing (
frame-ancestors) -frame-ancestorsallows the Port web app (on*.getport.ioand*.port.io) to embed your plugin. Arbitrary third-party sites cannot frame it. -
Trusted types -
require-trusted-types-for 'script'enforces trusted types for script-related DOM sinks. If a library assigns raw strings where the browser expects a trusted type, you may need to adjust usage or dependencies.
Technical limitations
- Each plugin artifact is one self-contained HTML file, multi-file bundles or separate asset uploads are not supported.
- The uploaded file must be 10 MB or smaller.
Port plugins CLI
The Port plugins CLI (@port-labs/port-plugins-cli) uploads and manages plugins from your terminal or from CI.
Install the CLI:
npm install -g @port-labs/port-plugins-cli
For full install steps, commands, authentication, configuration, and plugin metadata limits, see the @port-labs/port-plugins-cli package on npm.
Authenticate the Port plugins CLI with a client ID and client secret, or with an access token. Admin permissions are required to upload and manage plugins. For where to find your credentials, see Find your Port credentials.
Using the plugins in Port
To use a plugin in a dashboard or entity page, see Custom widget.
Plugins manager
Admins can open Plugins Manager in Builder to manage plugins for your organization:
- Navigate to the Builder page.
- Click on the Plugins Manager in the left sidebar to manage your uploaded plugins.
The Plugins Manager lists all plugins uploaded to your organization, showing each plugin's identifier, title, description, size, creator, and the custom parameters it exposes (Params). From here, admins can review available plugins before wiring one into a custom widget.
API reference
Use these Port API endpoints to upload, list, update, and delete plugins programmatically: