Skip to content
Development
Skill

/experience-ui-bundle-salesforce-data-access

MUST activate whenever a uiBundles/*/src/ project reads, writes, or displays Salesforce data — INCLUDING building a page, list, table, card grid, dashboard, or form that shows, filters, counts, or edits records of any object (e.g. Property__c, Account, Case), even when the

From plugin
sf-skills
1.1k200 skills6 agents15 commands4 MCP

Claude Code

$ npx -y skills add forcedotcom/sf-skills --skill experience-ui-bundle-salesforce-data-access --agent claude-code

SKILL.md

experience-ui-bundle-salesforce-data-access.SKILL.md
name: experience-ui-bundle-salesforce-data-access
description: "MUST activate whenever a uiBundles/*/src/ project reads, writes, or displays Salesforce data — INCLUDING building a page, list, table, card grid, dashboard, or form that shows, filters, counts, or edits records of any object (e.g. Property__c, Account, Case), even when the prompt names only the UI or the object and never says query, GraphQL, or SDK. Records behind such a component come from Salesforce, so use this ALONGSIDE experience-ui-bundle-frontend-generate: that skill styles the component, this one wires its data. Also triggers on @salesforce/platform-sdk imports, sdk.graphql.query / mutate / sdk.fetch calls, *.graphql files, or stale data needing force-refresh. New read/write work uses the current @salesforce/platform-sdk API; migrate only EXISTING old @salesforce/sdk-data callable code. Not for pure styling/layout with no records, app shell, file upload, or auth/search scaffolding. DO NOT TRIGGER for OAuth, object/field schema changes, Bulk/Tooling/Metadata API, or declarative automation."
metadata:
  version: "2.2"
  domains: ["Experience", "Platform"]
  minApiVersion: "66.0"
  relatedSkills:
    - "experience-ui-bundle-frontend-generate"
    - "platform-metadata-deploy"
  cliTools:
    - tool: ["node"]
      semver: ">=18.0.0"
    - tool: ["npm"]
      semver: ">=9.0.0"
    - tool: ["npx"]
      semver: ">=9.0.0"
    - tool: ["sf"]
      semver: ">=2.0.0"

Salesforce Data Access (UI bundles)

All Salesforce data access in a UI bundle goes through the **`@salesforce/platform-sdk`** data SDK. The SDK handles auth, CSRF, and base-URL resolution, and — on the WebApp surface — caches every GraphQL query by default.

This file is the **workflow + guardrail spine**. Depth lives in linked docs:

  • **[references/graphiti-cli.md](references/graphiti-cli.md)** — the **`graphiti` CLI** (`sf-gql-*`

commands) that compiles a small JSON spec into a schema-correct, guardrail-applied query + variables + types. The preferred way to author the GraphQL in steps below; falls back to the schema-grep script when unavailable.

  • **[references/sdk-api.md](references/sdk-api.md)** — `query`/`mutate` call surface + generated-type

placement; the behavior nuance (surfaces, error stances, `QueryResult`) grounds on **tier-2b**.

  • **[references/caching.md](references/caching.md)** — the on-by-default cache + two refresh modes;

behavior grounds on **tier-2b** `docs/data/` when installed, with the full version-stamped fallback here.

  • **[references/graphql-hand-authoring.md](references/graphql-hand-authoring.md)** — schema lookup, read /

mutation templates, every platform guardrail (`@optional`, pagination, limits, semi-join, wrappers, error table…).

  • **[references/rest-and-integration.md](references/rest-and-integration.md)** — `sdk.fetch`,

the supported-API allowlist, and the reactive/lifecycle integration patterns.

  • **[references/migration.md](references/migration.md)** — old `@salesforce/sdk-data` callable code

→ new namespace. The **only** place the dead API appears as usable code.

The one-paragraph mental model

`const sdk = await createDataSDK()`. Then `sdk.graphql` is a **namespace**, not a function: **`sdk.graphql!.query({...})`** for reads, **`sdk.graphql!.mutate({...})`** for writes. On WebApp, **every `query()` is cached by default** (300s). HTTP 200 never means success — always check `result.errors`. Verify every entity and field against the schema before you query it: one unverified field fails the *whole* query at runtime, and `schema.graphql` is too large to eyeball — look it up.

import { createDataSDK, gql } from "@salesforce/platform-sdk"; // gql tags the query string so codegen + eslint validate it

const sdk = await createDataSDK();
const result = await sdk.graphql!.query({ query: GET_ACCOUNTS, variables });
if (result.errors?.length) throw new Error(result.errors.map((e) => e.message).join("; "));
const rows = result.data?.uiapi?.query?.Account?.edges?.map((e) => e.node) ?? []; // unwrap edges/node; read field values via .value

Typed call params (`query<GetAccountsQuery, GetAccountsQueryVariables>`), the `CacheControl` type, and `NodeOfConnection<T>` (extracts a node type from a Connection for clean typing) all live in [references/sdk-api.md](references/sdk-api.md).

> **This changed (breaking — PR #502).** The previous callable `sdk.graphql(...)` form and the > previous package name are **dead** — the code above is the only correct form. If you encounter > the old API in existing code (or a stale `dist/` artifact), don't copy it; convert it per > [Working on existing code](#working-on-existing-code-migration). > > **`sdk.graphql!` is WebApp-only.** The non-null assertion above is correct *only* if the > bundle runs solely on WebApp. On other surfaces it can crash — decide before you write it. > See **[Surfaces — `!` vs guard](#surfaces--sdkgraphql-vs-guard)** below.

---

Ground the SDK contract on the installed types (tier-2a)

`@salesforce/platform-sdk` force-publishes on a shared version line and moves fast. This SKILL's prose is a point-in-time snapshot of the call contract; the **installed declarations are authoritative for the version you actually have**. Before writing any `query`/`mutate`, read the installed types and let them win:

  • `node_modules/@salesforce/platform-sdk/dist/core/data.d.ts` — `query`/`mutate`

signatures, `QueryResult` (has `subscribe`/`refresh`) vs `MutationResult` (has neither, by design), the `CacheControl` union, the default TTL.

  • `node_modules/@salesforce/platform-sdk/dist/data/index.d.ts` — `createDataSDK`,

`gql`, `NodeOfConnection`.

**Precedence — installed `.d.ts` beats this SKILL's prose.** If a signature, type, or default here disagrees with the installed declaration, follow the declaration and note the drift; do not "correct" the types to match the prose.

**Grounding ladder** (one model, two axes):

| Tier | Grounds | Answers

Read more
@forcedotcom
Ships withsf-skills

This repository provides Salesforce agent skills, plugins, and sample apps for building applications.

1.1k200 skills6 agents4 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.1k
Star history of forcedotcom/sf-skills on GitHub, a chart by star-history.com

Other skills on sf-skills.

agentforce-observe

agentforce-observe

Analyze production Agentforce agent behavior using session traces and Data Cloud, and manage Agent Health Monitoring (AHM)…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about experience-ui-bundle-salesforce-data-access.

Which coding agents can use experience-ui-bundle-salesforce-data-access?
experience-ui-bundle-salesforce-data-access installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.