afv-library/skills/using-webapp-graphql/SKILL.md
k-j-kim 9ba064174a
feat: syncing webapp skills sync to afv @W-21338965@ (#57)
* feat: removing old webapp skills

* feat: adding sync of skills from webapps to afv

* feat: adding the first iteration of skills

* feat: pin template deps to latest npm versions and flatten skill folders

- Add pin-template-deps.js to resolve "*" deps to exact npm versions
- Integrate pinning into sync-template-skills npm script
- Remove check-template-skills-versions.js (no longer needed)
- Simplify workflow to single sync step
- Flatten skill output: one folder per skill with cleaned names

Made-with: Cursor

* fix: resolve skill validation errors

- Move .template-versions.json from skills/ to root
- Shorten skill names to meet 64-char limit:
  - salesforce-webapp-feature-micro-frontend-generating-micro-frontend-lwc → salesforce-webapp-micro-frontend-lwc
  - salesforce-webapp-feature-react-agentforce-conversation-client-integrating-agentforce-conversation-client → salesforce-webapp-agentforce-conversation-client
  - salesforce-webapp-feature-react-file-upload-implementing-file-upload → salesforce-webapp-react-file-upload
- Expand descriptions to meet 20-word minimum with trigger context

* Add webapp skills from template, sync script updates

- Rename skill folders from salesforce-webapp-* to *-webapp-* convention
- Update sync-template-skills.js: set SKILL.md front matter name to dest folder
- Remove sync-template-skills workflow and pin-template-deps script
- Add .synced-template-skills.json manifest, deploying-webapp-to-salesforce skill
- Replace salesforce-webapp-designing-webapp-ui-ux with designing-webapp-ui-ux

Made-with: Cursor

* Align SKILL.md front matter name with folder for all webapp skills

Made-with: Cursor

* Fix skill validation: description length and trigger context for configuring-webapp-metadata, creating-webapp

Made-with: Cursor

* Rename sync script to sync-webapp-skills, drop manifest file

- Rename sync-template-skills.js to sync-webapp-skills.js
- Update package.json script to sync-webapp-skills
- Remove .synced-template-skills.json creation and add to .gitignore

Made-with: Cursor

* Revert sync-react-b2e-sample and sync-react-b2x-sample to upstream version

Made-with: Cursor

* Sync script: pin b2e and b2x to latest, sync skills from template

- Pin both template packages to latest in sync-webapp-skills.js
- Update package.json / package-lock.json (b2x 1.109.0)
- Sync skills: managing-webapp-agentforce-conversation-client, bar-line-chart,
  remove building-webapp-analytics-charts and integrating-webapp-agentforce-conversation-client
- Minor skill content updates

Made-with: Cursor

* Remove interactive map, weather widget, and Unsplash skills (no longer in template)

Made-with: Cursor

---------

Co-authored-by: Hemant Singh Bisht <hsinghbisht@salesforce.com>
2026-03-19 22:46:27 +05:30

12 KiB

name description paths
using-webapp-graphql Salesforce GraphQL data access. Use when the user asks to fetch, query, or mutate Salesforce data, or add a GraphQL operation for an object like Account, Contact, or Opportunity.
**/*.ts
**/*.tsx
**/*.graphql

Salesforce GraphQL

Guidance for querying and mutating Salesforce data via the Salesforce GraphQL API. Use createDataSDK() + sdk.graphql?.() and codegen tooling.

When to Use

  • User asks to "fetch data from Salesforce"
  • User asks to "query" or "mutate" Salesforce records
  • User wants to add a new GraphQL operation (query or mutation)
  • User asks to add data access for a Salesforce object (Account, Contact, Opportunity, etc.)

Schema Access Policy (GREP ONLY)

GREP ONLY — The schema.graphql file is very large (~265,000+ lines). All schema lookups MUST use the grep-only commands defined in the exploring-graphql-schema skill. Do NOT open, read, stream, or parse ./schema.graphql with any tool other than grep.

Directory Context

The generated app has a two-level directory structure. Commands must run from the correct directory.

<project-root>/                                            ← SFDX project root
├── schema.graphql                                         ← grep target
├── sfdx-project.json
└── force-app/main/default/webapplications/<app-name>/     ← webapp dir
    ├── package.json         (npm scripts: graphql:schema, graphql:codegen, lint)
    ├── eslint.config.js     (schema ref: ../../../../../schema.graphql)
    ├── codegen.yml          (schema ref: ../../../../../schema.graphql)
    └── src/                 (source code, .graphql query files)
Command Run from Why
npm run graphql:schema webapp dir Script is in webapp's package.json
npm run graphql:codegen webapp dir Reads codegen.yml in webapp dir
npx eslint <file> webapp dir Reads eslint.config.js in webapp dir
grep ... schema.graphql project root schema.graphql lives at project root
sf api request graphql project root Needs sfdx-project.json

Wrong directory = silent failures. npm run graphql:schema from the project root will fail with "missing script." grep ./schema.graphql from the webapp dir will fail with "no such file."

Prerequisites

The base React app (base-react-app) ships with all GraphQL dependencies and tooling pre-configured:

  • @salesforce/sdk-data — runtime SDK for createDataSDK and gql
  • @graphql-codegen/cli + plugins — type generation from .graphql files and inline gql queries
  • @graphql-eslint/eslint-plugin — validates .graphql files and gql template literals against schema.graphql (used as a query validation gate — see Step 6)
  • graphql — shared by codegen, ESLint, and schema introspection

Before using this skill, ensure:

  1. The @salesforce/sdk-data package is available (provides createDataSDK, gql, NodeOfConnection)
  2. Deployment order: Metadata must be deployed before schema fetch; schema must be refetched after any metadata deployment. Invoke the deploying-to-salesforce skill when deploying or syncing with the org.
  3. A schema.graphql file exists at the project root. If missing, generate it:
    # Run from webapp dir (force-app/main/default/webapplications/<app-name>/)
    npm run graphql:schema
    

npm Scripts

  • npm run graphql:schema(run from webapp dir) Downloads the full GraphQL schema from a connected Salesforce org via introspection. Outputs schema.graphql to the project root.
  • npm run graphql:codegen(run from webapp dir) Generates TypeScript types from .graphql files and inline gql queries. Outputs to src/api/graphql-operations-types.ts.

Workflow

Step 1: Download Schema

Ensure schema.graphql exists at the project root. If missing, run npm run graphql:schema from the webapp dir.

Step 2: Explore the Schema (grep-only)

Before writing any query, verify the target object and its fields exist in the schema.

Invoke the exploring-graphql-schema skill for the full exploration workflow and mandatory grep-only access policy.

GREP ONLY — All schema lookups MUST use the grep commands defined in the exploring-graphql-schema skill. Do NOT open, read, stream, or parse ./schema.graphql with any tool other than grep.

Key actions (all via grep):

  • type <ObjectName> implements Record — find available fields
  • input <ObjectName>_Filter — find filter options
  • input <ObjectName>_OrderBy — find sorting options
  • input <ObjectName>CreateInput / <ObjectName>UpdateInput — find mutation input types

Step 3: Choose the Query Pattern

Pattern 1 — External .graphql file (recommended for complex queries):

  • Queries with variables, fragments, or shared across files
  • Full codegen support, syntax highlighting, shareable
  • Requires codegen step after changes
  • See example: api/utils/accounts.ts + api/utils/query/highRevenueAccountsQuery.graphql

Pattern 2 — Inline gql tag (recommended for simple queries):

  • Simple queries without variables; colocated with usage code
  • Supports dynamic queries (field set varies at runtime)
  • MUST use gql tag — plain template strings bypass @graphql-eslint validation
  • See example: api/utils/user.ts

Step 4: Write the Query

For Pattern 1:

  1. Create a .graphql file under src/api/utils/query/
  2. Follow UIAPI structure: query { uiapi { query { ObjectName(...) { edges { node { ... } } } } } }
  3. For mutations, invoke the generating-graphql-mutation-query skill
  4. For read queries, invoke the generating-graphql-read-query skill

For Pattern 2:

  1. Define query inline using the gql template tag
  2. Ensure the query name matches what codegen expects

Step 5: Test Queries Against Live Org

Use the testing workflows in the generating-graphql-read-query and generating-graphql-mutation-query skills to validate queries against the connected org before integrating into the app.

Step 6: Generate Types

# Run from webapp dir (force-app/main/default/webapplications/<app-name>/)
npm run graphql:codegen

This updates src/api/graphql-operations-types.ts with <OperationName>Query/<OperationName>Mutation and <OperationName>QueryVariables/<OperationName>MutationVariables.

Step 7: Lint Validate

Run ESLint on the file containing the query to validate it against the schema before any live testing:

# Run from webapp dir
npx eslint <path-to-file>

The @graphql-eslint/eslint-plugin processor extracts GraphQL from gql template literals and validates them against schema.graphql. Fix all ESLint errors before proceeding.

Step 8: Implement and Verify

Implement the data access function using the pattern below. Use the Quality Checklist before completing.


Core Types & Function Signatures

createDataSDK and graphql

import { createDataSDK } from "@salesforce/sdk-data";

const sdk = await createDataSDK();
const response = await sdk.graphql?.<ResponseType, VariablesType>(query, variables);

createDataSDK() returns a DataSDK instance. The graphql method uses optional chaining (?.) because not all surfaces support GraphQL.

gql Template Tag

import { gql } from "@salesforce/sdk-data";

const MY_QUERY = gql`
  query MyQuery {
    uiapi { ... }
  }
`;

The gql tag enables ESLint validation against the schema. Plain template strings bypass validation.

Error Handling

Default: treat any errors as failure (Strategy A). For partial data tolerance, log errors but use data. For mutations where some return fields are inaccessible, use Strategy C (fail only when no data).

// Default: strict
if (response?.errors?.length) {
  throw new Error(response.errors.map((e) => e.message).join("; "));
}
const result = response?.data;

Responses follow uiapi.query.ObjectName.edges[].node; fields use { value }.

NodeOfConnection

import { type NodeOfConnection } from "@salesforce/sdk-data";

type AccountNode = NodeOfConnection<GetHighRevenueAccountsQuery["uiapi"]["query"]["Account"]>;

Pattern 1: External .graphql File

Create a .graphql file, run npm run graphql:codegen, import with ?raw suffix, and use generated types.

Required imports:

import { createDataSDK, type NodeOfConnection } from "@salesforce/sdk-data";
import MY_QUERY from "./query/myQuery.graphql?raw"; // ← ?raw suffix required
import type { GetMyDataQuery, GetMyDataQueryVariables } from "../graphql-operations-types";

When to use: Complex queries with variables, fragments, or shared across files. Does NOT support dynamic queries (field set varies at runtime).


Pattern 2: Inline gql Tag

Required imports:

import { createDataSDK, gql } from "@salesforce/sdk-data";
import { type CurrentUserQuery } from "../graphql-operations-types";

const MY_QUERY = gql`
  query CurrentUser {
    uiapi { ... }
  }
`;

MUST use gql tag — plain template strings bypass the @graphql-eslint processor entirely, meaning no lint validation against the schema.

When to use: Simple, colocated queries. Supports dynamic queries (field set varies at runtime).


Conditional Field Selection

For dynamic fieldsets with known fields, use @include(if: $condition) and @skip(if: $condition) in .graphql files. See GraphQL spec for details.


Direct API Calls

// NOT RECOMMENDED: Direct axios/fetch calls for GraphQL
// PREFERRED: Use the Data SDK
const sdk = await createDataSDK();
const response = await sdk.graphql?.<ResponseType>(query, variables);

Missing Type Definitions

// NOT RECOMMENDED: Untyped GraphQL calls
// PREFERRED: Provide response type
const response = await sdk.graphql?.<GetMyDataQuery>(query);

Plain String Queries (Without gql Tag)

// NOT RECOMMENDED: Plain strings bypass ESLint validation
const query = `query { ... }`;

// PREFERRED: Use gql tag for inline queries
const QUERY = gql`query { ... }`;

Quality Checklist

If you have not completed the workflow above, stop and complete it first. Invoke the skill workflow before using this checklist.

Before completing GraphQL data access code:

For Pattern 1 (.graphql files):

  1. All field names verified via grep against schema.graphql (invoke exploring-graphql-schema)
  2. Create .graphql file for the query/mutation
  3. Run npm run graphql:codegen to generate types
  4. Import query with ?raw suffix
  5. Import generated types from graphql-operations-types.ts
  6. Use sdk.graphql?.<ResponseType>() with proper generic
  7. Handle response.errors and destructure response.data
  8. Use NodeOfConnection for cleaner node types when needed
  9. Run npx eslint <file> from webapp dir — fix all GraphQL errors

For Pattern 2 (inline with gql):

  1. All field names verified via grep against schema.graphql
  2. Define query using gql template tag (NOT a plain string)
  3. Ensure query name matches generated types in graphql-operations-types.ts
  4. Import generated types for the query
  5. Use sdk.graphql?.<ResponseType>() with proper generic
  6. Handle response.errors and destructure response.data
  7. Run npx eslint <file> from webapp dir — fix all GraphQL errors

General:

  • Lint validation passes (npx eslint <file> reports no GraphQL errors)
  • Query field names match the schema exactly (case-sensitive, confirmed via grep)
  • Response type generic is provided to sdk.graphql?.<T>()
  • Optional chaining is used for nested response data

Reference

  • Schema exploration: invoke the exploring-graphql-schema skill
  • Read query generation: invoke the generating-graphql-read-query skill
  • Mutation query generation: invoke the generating-graphql-mutation-query skill
  • Shared GraphQL schema types: shared-schema.graphqls (in this skill directory)
  • Schema download: npm run graphql:schema (run from webapp dir)
  • Type generation: npm run graphql:codegen (run from webapp dir)