
Sf Lwc
Ship Salesforce Lightning Web Components with correct LDS wire adapters, schema imports, and UI API patterns instead of guessing Apex-heavy data access.
Overview
sf-lwc is an agent skill for the Build phase that documents Salesforce Lightning Web Component patterns for LDS wire adapters and UI Record API usage.
Install
npx skills add https://github.com/clientell-ai/salesforce-skills --skill sf-lwcWhat is this skill?
- Lightning Data Service wire patterns with @salesforce/schema field imports
- getRecord, getFieldValue, getFieldDisplayValue, and optionalFields for FLS-safe reads
- getObjectInfo and uiObjectInfoApi metadata wiring examples
- Copy-paste JavaScript snippets aligned to Salesforce UI Record API conventions
Adoption & trust: 1 installs on skills.sh; 7 GitHub stars; 3/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
What problem does it solve?
You are building LWCs on Salesforce but keep mixing Apex calls, wrong field imports, or brittle wire configs that break under FLS and metadata changes.
Who is it for?
Indie consultants or solo ISVs shipping Experience Cloud or internal Salesforce apps who want agent-assisted LWC that stays on-platform.
Skip if: Teams not on Salesforce, pure Aura-only legacy stacks, or backend-only Apex integration work with no UI surface.
When should I use this skill?
When implementing or reviewing Salesforce LWCs that read records or object metadata via Lightning UI APIs.
What do I get? / Deliverables
Your agent emits LWC code that uses schema-backed wires, optionalFields where needed, and object metadata APIs consistent with Salesforce best practices.
- LWC JavaScript modules using LDS wires
- Record-detail and metadata-driven UI snippets
Recommended Skills
Journey fit
LWC is the primary UI layer for Salesforce products, so the canonical shelf is Build when you are implementing customer-facing org UI. The reference is entirely Lightning Web Component frontend patterns (wire, getRecord, object metadata), not backend Apex or DevOps.
How it compares
Use as a focused LWC snippet reference instead of generic React or Vue frontend skills that ignore Lightning UI APIs.
Common Questions / FAQ
Who is sf-lwc for?
Solo builders and small teams implementing Salesforce Lightning Web Components who want correct LDS and uiRecordApi patterns while pair-programming with an AI agent.
When should I use sf-lwc?
Use it in the Build phase while coding record pages, related-field displays, or metadata-driven forms; also when refactoring LWCs away from unnecessary Apex controllers.
Is sf-lwc safe to install?
Review the Security Audits panel on this Prism page and your org’s allowed package sources before trusting any third-party skill in a production Salesforce workspace.
SKILL.md
READMESKILL.md - Sf Lwc
# LWC Patterns Reference ## 1. Lightning Data Service (LDS) — Wire Adapters ### getRecord with Field Imports ```javascript import { LightningElement, wire, api } from 'lwc'; import { getRecord, getFieldValue, getFieldDisplayValue } from 'lightning/uiRecordApi'; import NAME_FIELD from '@salesforce/schema/Account.Name'; import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry'; import OWNER_NAME_FIELD from '@salesforce/schema/Account.Owner.Name'; const FIELDS = [NAME_FIELD, INDUSTRY_FIELD, OWNER_NAME_FIELD]; export default class AccountDetail extends LightningElement { @api recordId; @wire(getRecord, { recordId: '$recordId', fields: FIELDS }) account; get name() { return getFieldValue(this.account.data, NAME_FIELD); } get industry() { return getFieldDisplayValue(this.account.data, INDUSTRY_FIELD); } get ownerName() { return getFieldValue(this.account.data, OWNER_NAME_FIELD); } get error() { return this.account.error; } } ``` **Using optionalFields** (no error if field is inaccessible): ```javascript @wire(getRecord, { recordId: '$recordId', fields: [NAME_FIELD], optionalFields: [OWNER_NAME_FIELD] }) account; ``` ### getObjectInfo for Object Metadata ```javascript import { LightningElement, wire } from 'lwc'; import { getObjectInfo } from 'lightning/uiObjectInfoApi'; import ACCOUNT_OBJECT from '@salesforce/schema/Account'; export default class ObjectMetadata extends LightningElement { @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT }) objectInfo; get defaultRecordTypeId() { if (this.objectInfo.data) { return this.objectInfo.data.defaultRecordTypeId; } return null; } get fieldMap() { if (this.objectInfo.data) { return this.objectInfo.data.fields; } return {}; } } ``` ### getPicklistValues and getPicklistValuesByRecordType ```javascript import { LightningElement, wire, api } from 'lwc'; import { getObjectInfo } from 'lightning/uiObjectInfoApi'; import { getPicklistValues, getPicklistValuesByRecordType } from 'lightning/uiObjectInfoApi'; import ACCOUNT_OBJECT from '@salesforce/schema/Account'; import INDUSTRY_FIELD from '@salesforce/schema/Account.Industry'; export default class PicklistExample extends LightningElement { @api recordId; @wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT }) objectInfo; // Single field picklist values @wire(getPicklistValues, { recordTypeId: '$objectInfo.data.defaultRecordTypeId', fieldApiName: INDUSTRY_FIELD }) industryOptions; // All picklist values for a record type @wire(getPicklistValuesByRecordType, { objectApiName: ACCOUNT_OBJECT, recordTypeId: '$objectInfo.data.defaultRecordTypeId' }) allPicklistValues; get industryPicklistValues() { if (this.industryOptions.data) { return this.industryOptions.data.values.map(item => ({ label: item.label, value: item.value })); } return []; } } ``` ### refreshApex() Cache Invalidation ```javascript import { LightningElement, wire, api } from 'lwc'; import { refreshApex } from '@salesforce/apex'; import getContacts from '@salesforce/apex/ContactController.getContacts'; export default class ContactList extends LightningElement { @api recordId; // Store the full wire result for refreshApex wiredContactsResult; @wire(getContacts, { accountId: '$recordId' }) wiredContacts(result) { this.wiredContactsResult = result; // cache the provisioned value const { data, error } = result; if (data) { this.contacts = data; this.error = undefined; } else if (error) { this.error = error; this.contacts = []; } } async handleRefresh() { await refreshApex(this.wiredContactsRes