360 Secure SkillHub
360 安全技能中心

port-dashboards

Port 仪表板构建参考 Skill:说明 12 种 widget 类型、12 列行布局约束、侧边栏位置、私有页面创建规则与 dataset 过滤语法,并提供分步流程与常见错误排查。可选通过 Port MCP 工具或 Pages API 创建、更新页面,无需实时账户也能生成正确载荷。

port-labs
热度 0.00
最近更新 2026-10-19 00:22:14
分类:数据依赖:MCP 服务 / 第三方 API应用场景:报告撰写 / 工作流 / 模板

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add port-labs/port-skills/port-dashboards
Metadata
name
port-dashboards
description
Build and update Port dashboard pages: widgets (table, number chart, pie chart, bar chart, multi-line chart, markdown, iframe, links, action card, action-runs table, entity details, AI agent), the 12-column row layout, sidebar placement, and private-page rules. Covers dataset filter syntax so a widget shows the entities you expect instead of an empty or wrong result. Use when asked to "build a Port dashboard", "add a widget to a dashboard page", "create a number chart / pie chart / table widget in Port", "why is my Port widget empty", "make this dashboard page private", or "where should this dashboard go in the sidebar". For building a custom plugin widget (your own React iframe), use the nested `port-dashboard-plugins` skill instead.
license
MIT
compatibility
Claude Code, Cursor, Codex CLI, GitHub Copilot
metadata
{"version":"1.0.0","author":"port-labs","repository":"https://github.com/port-labs/port-skills","tags":"port,dashboards,widgets,reference","summary":"Build Port dashboard pages with widgets, layout, and permissions"}

Port dashboard pages

A Port dashboard page is a sidebar entry made of one or more widgets (tables, charts, markdown, links, and more) arranged in a 12-column grid. This skill is reference-only: static knowledge about widget schemas, the layout grid, sidebar placement, and dataset filter syntax, drawn from Port's dashboard page schema and public docs. It doesn't need a live Port account or MCP server to produce a correct dashboard payload, only a real account to actually create the page.

Out of scope: building your own custom-code widget (a React/TypeScript iframe plugin uploaded via port-plugins-cli) is the nested port-dashboard-plugins skill, not this one. Blueprint and property modeling (what a dataset can filter on) is owned by the port-blueprints skill; this skill only covers how those properties map onto widget and dataset fields. The full search rule grammar (all operators, and/or/not nesting) is Port's Search and query syntax; this skill covers the subset relevant to widget datasets. Who can view or edit a page once it exists, including private pages shared with specific users or teams, is the port-permissions skill's page-permissions reference, not this one; this skill only covers a private page's own creation and visibility mechanics (see Step 5).

Skill class

Reference skill: the widget schemas, grid rules, and dataset syntax below are static and enough to hand-author a correct dashboard JSON payload. If the Port MCP server is connected, its dashboard tools (upsert_dashboard_page, upsert_widget, get_page, get_sidebar, load_widget_schema, list_entities, list_blueprints) are an optional enhancement: they create the page for you and let you sample real entities to validate a dataset before saving. Without them, use the fallback in every step below: the Port UI's dashboard editor, or the Pages API / Swagger directly.

Prerequisites

  • Go over the port-getting-started skill first if this is your first time working with Port.
  • The blueprint(s) the dashboard's widgets will query already exist, with the properties you plan to filter, group, or chart on.
  • Optional: the Port MCP server connected in your agent, for live dataset validation and one-shot page creation (see Skill class above). Without it, use the Port UI or the Pages API with a client_id/client_secret pair (... menu > Credentials in the Port app). Search search_port_knowledge_sources for anything this skill doesn't cover.

Step 1 - Decide sidebar placement

Precondition: a new dashboard page needs a home in the sidebar. Action: if MCP is available, call get_sidebar to inspect the existing folder structure before creating the page. If a single folder clearly matches the dashboard's topic, place the page there (parent on the page). If several folders are plausible, ask the user which one they prefer instead of guessing. If nothing matches, place the page at the sidebar root, creating a new folder only when the dashboard starts a new category of its own. Fallback: without MCP, open the Port UI's sidebar and read the folder tree directly, or GET /v1/pages (see references/dashboards.md) to list existing pages and their parent/after fields.

Step 2 - Choose widgets and validate each dataset

Precondition: you know which entities and metrics the dashboard should show. Action: pick one widget type per metric or view from the twelve types in references/dashboards.md, matching the widget to the question ("how many" -> number chart, "trend over time" -> multi-line chart, "browse rows" -> table). For every widget with a dataset, resolve the target blueprint first, then validate the dataset before creating the widget: if MCP is available, run list_entities with the dataset as query, countOnly: true, and a small limit (3-5), to confirm the count and that the returned entities look right. If the call errors or the results look wrong, call list_blueprints to check property names, types, and enum values, fix the dataset, and retry. Fallback: without MCP, run the equivalent call yourself: POST /v1/blueprints/{blueprint}/entities/search with the same query body (see references/dashboards.md for the rule grammar and examples), or build the widget in the Port UI and use its built-in entity count/preview before saving.

Step 3 - Lay out the page (12-column grid)

Precondition: the widget set for the page is known. Action: arrange widgets into rows. Every row's column sizes must sum to exactly 12, a row holds at most 4 columns, each column is 3-12 wide, and every row is at least 400px tall. Every layout column's id must match a widget's id exactly, one-to-one. See references/dashboards.md for the layout schema and worked examples. Fallback: the Port UI's drag-and-drop dashboard editor enforces these constraints for you, use it when hand-writing a layout for 6+ widgets gets error-prone.

Step 4 - Create or update the page

Precondition: widgets and layout are ready. Action: if MCP is available, call upsert_dashboard_page with the full identifier, title, widgets, and layout. For 5+ widgets, try the full payload first; if it fails on size or complexity, fall back to an incremental flow: create an empty page (widgets: []), add widgets one at a time with parallel upsert_widget calls, then call get_page and pass its widgets straight through to a final upsert_dashboard_page call that only adds the new layout. Fallback: without MCP, create the page from the Port UI's dashboard editor, or call the Pages API directly: POST /v1/pages (or PATCH /v1/pages/{identifier} if it already exists) with type: "dashboard" and a single root dashboard-widget wrapping your widgets and layout (see references/dashboards.md for the exact envelope Port expects).

Step 5 - Handle private pages correctly

Precondition: the dashboard is personal, not for the whole organization. Action: set visibility: "private" and omit parent and after entirely, whether via MCP or the raw API. Port keeps private pages in a separate sidebar section and appends an owner-specific suffix to the identifier in its response, use that returned identifier for any follow-up edit, widget update, or delete, not the one you sent. Fallback: from the UI, set Visibility to Private when creating the page (the field is read-only after creation for non-admins); an org admin must first grant the create:private-pages scope if the option isn't visible. See references/dashboards.md for the full rules and an example payload.

Examples

Worked, complete JSON payloads for every widget type, a full layout, and the raw API envelope are in references/dashboards.md.

Common pitfalls

Symptom Cause Fix
Widget renders empty or with the wrong entities Dataset filters on the wrong property, wrong blueprint, or a typo'd enum value Validate with list_entities/entities/search before creating the widget, see Step 2
Page creation rejected: "column sizes must sum to 12" A row's column size values don't add to 12 Recompute the row, max 4 columns, each 3-12 wide, see Step 3
Page creation rejected: row height too small A row's height is under 400px Set every row to at least 400
Widget never renders / layout looks broken A layout column's id doesn't match any widget's id Keep widget ids and layout column ids in exact sync
Private page edits silently target the wrong page, or 404 Used the identifier you sent instead of the one Port returned (owner-suffixed) Store and reuse the identifier from the create/get_page response, see Step 5
Private page creation rejected parent or after was set alongside visibility: "private" Omit both fields entirely for private pages
Number chart shows 0 or an error chartType-specific required fields missing (e.g. func/averageOf for aggregateByProperty) Check the per-chartType required fields in references/dashboards.md
Pie/bar chart property rejected property isn't prefixed (property#, relation#, scorecard#, ...) or a meta field ($identifier, $title, $team) Use the prefixed form, see references/dashboards.md

Quick reference

  • Widget types: table-entities-explorer, entity-details, action-card-widget, action-runs-table-widget, links-widget, ai-agent, markdown, iframe-widget, entities-number-chart, entities-pie-chart, bar-chart, multi-line-chart. Full schema for each: references/dashboards.md.
  • Layout: rows of 1-4 columns, column size 3-12 summing to exactly 12 per row, row height >= 400px, column id matches a widget id.
  • Visibility: "org" (default, sidebar-placeable via parent/after) or "private" (no parent/after, identifier gets an owner suffix).
  • Dataset shape: { combinator: "and" | "or", rules: [...] }, each rule a property/relation/scorecard clause. Full grammar: references/dashboards.md.
  • MCP tools (optional, live account): get_sidebar, list_blueprints, list_entities, load_widget_schema, upsert_widget, upsert_dashboard_page, get_page.
  • Fallback without MCP: Port's UI dashboard editor, or the Pages API (POST/PATCH/GET /v1/pages) and POST /v1/blueprints/{blueprint}/entities/search for dataset checks.
  • For custom-code widgets instead of built-in widget types, see the nested port-dashboard-plugins skill.