Org Skills

lwc-development

Build production-grade Salesforce Lightning Web Components (LWC) — component design, @wire vs imperative Apex, Lightning Data Service (LDS) and UI API, Lightning Message Service, events and composition, SLDS 2 styling and Lightning Base Components, Experience Cloud (LWR) sites, LWC in Flow screens, governor-limit-aware UI patterns, and security (CRUD/FLS, Locker/Lightning Web Security).

Download .zip Raw Source
When agents use itUse this whenever the user mentions LWC, Lightning Web Components, Aura migration, Lightning App Builder, Experience Cloud components, Salesforce frontend, @wire, lightning-record-form, lightning-datatable, Lightning Message Channel, or asks how to build UI on the Salesforce platform. Also apply it when reviewing LWC code.

Install

Copilot (VS Code, Visual Studio, Copilot CLI and github.com) reads skills from the repository — commit them so the whole team gets them.

npx skills add AGCO-Global/org-skills --skill lwc-development -a github-copilot
# or with the org installer (adds .github/skills/lwc-development):
npx -y github:AGCO-Global/org-skills add skill lwc-development

Uses the open skills CLI. Works with Claude Code, Codex, Cursor, Copilot, Gemini CLI, OpenCode, Windsurf and 60+ others — it asks which agent to install into.

npx skills add AGCO-Global/org-skills --skill lwc-development
# user-level instead of project-level:
npx skills add AGCO-Global/org-skills --skill lwc-development -g

Installs the salesforce-lwc-skills plugin, which bundles all Salesforce / LWC skills and keeps them updated.

/plugin marketplace add AGCO-Global/org-skills
/plugin install salesforce-lwc-skills@org-skills
# or just this skill, in this repository:
npx skills add AGCO-Global/org-skills --skill lwc-development -a claude-code

Use Download .zip above, then upload it under Customize → Skills → Upload skill. Team and Enterprise admins can sync this repo as a plugin marketplace instead.

Installs into .agents/skills/, which Codex reads.

npx skills add AGCO-Global/org-skills --skill lwc-development -a codex

Installs into Cursor's skills folder.

npx skills add AGCO-Global/org-skills --skill lwc-development -a cursor

Installs into Gemini CLI's skills folder.

npx skills add AGCO-Global/org-skills --skill lwc-development -a gemini-cli

Any tool with rules, instructions or custom prompts: use Copy SKILL.md above and paste it in. It is plain Markdown.

Commands use your normal git sign-in to GitHub, so they work while the repository is private. Node.js 20+ required.

Skill contents

Salesforce LWC Development

LWC is standard web components plus a platform that punishes sloppy data access with governor limits, sharing violations, and slow pages. The best LWC engineers get data through the platform's cached services first and write Apex last.

1. Data access decision — in this order

Need Use Why
Show/edit one record's fields lightning-record-form / lightning-record-view-form / lightning-record-edit-form Zero Apex, FLS enforced, LDS cache, layout-aware
Read fields of the current record @wire(getRecord, { recordId, fields }) + getFieldValue Cached via LDS; reactive to updates
Create/update/delete one record createRecord / updateRecord / deleteRecord from lightning/uiRecordApi Cache-aware, no Apex, no DML limits on your side
Picklist values, object info getPicklistValues, getObjectInfo (lightning/uiObjectInfoApi) Cached, respects record types
Related lists lightning/uiRelatedListApi (getRelatedListRecords) Cached, respects layout
Lists with filtering/aggregation/joins Apex @AuraEnabled(cacheable=true) with @wire Only when UI API can't express the query
Mutations with business logic, multiple objects, callouts Apex imperative call (await method({...})) Needs WITH USER_MODE/security check
Complex search (SOSL) Apex cacheable
GraphQL flexibility (multiple objects, pagination) lightning/uiGraphQLApi (gql) Cached, declarative

Reach for Apex only after confirming the UI API can't do it. Every Apex method is code to test, secure, and maintain.

2. Component design

  • One responsibility per component. Composite screens are containers (own data, handle events) with child presentational components (receive @api props, emit events).
  • Public API: @api properties with JSDoc; getters for derived values (never store computed state).
  • Communication: parent → child via @api and public methods; child → parent via CustomEvent (this.dispatchEvent(new CustomEvent('select', { detail: { id } }))); unrelated components via Lightning Message Service (lightning/messageService + a MessageChannel metadata file). Avoid pubsub libraries.
  • Events: lowercase, no on prefix, no hyphens in the name; bubbles: false, composed: false by default; escalate to bubbles: true only when crossing one level.
  • Slots for layout composition (<slot name="actions">).
  • Reactivity: fields are reactive; arrays/objects need reassignment (this.items = [...this.items, x]), not mutation. @track only for deep mutation of objects you can't reassign — rare.
  • Lifecycle: connectedCallback for setup that needs the DOM parent (subscriptions), renderedCallback guarded with a flag (it runs on every render), disconnectedCallback to unsubscribe LMS and remove listeners. Never fetch in renderedCallback.
  • Async: async/await with try/catch; errors surfaced via lightning/platformShowToastEvent or an inline <template lwc:if={error}> message. Use reduceErrors-style helpers to flatten error.body.message / pageErrors / fieldErrors.
  • Templates: lwc:if / lwc:elseif / lwc:else (not if:true), for:each with key, lwc:ref for element access, lwc:spread for prop forwarding.

3. Wire vs imperative — the rule

  • @wire for read data that should stay in sync. It's declarative, cached, and refreshes on refreshApex or when LDS knows the record changed.
  • Imperative for mutations and reads that depend on user action (search on click). After an imperative mutation via Apex, call refreshApex(this.wiredResult) or notifyRecordUpdateAvailable (lightning/uiRecordApi) so LDS-backed components update.
  • Wired Apex must be cacheable=true; cached methods cannot do DML.
  • Wire parameters are reactive with $recordId syntax; guard against undefined on first render.

4. Apex written for LWC

Every @AuraEnabled method the frontend calls:

  • with sharing on the class (or inherited sharing for utilities); use WITH USER_MODE in SOQL/SOSL and Database.insert(records, AccessLevel.USER_MODE) for DML so CRUD/FLS is enforced by the platform.
  • Bulk-safe signature — accept a List<Id>/wrapper, not one Id per call, so the UI can batch.
  • Return DTO wrapper classes (public class OrderRow { @AuraEnabled public Id id; ... }) instead of raw SObjects when the UI needs shaped data. Keeps the contract stable and hides fields the UI shouldn't see.
  • Throw AuraHandledException with user-safe messages; log the real error to a custom logging object/Platform Event.
  • Server-side pagination (LIMIT/OFFSET or keyset) for lists; never return thousands of rows to the browser.
  • Cacheable reads separated from mutations in different methods (or classes).
  • Test class covers positive, negative (no access), and bulk paths — see salesforce-frontend-testing.

5. Styling and UX

  • Lightning Base Components first (lightning-button, lightning-input, lightning-datatable, lightning-card, lightning-combobox). They are accessible, themed, and mobile-tested.
  • SLDS 2 styling hooks (--slds-g-* global tokens, --slds-c-* component hooks) to customise; never override base component internals or use /deep/.
  • Own CSS is scoped per component; use the :host selector for the root. For shared styles, a CSS-only module component imported with import sharedStyles from 'c/sharedStyles' and static stylesheets = [sharedStyles].
  • Layout with lightning-layout / SLDS grid classes; responsive by default; test in App Builder small/large device previews.
  • Loading with lightning-spinner inside a relative container; empty states designed, not blank; errors inline near the action.
  • Icons via lightning-icon with utility/standard sets; custom SVG as a static resource.
  • Never hardcode labels — use Custom Labels (@salesforce/label/c.My_Label) for i18n.

6. Accessibility

  • Base components handle most a11y; when using raw HTML, add aria-*, role, focus management, and keyboard handlers.
  • Every icon-only button has alternative-text; every form input a label (or variant="label-hidden" with label set).
  • Test with the sa11y Jest matcher and screen reader on at least one key flow.

7. Platform surfaces

  • Lightning App Builder / Record pages: expose @api recordId, @api objectApiName; declare targets and targetConfigs in js-meta.xml with typed design properties and default values so admins configure without code.
  • Flow screens: lightning__FlowScreen target; @api inputs/outputs; dispatch FlowAttributeChangeEvent on change and FlowNavigationNextEvent for navigation; validate via @api validate().
  • Experience Cloud (LWR): no Aura, no lightning/navigation shortcuts that assume internal app; use lightning__ServiceCloud/lightningCommunity__Page targets, guest-user sharing considerations, lightning/navigation with standard__webPage; performance budget matters — LWR pages are public.
  • Quick actions: lightning__RecordAction with actionType="ScreenAction"; close via CloseActionScreenEvent.
  • Utility bar / Console: lightning/platformWorkspaceApi for tab management.
  • Mobile: Salesforce Mobile App renders LWCs — test touch targets and offline behaviour with LWC Offline (Mobile Offline / Field Service) if relevant.

8. Security

  • Lightning Web Security (LWS) is the runtime; avoid eval, innerHTML with user data, and dynamic import() of third-party code. Third-party libraries load from static resources via loadScript/loadStyle only.
  • Trust nothing from @api inputs in a public Experience site — validate server-side.
  • CRUD/FLS: enforced in Apex with USER_MODE; UI hides fields but never relies on hiding as security.
  • CSP Trusted Sites for any external URL fetched from the browser.
  • Never put secrets in JS or static resources; use Named Credentials in Apex.

9. Delivery

  • Source-format project (sfdx-project.json), scratch orgs for dev, unlocked packages or CI deploy to sandboxes; sf CLI, not sfdx.
  • ESLint with @salesforce/eslint-config-lwc/recommended; Prettier with the Apex plugin; Jest with @salesforce/sfdx-lwc-jest; PMD for Apex.
  • Code review checklist: data-access decision justified, USER_MODE present, labels externalised, events named correctly, renderedCallback guarded, tests present.

Anti-patterns to flag

  • Apex for something lightning-record-form or getRecord does.
  • @wire method that isn't cacheable=true, or cacheable methods doing DML.
  • Imperative Apex on every keystroke without debounce.
  • renderedCallback fetching data or mutating tracked state without a guard (infinite loop).
  • Mutating arrays in place and wondering why the template didn't update.
  • Global window state or pub/sub helpers instead of LMS.
  • Custom-built inputs/buttons duplicating base components (and losing a11y).
  • SOQL in a loop or unbulkified Apex serving a datatable.
  • Hardcoded record type ids, profile names, or labels.
  • Aura components for new work.