What it isAlways-on coding rules. GitHub Copilot applies them to files matching **/lwc/**; the Claude Code version is a path-scoped rule generated from the same file. Why use instructions →
Install
This repository (recommended)
Adds .github/instructions/lwc.instructions.md — commit it so everyone's Copilot follows the same rules.
Nothing to invoke — edit a matching file and Copilot picks the rules up. Adjust applyTo if your repository layout differs.
This repository (recommended)
Adds .claude/rules/lwc.md — commit it. Claude loads it when it reads a matching file.
npx -y github:AGCO-Global/org-skills add instructions lwc --tool claude
Just for me, every repository
Save it in your user profile instead.
npx -y github:AGCO-Global/org-skills add instructions lwc --tool claude --user
Use it
Nothing to invoke. Adjust the paths globs if your repository layout differs.
Commands run in your repository folder and need Node.js 20+. They use your normal git sign-in to GitHub, so they work while the repository is private. Run npx -y github:AGCO-Global/org-skills list to see everything available.
Settings
name: "Lightning Web Components"
description: "Always-on rules for writing Salesforce Lightning Web Components, their templates, styles, metadata and Jest tests."
applyTo: "**/lwc/**"
Instructions Copilot follows
Lightning Web Components rules
Get data through the platform's cached services first and write Apex last; every Apex method is code to secure, test and maintain.
Data access
Use base record forms (lightning-record-form, -view-form, -edit-form) for single-record view and edit. No Apex, FLS enforced, cached.
Read record fields with @wire(getRecord) and getFieldValue; write with createRecord/updateRecord/deleteRecord from lightning/uiRecordApi.
Use getObjectInfo, getPicklistValues, related list and GraphQL adapters before custom Apex. They respect record types and layouts.
Use @wire for reads that should stay in sync; wired Apex must be @AuraEnabled(cacheable=true) and do no DML.
Call Apex imperatively for mutations and user-triggered reads; debounce search input. One call per keystroke burns limits.
After an imperative mutation, call refreshApex(this.wiredResult) or notifyRecordUpdateAvailable so other components update.
Guard wire handlers against undefined data on first render; reactive params use $recordId.
Prefer several small cacheable wires over one call returning the whole page; paginate server-side, never ship thousands of rows.
Reactivity and lifecycle
Reassign arrays and objects (this.items = [...this.items, item]) instead of mutating them; in-place mutation does not re-render.
Use getters for derived values; do not store computed state.
Use @track only for deep mutation you cannot replace with reassignment.
Set up subscriptions in connectedCallback and remove them in disconnectedCallback. Leaks otherwise.
Never fetch data in renderedCallback, and guard any work there with a flag. It runs on every render.
Use lwc:if/lwc:elseif/lwc:else (not if:true), key on every for:each item, and lwc:ref for element access.
Events and communication
Parent to child through @api properties and methods; child to parent through CustomEvent with data in detail.
Name events lowercase with no on prefix or hyphens; keep bubbles and composed false unless crossing a boundary is required.
Use Lightning Message Service with a MessageChannel for unrelated components; no pub/sub helpers or window globals.
Surface errors with ShowToastEvent or an inline message near the action; flatten error.body into readable text.
Styling and accessibility
Use Lightning Base Components before custom markup. They are accessible and themed.
Customise with SLDS styling hooks (--slds-g-*, --slds-c-*); never reach into base component internals.
Keep CSS scoped to the component with :host; no hard-coded colours where a token exists.
Use Custom Labels (@salesforce/label/c.X) for all user-facing text. Needed for translation.
Give icon-only buttons alternative-text and every input a label (use variant="label-hidden" to hide it visually).
Add role, aria-*, focus handling and keyboard support to any raw interactive HTML.
Security and runtime
Respect Lightning Web Security/Locker: no eval, no innerHTML with user data, no reaching into other components' DOM.
Load third-party libraries from static resources with loadScript/loadStyle, never from a CDN at runtime.
Treat hiding fields in the UI as UX, not security; Apex must enforce access with USER_MODE and with sharing.
Never put secrets in JavaScript or static resources; add external URLs to CSP Trusted Sites.
Declare targets and typed targetConfigs with defaults in js-meta.xml so admins can configure components.
Tests
Write Jest tests with @salesforce/sfdx-lwc-jest in __tests__/<component>.test.js, one behaviour per it.
Mock Apex with jest.mock('@salesforce/apex/...', () => ({ default: jest.fn() }), { virtual: true }); drive wires with .emit(data)/.error(err) and imperative calls with mockResolvedValue/mockRejectedValue.
Emit LDS adapters (getRecord.emit(fixture)) with JSON fixtures in __tests__/data/.
await a promise flush after every emit or action, and remove elements from document.body in afterEach. Prevents flaky, leaking tests.
Assert rendered output, dispatched events, Apex parameters and error branches, and run toBeAccessible() from sa11y.
Go deeper: for larger tasks use the lwc-development, salesforce-frontend-architecture and salesforce-frontend-testing skills, and frontend-code-review before opening a pull request.
---
name: "Lightning Web Components"
description: "Always-on rules for writing Salesforce Lightning Web Components, their templates, styles, metadata and Jest tests."
applyTo: "**/lwc/**"
---
# Lightning Web Components rules
Get data through the platform's cached services first and write Apex last; every Apex method is code to secure, test and maintain.
## Data access
- Use base record forms (`lightning-record-form`, `-view-form`, `-edit-form`) for single-record view and edit. No Apex, FLS enforced, cached.
- Read record fields with `@wire(getRecord)` and `getFieldValue`; write with `createRecord`/`updateRecord`/`deleteRecord` from `lightning/uiRecordApi`.
- Use `getObjectInfo`, `getPicklistValues`, related list and GraphQL adapters before custom Apex. They respect record types and layouts.
- Use `@wire` for reads that should stay in sync; wired Apex must be `@AuraEnabled(cacheable=true)` and do no DML.
- Call Apex imperatively for mutations and user-triggered reads; debounce search input. One call per keystroke burns limits.
- After an imperative mutation, call `refreshApex(this.wiredResult)` or `notifyRecordUpdateAvailable` so other components update.
- Guard wire handlers against `undefined` data on first render; reactive params use `$recordId`.
- Prefer several small cacheable wires over one call returning the whole page; paginate server-side, never ship thousands of rows.
## Reactivity and lifecycle
- Reassign arrays and objects (`this.items = [...this.items, item]`) instead of mutating them; in-place mutation does not re-render.
- Use getters for derived values; do not store computed state.
- Use `@track` only for deep mutation you cannot replace with reassignment.
- Set up subscriptions in `connectedCallback` and remove them in `disconnectedCallback`. Leaks otherwise.
- Never fetch data in `renderedCallback`, and guard any work there with a flag. It runs on every render.
- Use `lwc:if`/`lwc:elseif`/`lwc:else` (not `if:true`), `key` on every `for:each` item, and `lwc:ref` for element access.
## Events and communication
- Parent to child through `@api` properties and methods; child to parent through `CustomEvent` with data in `detail`.
- Name events lowercase with no `on` prefix or hyphens; keep `bubbles` and `composed` false unless crossing a boundary is required.
- Use Lightning Message Service with a `MessageChannel` for unrelated components; no pub/sub helpers or `window` globals.
- Surface errors with `ShowToastEvent` or an inline message near the action; flatten `error.body` into readable text.
## Styling and accessibility
- Use Lightning Base Components before custom markup. They are accessible and themed.
- Customise with SLDS styling hooks (`--slds-g-*`, `--slds-c-*`); never reach into base component internals.
- Keep CSS scoped to the component with `:host`; no hard-coded colours where a token exists.
- Use Custom Labels (`@salesforce/label/c.X`) for all user-facing text. Needed for translation.
- Give icon-only buttons `alternative-text` and every input a `label` (use `variant="label-hidden"` to hide it visually).
- Add `role`, `aria-*`, focus handling and keyboard support to any raw interactive HTML.
## Security and runtime
- Respect Lightning Web Security/Locker: no `eval`, no `innerHTML` with user data, no reaching into other components' DOM.
- Load third-party libraries from static resources with `loadScript`/`loadStyle`, never from a CDN at runtime.
- Treat hiding fields in the UI as UX, not security; Apex must enforce access with `USER_MODE` and `with sharing`.
- Never put secrets in JavaScript or static resources; add external URLs to CSP Trusted Sites.
- Declare `targets` and typed `targetConfigs` with defaults in `js-meta.xml` so admins can configure components.
## Tests
- Write Jest tests with `@salesforce/sfdx-lwc-jest` in `__tests__/<component>.test.js`, one behaviour per `it`.
- Mock Apex with `jest.mock('@salesforce/apex/...', () => ({ default: jest.fn() }), { virtual: true })`; drive wires with `.emit(data)`/`.error(err)` and imperative calls with `mockResolvedValue`/`mockRejectedValue`.
- Emit LDS adapters (`getRecord.emit(fixture)`) with JSON fixtures in `__tests__/data/`.
- `await` a promise flush after every emit or action, and remove elements from `document.body` in `afterEach`. Prevents flaky, leaking tests.
- Assert rendered output, dispatched events, Apex parameters and error branches, and run `toBeAccessible()` from sa11y.
Go deeper: for larger tasks use the lwc-development, salesforce-frontend-architecture and salesforce-frontend-testing skills, and frontend-code-review before opening a pull request.
---
paths:
- "**/lwc/**"
---
<!-- Lightning Web Components — generated from instructions/salesforce/lwc/lwc.instructions.md for Claude Code. Edit that file, not this one. -->
# Lightning Web Components rules
Get data through the platform's cached services first and write Apex last; every Apex method is code to secure, test and maintain.
## Data access
- Use base record forms (`lightning-record-form`, `-view-form`, `-edit-form`) for single-record view and edit. No Apex, FLS enforced, cached.
- Read record fields with `@wire(getRecord)` and `getFieldValue`; write with `createRecord`/`updateRecord`/`deleteRecord` from `lightning/uiRecordApi`.
- Use `getObjectInfo`, `getPicklistValues`, related list and GraphQL adapters before custom Apex. They respect record types and layouts.
- Use `@wire` for reads that should stay in sync; wired Apex must be `@AuraEnabled(cacheable=true)` and do no DML.
- Call Apex imperatively for mutations and user-triggered reads; debounce search input. One call per keystroke burns limits.
- After an imperative mutation, call `refreshApex(this.wiredResult)` or `notifyRecordUpdateAvailable` so other components update.
- Guard wire handlers against `undefined` data on first render; reactive params use `$recordId`.
- Prefer several small cacheable wires over one call returning the whole page; paginate server-side, never ship thousands of rows.
## Reactivity and lifecycle
- Reassign arrays and objects (`this.items = [...this.items, item]`) instead of mutating them; in-place mutation does not re-render.
- Use getters for derived values; do not store computed state.
- Use `@track` only for deep mutation you cannot replace with reassignment.
- Set up subscriptions in `connectedCallback` and remove them in `disconnectedCallback`. Leaks otherwise.
- Never fetch data in `renderedCallback`, and guard any work there with a flag. It runs on every render.
- Use `lwc:if`/`lwc:elseif`/`lwc:else` (not `if:true`), `key` on every `for:each` item, and `lwc:ref` for element access.
## Events and communication
- Parent to child through `@api` properties and methods; child to parent through `CustomEvent` with data in `detail`.
- Name events lowercase with no `on` prefix or hyphens; keep `bubbles` and `composed` false unless crossing a boundary is required.
- Use Lightning Message Service with a `MessageChannel` for unrelated components; no pub/sub helpers or `window` globals.
- Surface errors with `ShowToastEvent` or an inline message near the action; flatten `error.body` into readable text.
## Styling and accessibility
- Use Lightning Base Components before custom markup. They are accessible and themed.
- Customise with SLDS styling hooks (`--slds-g-*`, `--slds-c-*`); never reach into base component internals.
- Keep CSS scoped to the component with `:host`; no hard-coded colours where a token exists.
- Use Custom Labels (`@salesforce/label/c.X`) for all user-facing text. Needed for translation.
- Give icon-only buttons `alternative-text` and every input a `label` (use `variant="label-hidden"` to hide it visually).
- Add `role`, `aria-*`, focus handling and keyboard support to any raw interactive HTML.
## Security and runtime
- Respect Lightning Web Security/Locker: no `eval`, no `innerHTML` with user data, no reaching into other components' DOM.
- Load third-party libraries from static resources with `loadScript`/`loadStyle`, never from a CDN at runtime.
- Treat hiding fields in the UI as UX, not security; Apex must enforce access with `USER_MODE` and `with sharing`.
- Never put secrets in JavaScript or static resources; add external URLs to CSP Trusted Sites.
- Declare `targets` and typed `targetConfigs` with defaults in `js-meta.xml` so admins can configure components.
## Tests
- Write Jest tests with `@salesforce/sfdx-lwc-jest` in `__tests__/<component>.test.js`, one behaviour per `it`.
- Mock Apex with `jest.mock('@salesforce/apex/...', () => ({ default: jest.fn() }), { virtual: true })`; drive wires with `.emit(data)`/`.error(err)` and imperative calls with `mockResolvedValue`/`mockRejectedValue`.
- Emit LDS adapters (`getRecord.emit(fixture)`) with JSON fixtures in `__tests__/data/`.
- `await` a promise flush after every emit or action, and remove elements from `document.body` in `afterEach`. Prevents flaky, leaking tests.
- Assert rendered output, dispatched events, Apex parameters and error branches, and run `toBeAccessible()` from sa11y.
Go deeper: for larger tasks use the lwc-development, salesforce-frontend-architecture and salesforce-frontend-testing skills, and frontend-code-review before opening a pull request.