A Claude Code skill that loads your org's brand and engineering conventions before Claude builds an LWC — so what comes out looks like your org and follows your standards, not generic SLDS. Fill in your palette and schema once; the conventions work for any org.
| Placeholder | What it is |
|---|---|
[ORG_NAME] | Your organisation name |
[NAMESPACE] | Your custom object/field prefix, or none |
[DEV_SANDBOX] / [FULL_SANDBOX] | Your sandbox CLI aliases |
[PREFIX] | Your LWC component naming prefix |
[API_VERSION] | Your org's metadata/LWC API version |
[BRAND_TOKENS] / [BRAND_FONT] | Your palette CSS variables and brand font |
| Schema Reference | Your object/field dictionary — replace the example format |
Save as brand-lwc.md, fill in the brand and schema sections, and invoke before any LWC build.
# Salesforce LWC Builder — Brand & Standards Skill
> Reusable template. Replace every [PLACEHOLDER] with your own org's details — the big ones are
> the Brand Tokens block and the Schema Reference. Everything else (sharing patterns, error handling,
> permission-set rule, test standards, four-state handling) is good practice for any org as-is.
You are building a Lightning Web Component for [ORG_NAME]. Apply everything below before writing a
single line of code.
## Org context — fill in once
- Namespace: [NAMESPACE] prefix on custom objects/fields, or none (e.g. acme__ or blank)
- Sandboxes: [DEV_SANDBOX] (dev) -> [FULL_SANDBOX] (full copy) -> Production via your release process
- CLI: Salesforce CLI (sf) authenticated to your sandboxes. Always deploy to [DEV_SANDBOX] first.
## Naming conventions — adjust to your team's
- LWC folder/component: [PREFIX] + camelCase (e.g. acctEventInvitations)
- Apex controller: PascalCase ([Feature]Controller)
- Apex test class: controller name + Test
- Permission set: descriptive + _LWC suffix ([Feature]_LWC)
- Metadata/LWC API version: [API_VERSION] (match your org's existing classes)
## Brand & visual standards — fill in your own
Always use your org's brand. Never ship default Salesforce blue / stock SLDS styling for component shells.
Replace this block with your real palette and font:
```css
:host {
--brand-primary: [#HEXCODE]; /* dominant brand colour */
--brand-primary-d: [#HEXCODE];
--brand-accent: [#HEXCODE]; /* use sparingly for highlights */
--text-dark: [#HEXCODE];
--text-mid: [#HEXCODE];
--border: [#HEXCODE];
--radius: 10px;
--shadow: 0 4px 16px rgba(0,0,0,0.12);
}
/* Font: '[BRAND_FONT]', 'Salesforce Sans', sans-serif
NB: a custom web font only loads in an LWC via a static resource — confirm yours is set up,
or fall back to a system stack. */
```
Component conventions that hold for any brand:
- Component shell: use a custom div wrapper, NOT <lightning-card>. Full visual control, clearly
separates your component from surrounding Salesforce chrome.
- Tables: custom HTML <table>, NOT <lightning-datatable>. You control rows, hover, borders, badges.
- Status badges: inline <span> pills. Keep one colour per status, consistent across components.
- Components should look modern — rounded corners, soft shadows, smooth hover. People compare
against SaaS UI, not classic Salesforce.
## Apex standards
### Sharing model
Choose deliberately and document why.
- Use `with sharing` by default — it respects record-level security.
- Use `without sharing` ONLY when a display component must show contextual data that the running
user's profile can't reach through sharing, AND the data is safe for anyone who can open the
record to see. Document the reason in a comment. Never reach for it just to make an error go away.
### Error handling
Wrap the method body in try/catch and throw AuraHandledException:
```apex
@AuraEnabled(cacheable=true)
public static List<MyRow> getData(Id recordId) {
try {
// query logic
return rows;
} catch (Exception e) {
throw new AuraHandledException('Error loading data: ' + e.getMessage());
}
}
```
### Inner classes
Return typed inner classes from @AuraEnabled methods — never raw SObject lists:
```apex
public class MyRow {
@AuraEnabled public String fieldOne;
@AuraEnabled public Date fieldTwo;
}
```
## Permission sets — mandatory for every LWC
Every LWC with an Apex controller needs a dedicated permission set granting class access — most
profiles don't grant it by default. Create [Feature]_LWC.permissionset-meta.xml granting the
controller's Apex class, and deploy it alongside the component. Assign it before testing as a
non-admin user.
## LWC patterns
### Wire adapters
- @wire(getRecord, { recordId: '$recordId', fields: FIELDS }) for record fields shown in the
component — auto-refreshes when the record is saved on the page.
- @wire(MyApexMethod, { param: '$recordId' }) for Apex data.
- Import displayed record fields into the LWC so it reacts to inline edits.
### State handling — handle all four, always
1. Loading (until the wire resolves)
2. Error (wire returns an error)
3. Data with results
4. Empty (wire returns an empty array)
Empty states should be compact and specific — plain wording about why nothing is shown.
## Schema reference — replace with your own
Document the objects this skill will touch so Claude stops guessing field names. Example format:
```
[OBJECT]__c
[Lookup_Field]__c -> [Parent Object]
[Date_Field]__c -> Date
[Status_Field]__c -> Picklist
```
Note any quirks: fields where the API name differs from the label, values stored as text to avoid
conversion, status-priority rules. A stale schema reference is worse than none.
## Test class standards
- Minimum coverage 75% for production; aim higher.
- Cover: happy path, alternative logic paths, boundary conditions, empty results return [] not null,
null/missing optional fields, data isolation, edge cases.
- Use System.runAs() with a standard-user profile to confirm no exceptions for non-admins.
- Use Assert.areEqual()/Assert.isNotNull(), not the deprecated System.assertEquals.
## Checklist before every deploy
- [ ] Sharing model chosen deliberately and documented
- [ ] Try/catch wrapping the method body
- [ ] Permission set created and included in the deploy
- [ ] Test class present, all passing, meaningful coverage
- [ ] All four states handled; empty state compact and specific
- [ ] Brand tokens used, not default SLDS blue
- [ ] No <lightning-card> or <lightning-datatable> — custom markup