{"id":68422,"plugin_id":"plugin_asdk_app_6ae0640e1ddc8191851d134bfeb36884","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-10-28T13:15:20.235Z","digest":"9c4ff639556b6d2ca7fe931f12d64f9c0490b218984ed02f2fc5a856022c488a","against":null,"payload":{"description":"Model a Port context lake data model using blueprints, defining identifiers, titles, icons, properties, relations, and calculation, mirror, or aggregation properties, then author them with the raw Port API. Use when asked to create a Port blueprint, define a Port data model, add a property to a blueprint, relate two blueprints, add a calculation property, add a mirror property, or add an aggregation property.","included_files":[{"relative_path":"assets/basic-service-blueprint.json","size_in_bytes":1317},{"relative_path":"assets/blueprint-with-calculation-property.json","size_in_bytes":1651},{"relative_path":"assets/blueprint-with-relations.json","size_in_bytes":1241},{"relative_path":"references/calculation-properties.md","size_in_bytes":5840},{"relative_path":"references/property-types.md","size_in_bytes":4753},{"relative_path":"references/relations.md","size_in_bytes":2815}],"name":"port-blueprints","skill_md_contents":"---\nname: port-blueprints\ndescription: \"Model a Port context lake data model using blueprints, defining identifiers, titles, icons, properties, relations, and calculation, mirror, or aggregation properties, then author them with the raw Port API. Use when asked to create a Port blueprint, define a Port data model, add a property to a blueprint, relate two blueprints, add a calculation property, add a mirror property, or add an aggregation property.\"\nlicense: MIT\ncompatibility: \"Claude Code, Cursor, Codex CLI, GitHub Copilot\"\nmetadata:\n  version: \"1.0.0\"\n  author: port-labs\n  repository: https://github.com/port-labs/port-skills\n  tags: port,blueprints,data-model,reference\n  summary: Model your context lake with Port blueprints, properties, and relations\n---\n\n# Port blueprints\n\nA blueprint is Port's schema primitive. It defines a type of asset in the\ncontext lake (a `service`, a `package`, a `cluster`, anything), the\nproperties that describe it, and how it relates to other blueprints. Every\nentity in Port's context lake is an instance of a blueprint, the same way a\ndatabase row is an instance of a table schema.\n\n## Use this skill when\n\nUse this skill to design or edit a Port data model: creating a new blueprint,\nadding or typing a property, relating two blueprints, or adding a\ncalculation, mirror, or aggregation property. It is reference-only, built\nfrom the static blueprint JSON schema and the raw Port API, so it works\nwithout a live Port account or Port MCP server connected. Without\ncredentials it still produces valid blueprint JSON the user can apply later.\n\nOut of scope: workflows (`port-workflows`),\nscorecards (`port-scorecards`), integration mapping (`port-integrations`),\nthe Terraform/Pulumi provider reference (`port-terraform`, pointed to in\n[Step 6](#step-6---create-or-update-the-blueprint-via-the-api)), and deciding\n*what* to model and how blueprints should relate at the data-model-design\nlevel (`port-context-lake` owns that; this skill is the JSON mechanics it\npoints to).\n\n## Prerequisites\n\n- Go over the `port-getting-started` skill first if this is your first time\n  working with Port.\n- To apply changes without MCP: a `CLIENT_ID`/`CLIENT_SECRET` pair (**...**\n  menu > **Credentials** in the Port app), exchanged for a bearer token at\n  `POST https://api.port.io/v1/auth/access_token`.\n- If Port's MCP server is connected, this skill can use it to read the\n  current blueprint (`list_blueprints`) and apply the result directly\n  (`upsert_blueprint`) instead of you copying JSON in by hand; the raw API\n  calls below always work as a fallback. Search\n  `search_port_knowledge_sources` for anything this skill doesn't cover.\n\n## Step 1 - Check whether the blueprint already exists\n\nPrecondition: you have a bearer token.\nAction: `GET /v1/blueprints/<identifier>`. `200` means it exists, edit it\ninstead of duplicating it. `404` means it's safe to create.\nFallback: no credentials yet. Draft the JSON and tell the user to verify\nuniqueness before applying it.\n\n## Step 2 - Decide the blueprint's identity\n\nPrecondition: you know what real-world asset this blueprint represents.\nAction: pick an `identifier` (unique, ≤100 characters, immutable after\ncreation), a human-readable `title`, and an `icon` from Port's\n[built-in icon set](https://docs.port.io/build-your-software-catalog/customize-integrations/configure-data-model/setup-blueprint/#full-icon-list).\nFallback: if the asset isn't precisely named yet, ask, or default to a\ncamelCase noun (`microservice`, `cloudResource`) and flag it as a guess.\n\n## Step 3 - Define properties\n\nPrecondition: you know what data this asset needs to carry.\nAction: for each field, add a typed entry under `schema.properties` and, if\nmandatory, its key to `schema.required`. See\n[references/property-types.md](references/property-types.md) for the full\ntype system: `string`, `number`, `boolean`, `array`, `object`, string\nformats (`url`, `email`, `user`, `team`, `date-time`, `timer`, `yaml`,\n`markdown`), `enum`, and meta-properties.\nFallback: if the data actually belongs to a different asset, use a relation\n([Step 4](#step-4---add-relations-if-this-asset-connects-to-others)) instead\nof duplicating it.\n\n## Step 4 - Add relations if this asset connects to others\n\nPrecondition: entities of this blueprint need to reference entities of\nanother blueprint (ownership, dependency, hierarchy).\nAction: add a `relations` entry pointing at the target blueprint's\nidentifier. See [references/relations.md](references/relations.md) for the\nsingle vs. many distinction and the `required`/`many` constraint.\nFallback: if the target blueprint doesn't exist yet, create it first,\nrelations require an existing target.\n\n## Step 5 - Add computed properties if useful\n\nPrecondition: a value can be derived from this blueprint's own properties, or\nfrom related entities, instead of being ingested directly.\nAction: use a calculation property (JQ over existing properties), a mirror\nproperty (pull a value from a related entity), or an aggregation property\n(count/sum/average across related entities). See\n[references/calculation-properties.md](references/calculation-properties.md).\nFallback: if the source property doesn't exist yet, add it first.\n\n## Step 6 - Create or update the blueprint via the API\n\nPrecondition: you have a bearer token and a complete blueprint JSON body.\nAction: use the endpoints below. Prefer `PATCH` for additive changes to avoid\nclobbering unrelated fields.\n\n| Operation | Method | Path |\n|---|---|---|\n| Create | `POST` | `/v1/blueprints` |\n| Fully replace | `PUT` | `/v1/blueprints/{identifier}` |\n| Update (additive) | `PATCH` | `/v1/blueprints/{identifier}` |\n| Read | `GET` | `/v1/blueprints/{identifier}` |\n| Delete | `DELETE` | `/v1/blueprints/{identifier}` |\n\n```bash\ncurl -L -X POST 'https://api.port.io/v1/blueprints' \\\n  -H \"Authorization: Bearer ${ACCESS_TOKEN}\" \\\n  -H 'Content-Type: application/json' \\\n  --data @blueprint.json\n ```\n\nFallback: a `422` usually means `required` lists a property that isn't in\n`properties`, or a relation `target` that doesn't exist yet. Fix the JSON and\nretry, don't silently drop the failing field.\n\nIf the user's Port account is managed with Terraform or Pulumi instead of raw\nAPI calls, use the `port-terraform` skill, it owns that reference in depth\nand the blueprint JSON shape maps directly onto it.\n\n## Examples\n\nReady-to-apply templates:\n\n- [assets/basic-service-blueprint.json](assets/basic-service-blueprint.json): a single blueprint, a valid `POST /v1/blueprints` body, with primitive and formatted string properties.\n- [assets/blueprint-with-relations.json](assets/blueprint-with-relations.json): a JSON array of two blueprints (`team`, then `microservice`), `POST` them in order, showing a required single relation and a self-referencing many relation.\n- [assets/blueprint-with-calculation-property.json](assets/blueprint-with-calculation-property.json): a blueprint with a calculation property, a mirror property, and an aggregation property. Assumes a `kubernetesCluster` and an `incident` blueprint already exist as relation/aggregation targets.\n\n## Common pitfalls\n\n| Symptom | Cause | Fix |\n|---|---|---|\n| `422` on create/update | `required` references a missing property, or a relation `target` doesn't exist | Create the target first; keep `required` in sync with `properties` |\n| Property type change is rejected or corrupts data | Property types are immutable after creation | Create a new property with the right type, [migrate data](https://docs.port.io/build-your-software-catalog/customize-integrations/configure-data-model/migrate-data/), delete the old one |\n| Relation rejected with `many` and `required` both `true` | Port forbids that combination | A required relation must be single (`many: false`) |\n| Calculation property returns `null` | JQ references a missing path, or a relation title (`.relations.x.title`) under persistent calculation | Test the JQ against a real entity payload; use a mirror property for relation titles |\n| New property invisible in the UI table | New properties are hidden by default in table views | Toggle it on with **Manage properties**; this doesn't affect the API or ingested data |\n\n## Quick reference\n\n- Blueprint top-level keys: `identifier`, `title`, `description`, `icon`,\n  `schema` (`properties`, `required`), `calculationProperties`,\n  `mirrorProperties`, `relations`, `ownership`.\n- Property types: `string`, `number`, `boolean`, `array`, `object`, plus\n  string formats. Full list: [references/property-types.md](references/property-types.md).\n- Relation shape: `{ \"title\", \"target\", \"required\", \"many\" }`. Details:\n  [references/relations.md](references/relations.md).\n- Derived properties: calculation (JQ), mirror (path into a relation),\n  aggregation (count/sum/average/min/max/median). Details:\n  [references/calculation-properties.md](references/calculation-properties.md).\n- Auth: `POST /v1/auth/access_token` with `clientId`/`clientSecret`.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}