|
| 1 | +--- |
| 2 | +name: build-plugin |
| 3 | +description: Guides building a SquaredUp low-code plugin for HTTP/REST APIs, from API exploration through deployment. Use when the user wants to integrate a service with SquaredUp, add a new data source, connect to a third-party tool, "pull data from", or "monitor" any service in SquaredUp. |
| 4 | +metadata: |
| 5 | + author: SquaredUp |
| 6 | + version: "0.0.3" |
| 7 | +--- |
| 8 | + |
| 9 | +# Building a SquaredUp Low-Code Plugin |
| 10 | + |
| 11 | +> **Scope:** Web API-based plugins only. If the target tool has no usable REST API, PowerShell may be a better fit — suggest it and stop. |
| 12 | +
|
| 13 | +**Announce at start:** "I'm using the build-plugin skill." |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## Required user inputs |
| 18 | + |
| 19 | +| Input | When to ask | Why | |
| 20 | +| ------------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------- | |
| 21 | +| **Author handle** (GitHub handle or display name) | Before writing `metadata.json` (Phase 4) | Goes into `author.name`. Guessing from git config frequently picks the wrong identity. | |
| 22 | + |
| 23 | +If the user has already volunteered the answer earlier in the conversation or you're updating a plugin, use that and skip the prompt. Otherwise, ask — even in autonomous mode. |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## When to Use |
| 28 | + |
| 29 | +- Building a new plugin for an HTTP/REST API |
| 30 | +- Adding data streams or dashboards to an existing plugin |
| 31 | +- Any request to integrate a service, "pull data from", or "monitor" a service in SquaredUp |
| 32 | +- Adding a new data source or integration to a SquaredUp workspace |
| 33 | + |
| 34 | +--- |
| 35 | + |
| 36 | +## Checklist |
| 37 | + |
| 38 | +Create a TaskCreate task for each phase: |
| 39 | + |
| 40 | +- [ ] **Phase 1** — Explore the API |
| 41 | +- [ ] **Phase 2** — Plan the plugin structure |
| 42 | +- [ ] **Phase 3** — Scaffold files (icon, file structure, `docs/README.md`) |
| 43 | +- [ ] **Phase 4** — Write `metadata.json` and `ui.json` → read [metadata.md](references/metadata.md) and [ui.md](references/ui.md) |
| 44 | +- [ ] **Phase 5** — Write import definitions → read [index-defs.md](references/index-defs.md) |
| 45 | +- [ ] **Phase 6** — Write data streams → read [data-streams.md](references/data-streams.md) |
| 46 | +- [ ] **Phase 7** — Write OOB default content → read [oob-content.md](references/oob-content.md) |
| 47 | +- [ ] **Phase 8** — Write `custom_types.json` → read [common-patterns.md](references/common-patterns.md) |
| 48 | +- [ ] **Phase 9** — Validate and deploy → invoke the `deploy-plugin` skill |
| 49 | + |
| 50 | +--- |
| 51 | + |
| 52 | +## Phase 1: Explore the API |
| 53 | + |
| 54 | +Before writing a single file, understand the API. **Use `AskUserQuestion` to ask for API documentation URLs, OpenAPI/Swagger specs, Postman collections, or any other reference material.** You can also search online, but verify you're looking at docs for the exact product/version the user wants. |
| 55 | + |
| 56 | +1. **Find the docs** — Gather URLs or spec files from the user, then fetch and read them. |
| 57 | +2. **Identify the object model** — What are the core entities? (e.g. installations, devices, sites). These become the **indexed objects** in SquaredUp — available for drilldown, search, scoping dashboards, and use as variables. |
| 58 | +3. **Find the list endpoints** — Used to import objects. Prefer fetching **50–250 records per page** across multiple requests — SquaredUp has a per-page timeout but supports as many paged requests as needed. |
| 59 | +4. **Find the data endpoints** — These power data streams. Identify whether each is scoped to a single object, multiple objects, or global (no object context). |
| 60 | +5. **Understand pagination** — Cursor/next-token, or offset/limit? Separate concern from response transformation. |
| 61 | +6. **Note the auth pattern** — API key in header, Bearer token, OAuth2, Basic auth? Determine from the docs. |
| 62 | + |
| 63 | +--- |
| 64 | + |
| 65 | +## Phase 2: Plan the Plugin Structure |
| 66 | + |
| 67 | +This phase produces a written plan and a user-approval gate before any files are written. Object types, import shape, and sourceId format are expensive to change once Phase 3+ commits them to JSON — Phase 2 is where scope errors are cheap to fix. |
| 68 | + |
| 69 | +### The plan must cover |
| 70 | + |
| 71 | +1. **Object types** — Every type that should appear in the SquaredUp graph. These go in `objectTypes` in `metadata.json` and as `sourceType` throughout. |
| 72 | +2. **Import steps** — Let the API shape dictate: one step returning many types, or separate steps per type. |
| 73 | +3. **Data streams** — For each object type, plan: |
| 74 | + - A **summary/current state** stream (`"timeframes": false`, returns current values) |
| 75 | + - A **history/metrics** stream (supports timeframes, returns time-series rows) |
| 76 | + - Any **cross-object** streams scoped to a parent (e.g. alarms for an installation) |
| 77 | + - **Prefer configurable streams** over hardcoded ones — use a UI parameter rather than multiple streams for the same endpoint with different values. |
| 78 | +4. **What's intentionally omitted** — API capabilities not being implemented, and why. Highest-value section for catching scope creep. |
| 79 | +5. **Authentication** — Auth mechanism and any UX concerns (token expiry, rate limits, hard-to-obtain credentials). |
| 80 | +6. **OOB dashboards** — A **top-level summary dashboard** plus **one perspective per object type** scoped via a dashboard variable. |
| 81 | +7. **sourceId format** — Use the raw API ID wherever possible. |
| 82 | + |
| 83 | +### Plan format |
| 84 | + |
| 85 | +Post the plan as markdown with one `###` heading per item above. Short example: |
| 86 | + |
| 87 | +```markdown |
| 88 | +## Plan |
| 89 | + |
| 90 | +### Object types |
| 91 | +- `My Installation` — sites being monitored |
| 92 | +- `My Device` — physical devices reporting telemetry |
| 93 | + |
| 94 | +### Import steps |
| 95 | +- `installations` — one step, returns both types |
| 96 | + |
| 97 | +### Data streams |
| 98 | +- `batterySummary` — per-device, current state |
| 99 | +- `batteryHistory` — per-device, time-series |
| 100 | +- `siteAlarms` — per-installation |
| 101 | + |
| 102 | +### What's intentionally omitted |
| 103 | +- Webhook ingestion (no v1 use case) |
| 104 | + |
| 105 | +### Authentication |
| 106 | +- API key in `X-API-Key` header |
| 107 | + |
| 108 | +### OOB dashboards |
| 109 | +- Overview, Installation perspective, Device perspective |
| 110 | + |
| 111 | +### sourceId format |
| 112 | +- Installation: raw API `id` |
| 113 | +- Device: composite `{installationId}-{deviceId}` (API has no global device ID) |
| 114 | +``` |
| 115 | + |
| 116 | +### Approval gate |
| 117 | + |
| 118 | +**When to fire:** when `metadata.json` doesn't exist yet in the plugin folder, OR when the planned `objectTypes` differs from the current `metadata.json`. Otherwise skip — incremental work that doesn't introduce new entities doesn't need the gate. |
| 119 | + |
| 120 | +**How:** post the plan, then call `AskUserQuestion` **in the same turn** with three options: |
| 121 | + |
| 122 | +- `Approve as written` → proceed to Phase 3 |
| 123 | +- `Trim scope — start with less` → user wants a smaller MVP; ask what to cut |
| 124 | +- `Adjust — different objects/streams/auth` → user wants changes; ask what specifically |
| 125 | + |
| 126 | +If the user picks anything other than approve (including "Other"), revise the plan and re-fire the gate with the updated plan. Loop until approval — a revised plan can introduce new wrong assumptions, so the second pass is doing real work, not theatre. If the user explicitly waives further gating ("just proceed", "looks fine, go", "stop asking"), honor that for the rest of this conversation. |
| 127 | + |
| 128 | +--- |
| 129 | + |
| 130 | +## Phase 3: Scaffold Files |
| 131 | + |
| 132 | +**Icon:** Find the official brand/product logo (SVG or PNG). Never auto-generate a generic icon — ask the user to supply one if you can't find an official logo. |
| 133 | + |
| 134 | +**Post-process SVG icons if needed.** SquaredUp shows icons on dark/white backgrounds. Fix if the SVG lacks a background or is not square: |
| 135 | + |
| 136 | +1. Set `width="512" height="512" viewBox="0 0 512 512"` |
| 137 | +2. Insert `<rect width="512" height="512" fill="BRAND_COLOR"/>` as the first child |
| 138 | +3. Wrap paths in `<g transform="translate(X, Y) scale(S)">` for ~10% padding: `S = min(409.6/w, 409.6/h)`, `X = (512−w*S)/2`, `Y = (512−h*S)/2` |
| 139 | + |
| 140 | +**File structure:** |
| 141 | + |
| 142 | +``` |
| 143 | +my-plugin/ |
| 144 | + v1/ |
| 145 | + metadata.json |
| 146 | + ui.json |
| 147 | + icon.svg |
| 148 | + custom_types.json |
| 149 | + configValidation.json # preferred: validates config on setup |
| 150 | + docs/ |
| 151 | + README.md # REQUIRED: shown in-product when users add the plugin |
| 152 | + indexDefinitions/ |
| 153 | + default.json |
| 154 | + dataStreams/ |
| 155 | + myStream.json |
| 156 | + scripts/ |
| 157 | + myScript.js |
| 158 | + defaultContent/ |
| 159 | + manifest.json |
| 160 | + scopes.json |
| 161 | + overviewDashboard.dash.json |
| 162 | + deviceDashboard.dash.json # single perspective — no sub-folder needed |
| 163 | + Installations/ # sub-folder only for multiple dashboards of the same type |
| 164 | + manifest.json |
| 165 | + dashboard1.dash.json |
| 166 | +``` |
| 167 | + |
| 168 | +**docs/README.md (required)** — surfaced in-product when a user adds the plugin. Always create as part of scaffolding; the `documentation` link in `metadata.json` must point to it (e.g. `https://github.com/squaredup/plugins/blob/main/plugins/MyPlugin/v1/docs/README.md`). |
| 169 | + |
| 170 | +The README must cover: |
| 171 | + |
| 172 | +1. What the plugin monitors — objects imported, what dashboards show |
| 173 | +2. Prerequisites / getting credentials — step-by-step, include required scopes/permissions |
| 174 | +3. Configuration fields — table explaining every `ui.json` field: what it is, where to find the value, whether required |
| 175 | +4. What gets indexed — list object types and what they represent |
| 176 | +5. Known limitations — rate limits, permission requirements, API quirks |
| 177 | + |
| 178 | +Write as if the user has never seen the API. They're reading it inside SquaredUp, not on the vendor's site. |
| 179 | + |
| 180 | +**Other rules:** |
| 181 | + |
| 182 | +- `scopes.json`: only include scopes used by OOB dashboards. Don't add speculatively. |
| 183 | +- `configValidation.json`: optional but strongly preferred — see [common-patterns.md](references/common-patterns.md). |
| 184 | +- **Single-dashboard rule:** Only create a sub-folder under `defaultContent/` when you have **multiple dashboards** for the same type. |
| 185 | + |
| 186 | +--- |
| 187 | + |
| 188 | +## Phases 4–8: Writing Files |
| 189 | + |
| 190 | +Read the corresponding reference file before writing each phase: |
| 191 | + |
| 192 | +| Phase | Files | Reference | |
| 193 | +| -------------------------- | --------------------------------------------------- | ---------------------------------------------------------------- | |
| 194 | +| 4 — Plugin identity & auth | `metadata.json`, `ui.json`, `configValidation.json` | [metadata.md](references/metadata.md), [ui.md](references/ui.md) | |
| 195 | +| 5 — Import definitions | `indexDefinitions/default.json` | [index-defs.md](references/index-defs.md) | |
| 196 | +| 6 — Data streams | `dataStreams/*.json`, `scripts/*.js` | [data-streams.md](references/data-streams.md) | |
| 197 | +| 7 — OOB default content | `defaultContent/`, `scopes.json` | [oob-content.md](references/oob-content.md) | |
| 198 | +| 8 — Custom types | `custom_types.json` | [common-patterns.md](references/common-patterns.md) | |
| 199 | + |
| 200 | +For reusable patterns (built-in properties stream, configValidation steps), read [common-patterns.md](references/common-patterns.md). |
| 201 | + |
| 202 | +--- |
| 203 | + |
| 204 | +## Phase 9: Validate & Deploy |
| 205 | + |
| 206 | +Invoke the `deploy-plugin` skill. |
0 commit comments