$npx -y skills add likweitan/abap-skills --skill btp-diagram-generatorGenerate SAP BTP (Business Technology Platform) solution architecture diagrams as native draw.io (.drawio) files following the official SAP BTP Solution Diagram guidelines (Fiori Horizon design system) and open them via a configured draw.io MCP server. USE WHEN: user asks to crea
| 1 | # BTP Solution Diagram Generator |
| 2 | |
| 3 | Produces a `.drawio` file in the workspace that conforms to the [SAP BTP Solution Diagram guidelines](https://sap.github.io/btp-solution-diagrams/) and opens it through whichever [draw.io MCP server](https://www.drawio.com/doc/faq/ai-drawio-generation) is configured. |
| 4 | |
| 5 | ## ⚡ Quick Path (use this first) |
| 6 | |
| 7 | For the vast majority of diagrams, **do not hand-write XML**. Use the `btp_builder` Python package — it owns icon lookup, SAP palette, port pinning, label HTML, A4 sizing, SVG upscaling, and validation. A typical L1 diagram is ~20 lines. |
| 8 | |
| 9 | ```python |
| 10 | # scripts/examples/task_center_arch.py — runnable end-to-end |
| 11 | import sys |
| 12 | from pathlib import Path |
| 13 | # Add the skill's scripts/ dir to sys.path so `btp_builder` imports work |
| 14 | # regardless of where the skill is installed (repo, ~/.claude/skills/, etc.) |
| 15 | sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) |
| 16 | |
| 17 | from btp_builder import BtpDiagram |
| 18 | |
| 19 | d = BtpDiagram(level="L1", title="Task Center Reference Architecture") |
| 20 | |
| 21 | btp = d.btp_container(x=260, y=80, w=560, h=440) |
| 22 | sub = d.subaccount(parent=btp, label="Subaccount", |
| 23 | x=btp.x + 24, y=btp.y + 110, w=520, h=170) |
| 24 | |
| 25 | wz = d.service("work zone", in_=sub, x=sub.x + 60, y=sub.y + 60) |
| 26 | tc = d.service("task center", right_of=wz) |
| 27 | ci = d.service("cloud identity", below=tc) |
| 28 | |
| 29 | eu = d.user("End User", x=60, y=btp.y + 100) |
| 30 | ac = d.app_client("Application Clients\n(Mobile or Desktop)", below=eu) |
| 31 | |
| 32 | s4 = d.external("SAP S/4HANA\nOn-Premise Solutions", |
| 33 | x=btp.right_edge() + 40, y=btp.y + 70, kind="sap") |
| 34 | third = d.external("3rd Party\nApplications", below=s4, kind="non-sap") |
| 35 | cloud = d.external("SAP Cloud\nApplications", below=third, kind="sap") |
| 36 | idp = d.idp("3rd-party Identity Provider", |
| 37 | x=ci.center_x() - 140, y=btp.bottom_edge() + 60) |
| 38 | |
| 39 | d.connect(eu, ac, direction="down") |
| 40 | d.connect(ac, wz, direction="right") |
| 41 | d.connect(wz, tc, kind="dblhd") |
| 42 | d.connect(tc, ci, kind="dblhd", direction="down") |
| 43 | d.connect(tc, s4); d.connect(tc, third); d.connect(tc, cloud) |
| 44 | d.connect(idp, ci, kind="dashed", direction="up") |
| 45 | |
| 46 | d.save("btp-task-center-architecture.drawio") # validates → raises on errors |
| 47 | ``` |
| 48 | |
| 49 | Run via `uv run python <script>.py` from the repository root. `save()` validates first and raises `ValueError` with the full error list if anything is off; warnings are printed. |
| 50 | |
| 51 | ### Quick-Path API surface |
| 52 | |
| 53 | | Call | Returns | Notes | |
| 54 | | ----------------------------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 55 | | `BtpDiagram(level, title)` | builder | level ∈ `L0`/`L1`/`L2`. Drives icon size + label weight. | |
| 56 | | `.btp_container(x,y,w,h, sub_label, env_label, with_logo)` | `NodeRef` | Light-blue outer frame + SAP corner logo + Subaccount/Multi-Cloud labels. | |
| 57 | | `.subaccount(parent, label, ...)` | `NodeRef` | White card inside the BTP container. | |
| 58 | | `.inner_card(parent, label, ...)` | `NodeRef` | Generic white sub-card (e.g. CIS service group). | |
| 59 | | `.service(name, in_=, right_of=, left_of=, below=, above=)` | `NodeRef` | `name` is fuzzy-matched via [reference/icon-aliases.json](reference/icon-aliases.json) (e.g. `"task center"`, `"cpi"`, `"hana cloud"`). | |
| 60 | | `.user(label, kind="sap")` | `NodeRef` | kind ∈ `sap` / `non-sap` / `highlight`. |