Data App Design
Make Databricks data + AI apps that communicate clearly and compile to real AppKit code. This
skill merges two bodies of knowledge and binds them to implementation:
- Composition — what to show, how much to abstract, how to lay it out →
references/dashboard-patterns.md
- Notation — make comparable things look comparable; honest scales; scenario marks →
references/ibcs-notation.md
- Implementation — the exact AppKit components, hooks, and tokens to use →
references/appkit-cheatsheet.md
Design advice that doesn't name a real component is incomplete. Always end at a component plan.
When to use / when NOT
- USE for: dashboard/overview/KPI pages, reports, metric/ontology pages, variance analysis, and Genie/NL data surfaces — design or critique.
- Do NOT use for: authoring managed AI/BI (Lakeview) dashboards (→
databricks-aibi-dashboards), generic frontend (forms, auth, settings, marketing), or scaffolding/build/deploy (→ databricks-apps). If a request is "add a form", "deploy this", or "build a Lakeview / AI-BI dashboard", this skill should not fire.
- Relationship:
databricks-apps builds/runs the app; this skill decides what the data screens should look like and which primitives realize them.
Workflow
- Frame — audience, the decision/question, refresh cadence, device, primary task. One sentence.
- Genre — pick the closest from
dashboard-patterns.md (static / analytic / magazine / infographic / repository / embedded mini). State it.
- Compose — choose content + composition patterns (data abstraction, meta-info, layout, interaction, color). Make the tradeoff explicit: what's summarized, hidden, paginated, or made interactive — and why.
- Apply notation — run the relevant
ibcs-notation.md rules: message-in-title, scenario marks (actual/PY/plan/forecast), honest scales, semantic color. On any chart-vocabulary conflict, IBCS wins (see the conflict note in that file).
- Bind to components — map every element to a primitive that's actually exported from
@databricks/appkit / @databricks/appkit-ui (see appkit-cheatsheet.md); never cite a component AppKit doesn't ship. There's no prebuilt KPI/trend/distribution card — compose those from primitives, following the notation rules. Use colorPalette + semantic tokens, never hardcoded hex. Bind data with useAnalyticsQuery/queryKey + sql.* params.
- Cover the states — every data view must handle loading / empty / error / partial (see checklist).
- Review — run the checklists in both reference files; lead critiques with the highest-impact comprehension or integrity issue, citing the affected component/file.
Required states & data realism (non-negotiable for data apps)
- Loading →
Skeleton; Empty → Empty with a useful next action; Error → inline message, never a blank panel; Partial/stale → show what you have + a freshness note.
- Every KPI shows unit + period + comparison + freshness/source (mirror the metric definition; don't show a number with no provenance).
- Large tables → server-side pagination/sort/filter, not client-side over a huge result set.
- Long-running queries → optimistic loading + timeout/error UX.
AI / Genie surfaces (the "AI" half)
Gate: this section applies only if the app has a Genie / chat / natural-language / "ask your data" surface. For a pure dashboard / KPI / report app with no conversational input, skip this section and references/genie-ai-trust.md entirely. When it does apply, implement ALL five (code in references/genie-ai-trust.md):
A Genie/chat/NL answer is only trustworthy if the user can see how it was produced and who it ran as. "Use GenieChat + a spinner" is NOT enough — for ANY Genie/chat surface, ship all five (copy the exact snippets from the reference):
- Identity — a
/api/whoami route (real x-forwarded-email/x-forwarded-user headers) + the signed-in user in a Badge. Claim OBO only if user_api_scopes: [dashboards.genie] is wired; otherwise disclose the query runs as the app's service principal.
- Generated SQL — render
attachments[].query in an inspectable "Generated SQL" Card; never hide how the answer was computed.
- Streaming/status — reflect
useGenieChat().status (streaming/error), never a frozen spinner.
- Disclaimer — a persistent "AI-generated — verify" note per answer.
- Governance + states —
genie() space config + a truthful execution-identity note (OBO when user-scoped, else service principal) + empty/error/ambiguous handling (Empty, Alert).
Output formats
Design proposal:
## Direction
[Genre, audience, primary task, design intent.]
## Pattern & notation choices
- Composition: [data info, meta info, layout, interaction, color]
- Notation: [message, scenario marks, scales, semantic color]
## Component plan ← the part that makes it buildable
- [element] → [AppKit component] (queryKey/props), [token/palette], states handled
## Tradeoffs & risks
[What's summarized/hidden/paginated/interactive; overload, scale, a11y, maintenance risks.]
Critique: lead with the top comprehension/integrity issue, cite the component/file, then list
findings by impact, each with the concrete fix (which component/token/state to change).
Anti-patterns
- Producing a design memo with no component plan.
- "Use semantic color" without naming the token/palette.
- Naming a component AppKit doesn't export (e.g. a prebuilt
KpiCard) — compose composites from published primitives instead.
- Adding interaction, pages, or density the task doesn't need (over-engineering a mock-first app).
- Forgetting loading/empty/error states, or KPIs with no freshness/source.
1---2name: databricks-app-design3description: Data App Design4---56# Data App Design78Make Databricks data + AI apps that communicate clearly and compile to real AppKit code. This9skill merges two bodies of knowledge and binds them to implementation:1011- **Composition** — what to show, how much to abstract, how to lay it out → `references/dashboard-patterns.md`12- **Notation** — make comparable things look comparable; honest scales; scenario marks → `references/ibcs-notation.md`13- **Implementation** — the exact AppKit components, hooks, and tokens to use → `references/appkit-cheatsheet.md`1415Design advice that doesn't name a real component is incomplete. Always end at a component plan.1617## When to use / when NOT18- USE for: dashboard/overview/KPI pages, reports, metric/ontology pages, variance analysis, and Genie/NL data surfaces — design *or* critique.19- Do NOT use for: authoring managed **AI/BI (Lakeview) dashboards** (→ `databricks-aibi-dashboards`), generic frontend (forms, auth, settings, marketing), or scaffolding/build/deploy (→ `databricks-apps`). If a request is "add a form", "deploy this", or "build a Lakeview / AI-BI dashboard", this skill should not fire.20- Relationship: `databricks-apps` builds/runs the app; this skill decides what the data screens should look like and which primitives realize them.2122## Workflow231. **Frame** — audience, the decision/question, refresh cadence, device, primary task. One sentence.242. **Genre** — pick the closest from `dashboard-patterns.md` (static / analytic / magazine / infographic / repository / embedded mini). State it.253. **Compose** — choose content + composition patterns (data abstraction, meta-info, layout, interaction, color). Make the tradeoff explicit: what's summarized, hidden, paginated, or made interactive — and why.264. **Apply notation** — run the relevant `ibcs-notation.md` rules: message-in-title, scenario marks (actual/PY/plan/forecast), honest scales, semantic color. On any chart-vocabulary conflict, **IBCS wins** (see the conflict note in that file).275. **Bind to components** — map every element to a primitive that's actually **exported from `@databricks/appkit` / `@databricks/appkit-ui`** (see `appkit-cheatsheet.md`); never cite a component AppKit doesn't ship. There's no prebuilt KPI/trend/distribution card — compose those from primitives, following the notation rules. Use `colorPalette` + semantic tokens, never hardcoded hex. Bind data with `useAnalyticsQuery`/`queryKey` + `sql.*` params.286. **Cover the states** — every data view must handle loading / empty / error / partial (see checklist).297. **Review** — run the checklists in both reference files; lead critiques with the highest-impact comprehension or integrity issue, citing the affected component/file.3031## Required states & data realism (non-negotiable for data apps)32- **Loading** → `Skeleton`; **Empty** → `Empty` with a useful next action; **Error** → inline message, never a blank panel; **Partial/stale** → show what you have + a freshness note.33- Every KPI shows unit + period + comparison + **freshness/source** (mirror the metric definition; don't show a number with no provenance).34- Large tables → server-side pagination/sort/filter, not client-side over a huge result set.35- Long-running queries → optimistic loading + timeout/error UX.3637## AI / Genie surfaces (the "AI" half)38**Gate:** this section applies **only** if the app has a Genie / chat / natural-language / "ask your data" surface. For a pure dashboard / KPI / report app with no conversational input, **skip this section and `references/genie-ai-trust.md` entirely.** When it does apply, implement ALL five (code in `references/genie-ai-trust.md`):39A Genie/chat/NL answer is only trustworthy if the user can see how it was produced and who it ran as. "Use `GenieChat` + a spinner" is NOT enough — for ANY Genie/chat surface, ship all five (copy the exact snippets from the reference):401. **Identity** — a `/api/whoami` route (real `x-forwarded-email`/`x-forwarded-user` headers) + the signed-in user in a `Badge`. Claim OBO **only if `user_api_scopes: [dashboards.genie]` is wired**; otherwise disclose the query runs as the app's service principal.412. **Generated SQL** — render `attachments[].query` in an inspectable "Generated SQL" `Card`; never hide how the answer was computed.423. **Streaming/status** — reflect `useGenieChat().status` (`streaming`/`error`), never a frozen spinner.434. **Disclaimer** — a persistent "AI-generated — verify" note per answer.445. **Governance + states** — `genie()` space config + a truthful execution-identity note (OBO when user-scoped, else service principal) + empty/error/ambiguous handling (`Empty`, `Alert`).4546## Output formats4748**Design proposal:**49```markdown50## Direction51[Genre, audience, primary task, design intent.]52## Pattern & notation choices53- Composition: [data info, meta info, layout, interaction, color]54- Notation: [message, scenario marks, scales, semantic color]55## Component plan ← the part that makes it buildable56- [element] → [AppKit component] (queryKey/props), [token/palette], states handled57## Tradeoffs & risks58[What's summarized/hidden/paginated/interactive; overload, scale, a11y, maintenance risks.]59```6061**Critique:** lead with the top comprehension/integrity issue, cite the component/file, then list62findings by impact, each with the concrete fix (which component/token/state to change).6364## Anti-patterns65- Producing a design memo with no component plan.66- "Use semantic color" without naming the token/palette.67- Naming a component AppKit doesn't export (e.g. a prebuilt `KpiCard`) — compose composites from published primitives instead.68- Adding interaction, pages, or density the task doesn't need (over-engineering a mock-first app).69- Forgetting loading/empty/error states, or KPIs with no freshness/source.