Salesforce component standards
Review or build Salesforce UI components with platform-specific rules for data access, security, SLDS 2 styling, accessibility, component communication, performance, and tests.
When to invoke
- "Review this Lightning Web Component for Salesforce standards."
- "Build an LWC that follows SLDS 2 and accessibility rules."
- "Check this Aura component and Apex controller for FLS/CRUD."
- "Audit this Visualforce page for XSS and CSRF issues."
- "Add Jest tests for this Salesforce component."
LWC data access
| Use case |
Pattern |
Why |
| Read one record reactively |
@wire(getRecord, { recordId, fields }) |
Lightning Data Service is cached and reactive. |
| Standard CRUD form |
<lightning-record-form> or <lightning-record-edit-form> |
Built-in FLS, CRUD, and accessibility. |
| Complex server query or filtered list |
@wire(apexMethodName, { param }) on cacheable=true Apex |
Cacheable wire re-runs when params change. |
| User-triggered DML or non-cacheable call |
Imperative apexMethodName(params).then(...).catch(...) |
DML cannot be wired unless @AuraEnabled(cacheable=true) and read-only. |
| Cross-component communication without shared parent |
Lightning Message Service (LMS) |
Decoupled across DOM boundaries. |
| Multi-object graph relationships |
GraphQL @wire(gql, { query, variables }) |
Fetch related data in one round trip. |
LWC security, styling, and communication
| Area |
Rule |
| XSS |
Never assign raw user data to innerHTML; use template {expression} binding. |
| Apex permissions |
@AuraEnabled methods enforce CRUD/FLS using WITH USER_MODE in SOQL or explicit Schema.sObjectType checks. |
| Org IDs |
Do not hardcode org-specific IDs in component JavaScript; query them or pass as props. |
@api input |
Validate type and range before using parent-supplied values in SOQL or Apex parameters. |
| SLDS 2 |
Use <lightning-*> base components such as lightning-button, lightning-input, lightning-datatable, and lightning-card. |
| Colors |
Do not hardcode color: #FF3366; use semantic SLDS tokens such as var(--slds-c-button-brand-color-background). |
| CSS overrides |
Do not override SLDS classes with !important; compose with custom CSS properties. |
| Modes |
Test custom CSS in light mode and dark mode. |
| Parent to child |
Use an @api property or an @api method. |
| Child to parent |
Use CustomEvent and this.dispatchEvent(new CustomEvent('eventname', { detail: data })). |
| Siblings/unrelated |
Use Lightning Message Service. |
| Never use |
document.querySelector, window.*, or Pub/Sub libraries for component communication. |
| Flow screen components |
Events reaching Flow need bubbles: true and composed: true; expose @api value for two-way binding. |
Accessibility and performance
Every LWC must satisfy WCAG 2.1 AA checks:
Performance rules:
- Avoid DML, heavy computation, or rendering state mutation in
connectedCallback because it runs on every DOM attach.
- Guard
renderedCallback with a boolean to prevent infinite render loops.
- Do not set reactive properties in
renderedCallback unless necessary and guarded.
- Paginate or stream large datasets instead of storing them all in component state.
Aura and Visualforce
| Technology |
Rule |
| Aura vs LWC |
New components should be LWC unless the target is Aura-only, such as extending force:appPage or using legacy Aura-specific events. |
| Aura controllers |
@AuraEnabled methods must use with sharing and enforce CRUD/FLS; Aura does not enforce them automatically. |
| Aura output |
Avoid unescaped {!v.something} in raw helpers; use <ui:outputText value="{!v.text}" /> or escaping components. |
| Aura events |
Prefer component events for parent-child; application events broadcast to the whole app and should be rare. |
| Hybrid stacks |
Use Lightning Message Service between LWC and Aura. |
| Visualforce XSS |
Never use <apex:outputText value="{!userInput}" escape="false" /> for user-controlled data. |
| Visualforce CSRF |
Use <apex:form> for postbacks; do not use raw <form method="POST">. |
| SOQL injection |
Bind URL parameters: WHERE Name = :nameParam; do not concatenate ApexPages.currentPage().getParameters().get('name'). |
| View state |
Keep view state under 135 KB, use transient, avoid persisting large collections, and set readonly="true" on read-only pages. |
| Custom controllers |
Standard controllers enforce FLS for bound fields; custom controllers must check Schema.sObjectType.Account.fields.Revenue__c.isAccessible() and DML permissions such as Schema.sObjectType.Account.isDeletable(). |
Jest requirements
Every component with user interaction or Apex data retrieval needs Jest tests covering render, data, event, and error behavior.
it('renders the component with correct title', async () => { /* ... */ });
it('calls apex method and displays results', async () => { /* wire mock */ });
it('dispatches event when button is clicked', async () => { /* ... */ });
it('shows error state when apex call fails', async () => { /* error path */ });
Use @salesforce/sfdx-lwc-jest utilities: setImmediate plus emit({ data, error }) for wire adapter mocking, and jest.mock('@salesforce/apex/MyClass.myMethod', ...) for Apex method mocking.
Anti-patterns
| Anti-pattern |
Technology |
Risk |
Fix |
innerHTML with user data |
LWC |
XSS |
Use template bindings {expression}. |
| Hardcoded hex colors |
LWC/Aura |
Dark-mode and SLDS 2 breakage |
Use SLDS CSS custom properties. |
Missing aria-label on icon buttons |
LWC/Aura/VF |
Accessibility failure |
Add alternative-text or aria-label. |
No guard in renderedCallback |
LWC |
Infinite rerender loop |
Add a hasRendered boolean guard. |
| Application event for parent-child |
Aura |
Unnecessary broadcast |
Use component event. |
escape="false" on user data |
Visualforce |
XSS |
Remove it or sanitize rich text with a whitelist. |
Raw <form> postback |
Visualforce |
CSRF vulnerability |
Use <apex:form>. |
No with sharing |
VF / Apex |
Data exposure |
Add with sharing. |
| FLS not checked |
VF / Apex |
Privilege escalation |
Add Schema.sObjectType checks. |
| SOQL concatenated with URL param |
VF / Apex |
SOQL injection |
Use bind variables. |
Compatibility vocabulary
Preserve these legacy terms, API names, command placeholders, and literal phrases when applying or migrating this skill:
<apex:page>
<c:something>
<div>
ALWAYS
ERROR
FROM
HTML
NEVER
SELECT
auto-escapes
auto-escaping
built-in
color: var(--slds-c-button-brand-color-background)
component-by-component
icon-only
re-fires
re-render
round-trip
server-side
this.template.querySelector('.el').innerHTML = userValue
view-state
wire
ApexPages.Message
ApexPages.Severity.ERROR
NoAccessException
System.NoAccessException
Output template
## Salesforce component standards result
**Status:** pass | fixes required | blocked
**Scope:** <LWC/Aura/Visualforce/Apex files>
| Area | Finding | Severity | Evidence | Required fix |
| --- | --- | --- | --- | --- |
| Security | <finding> | <High/Medium/Low> | <file/line or snippet> | <fix> |
| Accessibility | <finding> | <High/Medium/Low> | <file/line or snippet> | <fix> |
| Tests | <finding> | <High/Medium/Low> | <file/line or snippet> | <fix> |
### Validation
- <Jest, Apex test, manual accessibility, or code review check>
Quality gate
1---2name: salesforce-component-standards-23description: Apply Salesforce UI component standards for Lightning Web Components, Aura, Visualforce, SLDS 2, WCAG 2.1 AA, secure Apex access, component communication, XSS, CSRF, FLS/CRUD, view state, and Jest tests. Use when building or reviewing Salesforce LWC, Aura components, Visualforce pages, or Apex controllers used by UI components.4---56# Salesforce component standards78Review or build Salesforce UI components with platform-specific rules for data access, security, SLDS 2 styling, accessibility, component communication, performance, and tests.910## When to invoke1112- "Review this Lightning Web Component for Salesforce standards."13- "Build an LWC that follows SLDS 2 and accessibility rules."14- "Check this Aura component and Apex controller for FLS/CRUD."15- "Audit this Visualforce page for XSS and CSRF issues."16- "Add Jest tests for this Salesforce component."1718## LWC data access1920| Use case | Pattern | Why |21| --- | --- | --- |22| Read one record reactively | `@wire(getRecord, { recordId, fields })` | Lightning Data Service is cached and reactive. |23| Standard CRUD form | `<lightning-record-form>` or `<lightning-record-edit-form>` | Built-in FLS, CRUD, and accessibility. |24| Complex server query or filtered list | `@wire(apexMethodName, { param })` on `cacheable=true` Apex | Cacheable wire re-runs when params change. |25| User-triggered DML or non-cacheable call | Imperative `apexMethodName(params).then(...).catch(...)` | DML cannot be wired unless `@AuraEnabled(cacheable=true)` and read-only. |26| Cross-component communication without shared parent | Lightning Message Service (LMS) | Decoupled across DOM boundaries. |27| Multi-object graph relationships | GraphQL `@wire(gql, { query, variables })` | Fetch related data in one round trip. |2829## LWC security, styling, and communication3031| Area | Rule |32| --- | --- |33| XSS | Never assign raw user data to `innerHTML`; use template `{expression}` binding. |34| Apex permissions | `@AuraEnabled` methods enforce CRUD/FLS using `WITH USER_MODE` in SOQL or explicit `Schema.sObjectType` checks. |35| Org IDs | Do not hardcode org-specific IDs in component JavaScript; query them or pass as props. |36| `@api` input | Validate type and range before using parent-supplied values in SOQL or Apex parameters. |37| SLDS 2 | Use `<lightning-*>` base components such as `lightning-button`, `lightning-input`, `lightning-datatable`, and `lightning-card`. |38| Colors | Do not hardcode `color: #FF3366`; use semantic SLDS tokens such as `var(--slds-c-button-brand-color-background)`. |39| CSS overrides | Do not override SLDS classes with `!important`; compose with custom CSS properties. |40| Modes | Test custom CSS in light mode and dark mode. |41| Parent to child | Use an `@api` property or an `@api` method. |42| Child to parent | Use `CustomEvent` and `this.dispatchEvent(new CustomEvent('eventname', { detail: data }))`. |43| Siblings/unrelated | Use Lightning Message Service. |44| Never use | `document.querySelector`, `window.*`, or Pub/Sub libraries for component communication. |45| Flow screen components | Events reaching Flow need `bubbles: true` and `composed: true`; expose `@api value` for two-way binding. |4647## Accessibility and performance4849Every LWC must satisfy WCAG 2.1 AA checks:5051- [ ] Inputs have `<label>` or `aria-label`; placeholder text is not the only label.52- [ ] Icon-only buttons have `alternative-text` or `aria-label`.53- [ ] Interactive elements work with Tab, Enter, Space, and Escape.54- [ ] Color is not the only status indicator; pair it with text, icon, or `aria-*` attributes.55- [ ] Error messages are connected to inputs with `aria-describedby`.56- [ ] Modal focus moves inside on open and returns on close.5758Performance rules:5960- Avoid DML, heavy computation, or rendering state mutation in `connectedCallback` because it runs on every DOM attach.61- Guard `renderedCallback` with a boolean to prevent infinite render loops.62- Do not set reactive properties in `renderedCallback` unless necessary and guarded.63- Paginate or stream large datasets instead of storing them all in component state.6465## Aura and Visualforce6667| Technology | Rule |68| --- | --- |69| Aura vs LWC | New components should be LWC unless the target is Aura-only, such as extending `force:appPage` or using legacy Aura-specific events. |70| Aura controllers | `@AuraEnabled` methods must use `with sharing` and enforce CRUD/FLS; Aura does not enforce them automatically. |71| Aura output | Avoid unescaped `{!v.something}` in raw helpers; use `<ui:outputText value="{!v.text}" />` or escaping components. |72| Aura events | Prefer component events for parent-child; application events broadcast to the whole app and should be rare. |73| Hybrid stacks | Use Lightning Message Service between LWC and Aura. |74| Visualforce XSS | Never use `<apex:outputText value="{!userInput}" escape="false" />` for user-controlled data. |75| Visualforce CSRF | Use `<apex:form>` for postbacks; do not use raw `<form method="POST">`. |76| SOQL injection | Bind URL parameters: `WHERE Name = :nameParam`; do not concatenate `ApexPages.currentPage().getParameters().get('name')`. |77| View state | Keep view state under `135 KB`, use `transient`, avoid persisting large collections, and set `readonly="true"` on read-only pages. |78| Custom controllers | Standard controllers enforce FLS for bound fields; custom controllers must check `Schema.sObjectType.Account.fields.Revenue__c.isAccessible()` and DML permissions such as `Schema.sObjectType.Account.isDeletable()`. |7980## Jest requirements8182Every component with user interaction or Apex data retrieval needs Jest tests covering render, data, event, and error behavior.8384```javascript85it('renders the component with correct title', async () => { /* ... */ });86it('calls apex method and displays results', async () => { /* wire mock */ });87it('dispatches event when button is clicked', async () => { /* ... */ });88it('shows error state when apex call fails', async () => { /* error path */ });89```9091Use `@salesforce/sfdx-lwc-jest` utilities: `setImmediate` plus `emit({ data, error })` for wire adapter mocking, and `jest.mock('@salesforce/apex/MyClass.myMethod', ...)` for Apex method mocking.9293## Anti-patterns9495| Anti-pattern | Technology | Risk | Fix |96| --- | --- | --- | --- |97| `innerHTML` with user data | LWC | XSS | Use template bindings `{expression}`. |98| Hardcoded hex colors | LWC/Aura | Dark-mode and SLDS 2 breakage | Use SLDS CSS custom properties. |99| Missing `aria-label` on icon buttons | LWC/Aura/VF | Accessibility failure | Add `alternative-text` or `aria-label`. |100| No guard in `renderedCallback` | LWC | Infinite rerender loop | Add a `hasRendered` boolean guard. |101| Application event for parent-child | Aura | Unnecessary broadcast | Use component event. |102| `escape="false"` on user data | Visualforce | XSS | Remove it or sanitize rich text with a whitelist. |103| Raw `<form>` postback | Visualforce | CSRF vulnerability | Use `<apex:form>`. |104| No `with sharing` | VF / Apex | Data exposure | Add `with sharing`. |105| FLS not checked | VF / Apex | Privilege escalation | Add `Schema.sObjectType` checks. |106| SOQL concatenated with URL param | VF / Apex | SOQL injection | Use bind variables. |107108## Compatibility vocabulary109110Preserve these legacy terms, API names, command placeholders, and literal phrases when applying or migrating this skill:111112- `<apex:page>`113- `<c:something>`114- `<div>`115- `ALWAYS`116- `ERROR`117- `FROM`118- `HTML`119- `NEVER`120- `SELECT`121- `auto-escapes`122- `auto-escaping`123- `built-in`124- `color: var(--slds-c-button-brand-color-background)`125- `component-by-component`126- `icon-only`127- `re-fires`128- `re-render`129- `round-trip`130- `server-side`131- `this.template.querySelector('.el').innerHTML = userValue`132- `view-state`133- `wire`134- `ApexPages.Message`135- `ApexPages.Severity.ERROR`136- `NoAccessException`137- `System.NoAccessException`138139## Output template140141```markdown142## Salesforce component standards result143144**Status:** pass | fixes required | blocked145**Scope:** <LWC/Aura/Visualforce/Apex files>146147| Area | Finding | Severity | Evidence | Required fix |148| --- | --- | --- | --- | --- |149| Security | <finding> | <High/Medium/Low> | <file/line or snippet> | <fix> |150| Accessibility | <finding> | <High/Medium/Low> | <file/line or snippet> | <fix> |151| Tests | <finding> | <High/Medium/Low> | <file/line or snippet> | <fix> |152153### Validation154- <Jest, Apex test, manual accessibility, or code review check>155```156157## Quality gate158159- [ ] LWC data access uses the narrowest safe pattern.160- [ ] User-controlled data is escaped and never assigned to `innerHTML` or `escape="false"`.161- [ ] Apex exposed to UI enforces sharing, CRUD, and FLS with `WITH USER_MODE` or `Schema.sObjectType` checks.162- [ ] SLDS 2 tokens and base components are used instead of hardcoded styles.163- [ ] WCAG 2.1 AA keyboard, label, focus, and color checks pass.164- [ ] Component communication avoids global DOM and Pub/Sub shortcuts.165- [ ] Visualforce postbacks use `<apex:form>` and view state stays under `135 KB`.166- [ ] Jest tests cover render, Apex success, event dispatch, and Apex failure paths where applicable.