Skip to main content

dashboard-management

Create, lay out, organize, or share Analytics dashboards and panels: sources, placement, folders, verification. Use to create a dashboard or to move, reorder, or lay out panels; a small edit of one existing panel needs no skill.

소스 정보

저장소
BuilderIO/agent-native
최근 소스 활동
2026년 10월 16일 03:42
감지된 SKILL.md 언어
영어
스타
7,366
포크
669

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
dashboard-management
description
Create, lay out, organize, or share Analytics dashboards and panels: sources, placement, folders, verification. Use to create a dashboard or to move, reorder, or lay out panels; a small edit of one existing panel needs no skill.
# Dashboard Management Dashboards are the canonical SQL-backed Analytics resources. New dashboards, saved analyses, reports, and bespoke extensions are represented as dashboard artifacts—not as separate user-facing Analytics objects. Legacy analysis tables and actions remain available only for compatibility. ## Storage Current storage: | Table | Purpose | | ------------------------- | -------------------------------------------- | | `dashboards` | Explorer and SQL dashboard records | | `dashboard_folders` | Personal and shared SQL dashboard folders | | `dashboard_views` | Saved filter presets per dashboard | | `dashboard_shares` | Standard framework share grants | | `dashboard_folder_shares` | Standard folder share grants | | `dashboard_revisions` | Bounded dashboard history snapshots | | `analyses` | Saved ad-hoc analysis records | | `analysis_revisions` | Bounded analysis history snapshots | | `analysis_shares` | Standard framework share grants for analyses | Legacy settings keys such as `u:<email>:dashboard-*`, `u:<email>:sql-dashboard-*`, `o:<orgId>:sql-dashboard-*`, and `adhoc-analysis-*` are still read as a fallback and copied into SQL on access. Do not create new dashboard settings rows. ## Dashboard folders Dashboard folders are SQL-backed, access-scoped containers for organizing SQL dashboards from `/dashboards`: - `personal` folders are private to their owner. - `shared` folders are organization-visible and require an active organization. - Use `list-dashboard-folders`, `create-dashboard-folder`, and `set-dashboard-folder` for folder reads and membership changes. - A folder never expands dashboard access. A personal folder can contain only an owned private dashboard; a shared folder can contain only an org-visible dashboard. Use the normal dashboard sharing actions separately. For organization-wide consolidation, use `migrate-analytics-artifacts` first with `dryRun: true`. The write requires an organization owner/admin and the exact confirmation token `MIGRATE_ANALYTICS_ARTIFACTS`. It materializes organization-scoped legacy settings, creates dashboard blocks for saved analyses and standalone extensions, archives exact duplicates, copies shares, and removes legacy settings keys only after SQL rows are materialized. Source rows remain recoverable. Private member-only rows are intentionally outside this organization-scoped operation. Use `mutate-dashboard` for existing dashboard edits. It resolves the current user/org context, validates the resulting config, writes the SQL-backed record, syncs collab, and returns a compact result with a `verified` flag. Use `update-dashboard` for new full-config saves, UI full-config saves, or explicitly requested low-level JSON-pointer edits. Every meaningful dashboard save snapshots the previous state into `dashboard_revisions`. Use `list-dashboard-revisions` to inspect available undo points and `restore-dashboard-revision` to restore one; restore snapshots the current state first, then syncs open dashboard editors. Each revision's `changes` names what the save that left it behind changed (`panel-added`, `column-resized`, `filter-changed`, `version-restored`, and so on), so restoring it undoes that change and every later one. To answer "undo the column I widened", pick the revision whose `changes` match instead of guessing from times. `changesStatus` is `absent` for revisions saved before changes were recorded and `unreadable` when the stored list is corrupt; say you can't tell what those changed rather than treating them as empty. On the page, an editor's own saves show a toast that names the change its Undo takes back, says "Saved for everyone" (org or public visibility; "Saved" when private), and counts the others who have the dashboard open. That Undo restores the revision its save left (a full-config `update-dashboard` save returns it as `revisionId`), but only while the dashboard is as that save left it: once someone else has saved, it fails rather than taking their change back. For "undo my last change" in chat, restore the newest revision from `list-dashboard-revisions`. The History panel shows each revision's first change with "+N more". Saved analyses follow the same undo model with `analysis_revisions`, `list-analysis-revisions`, and `restore-analysis-revision`. Dashboards open in View mode. An editor switches the header toggle to Edit before drags, renames, and column edits on the page save for everyone; the chat context reports the current mode. A table column width dragged in View mode is stored only in that person's browser, so "widen this column for me" is a drag in View mode, not a dashboard change. `config.columns[].width` is the shared width everyone sees; set it only when asked to change the dashboard itself. Never use `db-patch`, raw SQL, or settings-key edits to create or modify a dashboard config. Those bypass the dashboard action's access checks, SQL validation, collab sync, and verification. If a dashboard action fails because the argument shape was wrong, fix that action's arguments and retry once — do not switch to db-patch or raw SQL. ### GitHub folder sync A linked folder mirrors its SQL dashboards to `<path>/<dashboardId>.json` in a GitHub repo. Read `docs/dashboard-github-folder-sync.md` before changing or explaining it. - Run `preview-dashboard-folder-github-sync` before any sync. It writes nothing. - `apply-dashboard-folder-github-sync` pulls from GitHub. It writes only the panels, order, and settings that changed on the GitHub side. - `export-dashboard-folder-to-github` opens one PR with the app's changes. It refuses while an earlier export PR is still open. - `configure-dashboard-folder-github-sync` links or unlinks a folder. It stores no credentials. - A unit changed on both sides is a conflict. It is reported and not applied. Do not resolve it by overwriting either side without asking the user. - Explorer dashboards, sharing, and deletions never sync. A synced dashboard cannot be permanently deleted; archive it or unlink its folder first. ## Valid Panel Sources `panel.source` is a backend selector, not a table name. It must be one of: | Source | Query shape | | ------------- | -------------------------------------------------------------------------------------------------------- | | `bigquery` | Literal warehouse SQL. Table names belong inside the SQL string. | | `ga4` | JSON descriptor for the Google Analytics Data API. | | `amplitude` | JSON descriptor for an Amplitude query. | | `first-party` | Read-only SQL over this template's `analytics_events` table, usually via `query-agent-native-analytics`. | Do not use `app-db` as a dashboard source. For first-party events collected through `/track`, use `source: "first-party"` or the `query-agent-native-analytics` action rather than raw internal `db-query`. AI-generated first-party panels are dashboard-time-bound by default. Set `config.timeScope` to `"dashboard"` and include the matching dashboard time filter in the SQL. The allowed values are: - `dashboard`: use the dashboard-selected time range; the default for ordinary metrics. - `fixed-window`: use an explicit bounded window independent of the dashboard filter. - `cohort-history`: use the bounded history of an explicitly defined cohort. - `all-time`: scan all available history; use only when the user requests it and put `all-time`, `lifetime`, or `historical` in the title or description. `{{timeRange}}` requires an explicit matching `filters` entry with `id: "timeRange"` and `type: "select"`. `{{<id>Start}}` and `{{<id>End}}` require a matching `filters` entry with that id and `type: "date-range"`. Do not rely on undeclared time variables. Server validation rejects unbound first-party SQL, so declare the filter or choose an explicit non-dashboard scope before saving. **A bound anywhere in the SQL is not the same as every CTE having its own bound.** If a panel has multiple top-level CTEs (`WITH a AS (...), b AS (...)`) and more than one of them reads `analytics_events`, EVERY one of those CTEs needs its own `{{timeRange}}`/`{{<id>Start}}`/`{{<id>End}}` reference or literal date bound — not just the final `SELECT` or one sibling CTE. A CTE that computes something like "this user's first-ever active day" by scanning `analytics_events` with no bound at all will full-table-scan on every render even though the panel _looks_ time-bound overall (root cause of a 2026-07-25 production incident: several dashboards had exactly this shape). Server validation checks each top-level CTE independently now, so this fails at save time — but write it right the first time: bound every CTE, or use `config.timeScope: "cohort-history"` only for a CTE that is genuinely defining a cohort (e.g. a first-seen date), never as a way to skip bounding an ordinary activity scan. ## Creating A Dashboard When the user asks for a dashboard: 1. Start from the preloaded `<resource scope="analytics-catalog">` references (catalog-first), else one `find-data`. If a relevant entry exists, use its `table`, `columns`, `queryTemplate`, and gotchas verbatim. 2. If a metric definition, date range, or grain is ambiguous and the choice would change the panel's numbers, use the `ask-question` clarifying tool once before building. Skip it when the dictionary or the user already settled it. 3. If a metric is not documented, do not guess column names and do not ask the user for them. Find the table and columns with `search-bigquery-schema` (or the provider's own schema action), then propose a dictionary entry with `save-data-dictionary-entry`. 4. Build a complete `SqlDashboardConfig` with `name` and `panels`. Optionally set top-level `columns` (1–6, default 2) to control how many grid columns the panels before any section use. 5. Every panel needs `id`, `title`, `source`, `chartType`, `width`, and `sql`. `width` is the number of grid columns the panel spans (1..6, clamped to the active section's column count). Section panels skip `source` and `sql` and may set their own `columns` (1–6) to override the dashboard default for the panels following the section. Extension panels (`chartType: "extension"`) also skip `source` and `sql`; use `config.extensionId` for ordinary author-selected shared embeds. Use `config.extensionSlotId` only when the user explicitly asks for a personal/per-viewer slot (see "Embedding An Extension As A Panel"). 6. Persist with `update-dashboard` (load it with `tool-search` — it is not on the initial tool surface), not raw SQL or settings writes. For a large first-party dashboard, load `compose-dashboard` the same way in one `tool-search` call. 7. Navigate to it with `pnpm action navigate --view=adhoc --dashboardId=<id>`. An explicit dashboard request authorizes the complete non-destructive build in the same turn. After querying or scaffolding, continue through extension-data seeding/refresh, dashboard save/embed, and navigation; do not ask whether to proceed or leave an empty Custom Block shell. Ask only when metric scope/grain is materially ambiguous, the change is destructive, or it has an external side effect such as sending email or outreach. Layout is always **1 column when the available content width is below the `md` threshold** (panels stack), then expands to the configured column count at/above it. The grid uses a container query, so it also stacks when the agent sidebar narrows the content pane — not only at narrow viewports. So picking 3 or 4 columns is fine — the renderer keeps narrow layouts readable automatically. ```bash pnpm action update-dashboard --dashboardId weekly-metrics --config '<full json>' pnpm action navigate --view=adhoc --dashboardId=weekly-metrics ``` The save path dry-runs BigQuery panels before persisting. If validation returns a provider error, fix the query and retry. Never work around validation by writing directly to a table. ### Replicating Or Adapting Another Dashboard When the user asks to replicate, clone, or adapt an existing dashboard into a new one, call `search-dashboard-references` with focused terms first. It searches accessible active saved dashboards (ids, names, descriptions, serialized config), including legacy ones. Inspect each result with `get-sql-dashboard` when `kind` is `sql`, or `get-explorer-dashboard` when it is `explorer`. A result is a reference, not proof its source is authoritative for the new request: check the provider and scope the user asked for before copying its source semantics, and do not route a replication request to first-party Analytics by default. This applies to a new dashboard, not to editing the dashboard that is already open. ## Dual-Axis Charts `line`, `area`, and `bar` panels can plot series against two y-axes. Reach for this whenever series share an x-axis but not a unit — a count next to a rate, or revenue next to a conversion percent. On a single axis the smaller series flattens into the baseline and reads as "no data." ```json { "id": "signups-vs-conversion", "title": "Signups vs conversion rate", "source": "first-party", "chartType": "line", "width": 1, "sql": "SELECT day, signups, conversion_rate FROM ...", "config": { "timeScope": "dashboard", "xKey": "day", "yKeys": ["signups", "conversion_rate"], "yFormatter": "number", "rightYKeys": ["conversion_rate"], "rightYFormatter": "percent" } } ``` - `rightYKeys` names series from `yKeys`; everything unnamed stays on the left. - `rightYFormatter` defaults to `yFormatter` when omitted. - Each axis is labelled with its series names (up to two per side), and tooltip values use the formatter of the axis the series belongs to. - At least one series must remain on the left. If `rightYKeys` names every series, or names a column the query never returned, the panel falls back to a single axis and shows a config warning rather than dropping the series. - Scheduled email reports render the same two scales, so a dual-axis panel is safe to put on a subscribed dashboard. ## Key-Date Event Markers Mark a launch, release, or incident on a `line`, `area`, `bar`, or `combo` chart with a date x-axis using `config.events`. Do not add a fake series or an extension for this. ```json "config": { "events": [ { "date": "2026-10-14", "time": "00:01", "timeZone": "America/Los_Angeles", "label": "Product Hunt live" }, { "date": "2026-10-14", "time": "12:00", "timeZone": "America/New_York", "label": "Launch posts on X, LinkedIn" } ] } ``` - Each event is `{ date: "YYYY-MM-DD", label, time?: "HH:MM", timeZone?, color? }`; multiple are allowed. `date` is the calendar date in the event's own zone. Give `time` when the moment matters (a launch hour); `timeZone` is an IANA zone and needs a `time`. Without a zone, the time is UTC. - A badge sits on the x-axis at the date with a faint dashed guide line. Hovering the badge lists every event on that day with its time, shown in the event's own zone ("12:01 AM PT"). It adds no legend entry and does not change the series tooltip. - Events on the same day share one badge; on an hourly axis each timed event sits in its own hour, and an event without a time sits on the first hour shown for its date. - On a daily or coarser axis, a date missing from the data snaps to the nearest x value. On an hourly axis, an event without a time whose date has no hours shown is hidden. A date outside the visible range is hidden; a non-date x-axis shows nothing. - `mutate-dashboard` rejects malformed events and other chart types. - Scheduled email reports draw the guide line, badge, and label text, including on combo charts. Labels sit in rows above the plot: same-day labels join, a long one wraps at words, and days that find no room are counted, not cut. ## Reusable Native Dashboard Patterns The recent extension-backed dashboards in Builder Analytics cluster into a few repeatable compositions. Prefer these native panels, with a real SQL or Data Program result behind each one, when creating a replacement or a new dashboard: | Pattern | Native composition | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | Customer ROI / value realization | `metric` KPI cards, `line` or `area` trends, `table` detail, and `callout` or `section` panels for the business narrative | | Account engagement / outreach | `metric` coverage and adoption cards, a daily `line` trend, `heatmap` or `table` segmentation, and `callout` alerts | | GTM pipeline / cross-sell | `funnel` for ordered stages, `metric` totals, `bar` or `line` trends, and a `table` for account-level follow-up | | Win/loss analysis | `section` groups with `metric`, `table`, `bar`, `callout`, and trend panels; use a Data Program for provider joins and evidence rows | Funnel panels use `config.xKey` for the stage label and `config.yKey` for a non-negative count or value. The renderer preserves the SQL row order, shows each stage's share of the first stage, and shows the change from the previous stage. Keep the intended stage order in SQL with `ORDER BY`.
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기