Apply the organisation's own Salesforce conventions — the naming rules and mandated patterns this org enforces on top of generic platform practice — across custom objects, fields, validation rules, page layouts, Lightning pages, Flows, custom labels, Apex classes, triggers and tests, and Visualforce.
When agents use itUse this whenever the user creates or names any Salesforce metadata: a custom object or field, a junction object, a record type, a validation rule, a page or compact layout, a Lightning page, a Flow, a custom label, an Apex class, trigger, handler or test class, or a Visualforce page; writes a trigger that must sit on `TriggerTemplateV2`; needs a record type Id through `Utils.getRecordTypeId`; stores callout credentials in `Credential__c`; wires a bypass through `Ignore_Validation_Rules__c`; suffixes a class `Ctrl`, `Controller` or `Rest`; or simply asks "what should I call this". Also apply it when porting older metadata that predates these rules.
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 salesforce-org-conventions -a github-copilot
# or with the org installer (adds .github/skills/salesforce-org-conventions):
npx -y github:AGCO-Global/org-skills add skill salesforce-org-conventions
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.
Installs the salesforce-standards-skills plugin, which bundles all Salesforce / Standards skills and keeps them updated.
/plugin marketplace add AGCO-Global/org-skills
/plugin install salesforce-standards-skills@org-skills
# or just this skill, in this repository:
npx skills add AGCO-Global/org-skills --skill salesforce-org-conventions -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 salesforce-org-conventions -a codex
Installs into Cursor's skills folder.
npx skills add AGCO-Global/org-skills --skill salesforce-org-conventions -a cursor
Installs into Gemini CLI's skills folder.
npx skills add AGCO-Global/org-skills --skill salesforce-org-conventions -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.
Try it — example prompts
Prompts this skill is tested against, and what a good answer includes.
Write the trigger for our new Problem__c object.
trigger ProblemTrigger on Problem__c with all 7 events declared (before/after insert, update, delete, plus after undelete)one line in the trigger body delegating through TriggerTemplateV2a separate ProblemTriggerHandler classbypass wired per handler class in the trigger
I need a checkbox on Account for whether the customer is active, and a field for the date they signed up.
checkbox labelled Active, API name Active__c — not Is_Active__cdate field label and API name both ending in Date, e.g. Signed_Up_Date__cAPI names generated from the label rather than hand-written camel caseFLS granted to System Administrator, System Specialist, System Specialist Lite and System Integrationa Description filled in on each field
Create a junction object linking Problems and Parts. Problem controls sharing.
object named Problem_Part__c with the primary parent Problem listed firstsingular object nameno underscores in the object labeltwo master-detail relationships, Problem firstat least one record type on the object
How do I get the Digital Support record type Id for Case in this class?
Utils.getRecordTypeId('Case:Digital_Support')stored in a static final variableconstant named in ALL_CAPS_SNAKE_CASE
Name this flow — it runs on Problem before upsert for the Asset MQ Standard record type.
Problem Asset_MQ Standard_Before_Upsertorder is Object, Record Type Label, Context, Eventa feature toggle so the flow can be switched off, as validation rules have
Where should the API key for our new ERP callout live?
a Named Credential where the callout can use oneotherwise Credential__cencrypted field and field-level security restricted to the integration userrecords kept out of change sets and packages
Skill contents
Salesforce Org Conventions
Targets: this organisation's Salesforce standards · Verified: 2026-09 against the team standards document
These are house rules, not platform rules. Where they differ from generic Salesforce advice they win, because reviewers enforce them and the existing codebase already follows them. Two habits carry most of the value: let the platform generate API names from well-chosen labels, and put every piece of logic behind the framework and helpers the org already owns rather than a new one. British English spelling throughout, in labels and API names alike.
1. Decide first
Question
Default
Change when
Trigger framework?
TriggerTemplateV2, one trigger per object, all 7 events declared
Never for new work — an object already on another framework is migrated, not forked
Where does a record type Id come from?
Utils.getRecordTypeId('Case:Digital_Support') held in a static final
Never a hard-coded Id and never an inline describe call
Where do callout credentials live?
Credential__c or a Named Credential
Named Credential whenever the callout can use one — see §3 for the Credential__c conditions
Do I need a new field?
No — use a standard field, then an existing custom field
Only when neither carries the meaning; then prefer a picklist over free text
API name?
Whatever the platform generates from the label
Never hand-written camel case; only the x prefix rule in §4 overrides this
Sharing declaration?
with sharing
without sharing with a comment saying why. Every class states one explicitly
Async work?
The org's Async class, so context is handled for you
Direct System.enqueueJob only where Async genuinely cannot express the job
Can this automation be switched off?
Yes — validation rules and flows honour User.Ignore_Validation_Rules__c; each trigger handler has its own bypass
Never ship automation with no way to disable it
2. Apex files, classes and members
Names. Classes start uppercase and UseCamelCase; variables and methods start lowercase and use camelCase; static final constants are ALL_CAPS_SNAKE_CASE. No non-ASCII characters in identifiers. Limit acronyms and abbreviations — a name should describe its purpose and still be readable and memorable.
Suffixes carry meaning. Visualforce and LWC controllers end in Ctrl or Controller (DemandPlan → DemandPlanCtrl). Classes exposing REST endpoints end in Rest. Test classes are the class under test plus Test (AccountTrigger → AccountTriggerTest).
Every file opens with the change log — date, name or initials, description of the change, and the user story or bug number. Template in references/apex-file-conventions.md.
DML goes through Database methods, so partial success is a decision rather than an accident; inspect the results you get back.
No SOQL or DML inside a loop, no hard-coded Ids, and no future or other async call from inside a loop.
3. Triggers and credentials
One trigger per object, named {ObjectName}Trigger, holding no logic — it hands off to {ObjectName}TriggerHandler through TriggerTemplateV2.
Declare all 7 events — before insert, before update, before delete, after insert, after update, after delete, after undelete — even where a handler ignores some. Trigger Hook relies on the full set being present.
Bypass logic lives in the trigger, per handler class, so one handler can be switched off without disabling the object.
Never pass Trigger.new wholesale into a handler method. Filter to the records actually in scope for that piece of logic and pass those. It keeps the handler honest about what it operates on and keeps bulk behaviour predictable.
Callout credentials belong in Credential__c or a Named Credential, never in code, a static resource or a hard-coded string. A Credential__c record is ordinary data: store the secret in an encrypted field, restrict field-level security to the integration user, and keep the records out of change sets and packages.
Skeleton, bypass wiring and the Utils / Async call patterns: references/apex-file-conventions.md.
4. Objects and fields
Objects are singular, unique, start with an uppercase letter, and carry no underscores in the label. Junction objects are named for the two objects they join with the primary parent first — the one that drives sharing — as in Problem_Part__c.
Every object has at least one record type, and security comes from permission sets and profiles.
Field labels are short; detail belongs in help text and the description. Date fields end in Date; Date/Time labels end in Date/Time with the API name ending Date_Time; checkboxes are not prefixed Is; lookups name their target object; a label starting with a number gets an API name starting with x.
Add FLS to the four admin profiles — System Administrator, System Specialist, System Specialist Lite, System Integration — whenever a field is created. A field nobody in admin can see is a support ticket waiting to happen.
Turn on History Tracking only for fields that genuinely matter, and never paste picklist values from Word or Excel: they carry invisible characters that break comparisons later.
Full tables, including the spelling and acronym rules: references/object-and-field-naming.md.
5. Automation, layouts and Visualforce
Validation rules reference User.Ignore_Validation_Rules__c, hard-code no Ids, and place the error at the field rather than the top of the page.
Flows are named Object · Record Type Label (if any) · Context · Event, as in Problem Asset_MQ Standard_Before_Upsert, and carry a feature toggle the way validation rules do.
Approval processes hard-code no Ids, and field updates never use Re-evaluate Workflow Rules after Field Change.
Custom labels are not prefixed for common terms such as Save, and no two labels share a value.
Layouts never contain the word "Layout" in the name. Lightning pages are named {sobject API Name} Org Default, with the Details tab first, Related last, and anything object- or process-specific in between.
Visualforce links pages with {!$Page.PageName} rather than /apex/PageName, surfaces errors through <apex:pageMessages />, marks non-persisted data transient to shrink view state, and wraps dynamic SOQL input in String.escapeSingleQuotes().
Layout, list view, compact layout, lookup filter and Visualforce detail: references/layouts-and-ui.md.
6. Tests
Test classes are named after the class they cover and end in Test. Target 90 % or better coverage — the platform's 75 % is a deployment floor, not the bar here. Never SeeAllData=true. Split behaviour across multiple test methods, build shared data in @TestSetup, reset limits with Test.startTest() / Test.stopTest(), and cover the negative cases as well as the happy path. Test idioms and mocking belong to apex-testing.
7. Deliverable format
## What I created
<metadata type and API name, with the label it was generated from>
## Conventions applied
<the specific rules that shaped each name, so a reviewer can check them>
## Follow-ups
<FLS on the four admin profiles, record type, help text, bypass wiring — whatever is still outstanding>
Checklist
Every API name was generated from its label; none hand-written in camel case
Object names singular; junction objects named primary parent first
Date, Date/Time, checkbox, lookup and numeric-leading field rules applied
FLS granted to the four admin profiles; description and help text filled in
Trigger is one line on TriggerTemplateV2, declares all 7 events, bypasses per handler
No Trigger.new passed into a handler unfiltered
Record type Ids come from Utils.getRecordTypeId into a static final
Every class declares with sharing or without sharing, and opens with the change log
Validation rules and flows honour User.Ignore_Validation_Rules__c
Credentials in Credential__c (encrypted, FLS-restricted) or a Named Credential
Tests named {ClassUnderTest}Test, at 90 %+, with negative cases
Anti-patterns
Hand-written camel case API name (MyNewField__c from "My New Field") → let the platform generate it from the label
Plural object name, or underscores in the label → singular, spaces in the label
Checkbox called Is_Active__c → Active__c; the type already says it is a boolean
Acronyms in a label or API name → spell it out; the abbreviation is obvious only to whoever coined it
Inline getRecordTypeInfosByDeveloperName() describe call → Utils.getRecordTypeId(...) in a static final
Logic in the trigger body, or a second trigger on the object → one trigger, TriggerTemplateV2, handler holds the logic
Trigger.new handed straight to a handler method → filter to the records in scope and pass those
Picklist values pasted from Word or Excel → retype them; pasted values carry invisible characters
"Layout" in a layout name, or a Lightning page named ad hoc → drop the word; {sobject API Name} Org Default
Go deeper
references/object-and-field-naming.md — the complete object, field, picklist and FLS tables; open it when creating or renaming metadata
references/apex-file-conventions.md — change-log template, the TriggerTemplateV2 skeleton with all 7 events and bypass wiring, and the Utils, Async and Credential__c call patterns
references/layouts-and-ui.md — page, search, compact and list layouts, lookup filters, Lightning page structure, custom labels and the Visualforce rules
Sibling skills: apex-development for Apex idioms, apex-testing for tests, salesforce-data-model for modelling decisions, salesforce-automation for Flow design, salesforce-code-review for reviews
---
name: salesforce-org-conventions
description: >
Apply the organisation's own Salesforce conventions — the naming rules and mandated patterns this org enforces on top of generic platform practice — across custom objects, fields, validation rules, page layouts, Lightning pages, Flows, custom labels, Apex classes, triggers and tests, and Visualforce. Use this whenever the user creates or names any Salesforce metadata: a custom object or field, a junction object, a record type, a validation rule, a page or compact layout, a Lightning page, a Flow, a custom label, an Apex class, trigger, handler or test class, or a Visualforce page; writes a trigger that must sit on `TriggerTemplateV2`; needs a record type Id through `Utils.getRecordTypeId`; stores callout credentials in `Credential__c`; wires a bypass through `Ignore_Validation_Rules__c`; suffixes a class `Ctrl`, `Controller` or `Rest`; or simply asks "what should I call this". Also apply it when porting older metadata that predates these rules.
metadata:
technology: Salesforce
type: development
---
# Salesforce Org Conventions
> **Targets:** this organisation's Salesforce standards · **Verified:** 2026-09 against the team standards document
These are house rules, not platform rules. Where they differ from generic Salesforce advice they win, because reviewers enforce them and the existing codebase already follows them. Two habits carry most of the value: let the platform generate API names from well-chosen labels, and put every piece of logic behind the framework and helpers the org already owns rather than a new one. British English spelling throughout, in labels and API names alike.
## 1. Decide first
| Question | Default | Change when |
|---|---|---|
| Trigger framework? | **`TriggerTemplateV2`**, one trigger per object, all 7 events declared | Never for new work — an object already on another framework is migrated, not forked |
| Where does a record type Id come from? | `Utils.getRecordTypeId('Case:Digital_Support')` held in a `static final` | Never a hard-coded Id and never an inline describe call |
| Where do callout credentials live? | `Credential__c` or a Named Credential | Named Credential whenever the callout can use one — see §3 for the `Credential__c` conditions |
| Do I need a new field? | No — use a standard field, then an existing custom field | Only when neither carries the meaning; then prefer a picklist over free text |
| API name? | Whatever the platform generates from the label | Never hand-written camel case; only the `x` prefix rule in §4 overrides this |
| Sharing declaration? | `with sharing` | `without sharing` with a comment saying why. Every class states one explicitly |
| Async work? | The org's `Async` class, so context is handled for you | Direct `System.enqueueJob` only where `Async` genuinely cannot express the job |
| Can this automation be switched off? | Yes — validation rules and flows honour `User.Ignore_Validation_Rules__c`; each trigger handler has its own bypass | Never ship automation with no way to disable it |
## 2. Apex files, classes and members
- **Names.** Classes start uppercase and `UseCamelCase`; variables and methods start lowercase and use `camelCase`; `static final` constants are `ALL_CAPS_SNAKE_CASE`. No non-ASCII characters in identifiers. Limit acronyms and abbreviations — a name should describe its purpose and still be readable and memorable.
- **Suffixes carry meaning.** Visualforce and LWC controllers end in `Ctrl` or `Controller` (`DemandPlan` → `DemandPlanCtrl`). Classes exposing REST endpoints end in `Rest`. Test classes are the class under test plus `Test` (`AccountTrigger` → `AccountTriggerTest`).
- **Every file opens with the change log** — date, name or initials, description of the change, and the user story or bug number. Template in `references/apex-file-conventions.md`.
- **DML goes through `Database` methods**, so partial success is a decision rather than an accident; inspect the results you get back.
- No SOQL or DML inside a loop, no hard-coded Ids, and no `future` or other async call from inside a loop.
## 3. Triggers and credentials
- One trigger per object, named `{ObjectName}Trigger`, holding no logic — it hands off to `{ObjectName}TriggerHandler` through `TriggerTemplateV2`.
- **Declare all 7 events** — `before insert, before update, before delete, after insert, after update, after delete, after undelete` — even where a handler ignores some. Trigger Hook relies on the full set being present.
- **Bypass logic lives in the trigger, per handler class**, so one handler can be switched off without disabling the object.
- **Never pass `Trigger.new` wholesale into a handler method.** Filter to the records actually in scope for that piece of logic and pass those. It keeps the handler honest about what it operates on and keeps bulk behaviour predictable.
- Callout credentials belong in `Credential__c` or a Named Credential, never in code, a static resource or a hard-coded string. A `Credential__c` record is ordinary data: store the secret in an encrypted field, restrict field-level security to the integration user, and keep the records out of change sets and packages.
Skeleton, bypass wiring and the `Utils` / `Async` call patterns: `references/apex-file-conventions.md`.
## 4. Objects and fields
- Objects are **singular**, unique, start with an uppercase letter, and carry no underscores in the label. Junction objects are named for the two objects they join with the **primary parent first** — the one that drives sharing — as in `Problem_Part__c`.
- Every object has **at least one record type**, and security comes from permission sets and profiles.
- Field labels are short; detail belongs in help text and the description. Date fields end in `Date`; Date/Time labels end in `Date/Time` with the API name ending `Date_Time`; checkboxes are **not** prefixed `Is`; lookups name their target object; a label starting with a number gets an API name starting with `x`.
- **Add FLS to the four admin profiles** — System Administrator, System Specialist, System Specialist Lite, System Integration — whenever a field is created. A field nobody in admin can see is a support ticket waiting to happen.
- Turn on History Tracking only for fields that genuinely matter, and never paste picklist values from Word or Excel: they carry invisible characters that break comparisons later.
Full tables, including the spelling and acronym rules: `references/object-and-field-naming.md`.
## 5. Automation, layouts and Visualforce
- **Validation rules** reference `User.Ignore_Validation_Rules__c`, hard-code no Ids, and place the error at the field rather than the top of the page.
- **Flows** are named *Object · Record Type Label (if any) · Context · Event*, as in `Problem Asset_MQ Standard_Before_Upsert`, and carry a feature toggle the way validation rules do.
- **Approval processes** hard-code no Ids, and field updates never use *Re-evaluate Workflow Rules after Field Change*.
- **Custom labels** are not prefixed for common terms such as `Save`, and no two labels share a value.
- **Layouts** never contain the word "Layout" in the name. Lightning pages are named `{sobject API Name} Org Default`, with the Details tab first, Related last, and anything object- or process-specific in between.
- **Visualforce** links pages with `{!$Page.PageName}` rather than `/apex/PageName`, surfaces errors through `<apex:pageMessages />`, marks non-persisted data `transient` to shrink view state, and wraps dynamic SOQL input in `String.escapeSingleQuotes()`.
Layout, list view, compact layout, lookup filter and Visualforce detail: `references/layouts-and-ui.md`.
## 6. Tests
Test classes are named after the class they cover and end in `Test`. Target **90 % or better** coverage — the platform's 75 % is a deployment floor, not the bar here. Never `SeeAllData=true`. Split behaviour across multiple test methods, build shared data in `@TestSetup`, reset limits with `Test.startTest()` / `Test.stopTest()`, and cover the negative cases as well as the happy path. Test idioms and mocking belong to `apex-testing`.
## 7. Deliverable format
```
## What I created
<metadata type and API name, with the label it was generated from>
## Conventions applied
<the specific rules that shaped each name, so a reviewer can check them>
## Follow-ups
<FLS on the four admin profiles, record type, help text, bypass wiring — whatever is still outstanding>
```
## Checklist
- [ ] Every API name was generated from its label; none hand-written in camel case
- [ ] Object names singular; junction objects named primary parent first
- [ ] Date, Date/Time, checkbox, lookup and numeric-leading field rules applied
- [ ] FLS granted to the four admin profiles; description and help text filled in
- [ ] Trigger is one line on `TriggerTemplateV2`, declares all 7 events, bypasses per handler
- [ ] No `Trigger.new` passed into a handler unfiltered
- [ ] Record type Ids come from `Utils.getRecordTypeId` into a `static final`
- [ ] Every class declares `with sharing` or `without sharing`, and opens with the change log
- [ ] Validation rules and flows honour `User.Ignore_Validation_Rules__c`
- [ ] Credentials in `Credential__c` (encrypted, FLS-restricted) or a Named Credential
- [ ] Tests named `{ClassUnderTest}Test`, at 90 %+, with negative cases
## Anti-patterns
- **Hand-written camel case API name** (`MyNewField__c` from "My New Field") → let the platform generate it from the label
- **Plural object name, or underscores in the label** → singular, spaces in the label
- **Checkbox called `Is_Active__c`** → `Active__c`; the type already says it is a boolean
- **Acronyms in a label or API name** → spell it out; the abbreviation is obvious only to whoever coined it
- **Inline `getRecordTypeInfosByDeveloperName()` describe call** → `Utils.getRecordTypeId(...)` in a `static final`
- **Logic in the trigger body, or a second trigger on the object** → one trigger, `TriggerTemplateV2`, handler holds the logic
- **`Trigger.new` handed straight to a handler method** → filter to the records in scope and pass those
- **Picklist values pasted from Word or Excel** → retype them; pasted values carry invisible characters
- **"Layout" in a layout name, or a Lightning page named ad hoc** → drop the word; `{sobject API Name} Org Default`
## Go deeper
- `references/object-and-field-naming.md` — the complete object, field, picklist and FLS tables; open it when creating or renaming metadata
- `references/apex-file-conventions.md` — change-log template, the `TriggerTemplateV2` skeleton with all 7 events and bypass wiring, and the `Utils`, `Async` and `Credential__c` call patterns
- `references/layouts-and-ui.md` — page, search, compact and list layouts, lookup filters, Lightning page structure, custom labels and the Visualforce rules
- Sibling skills: `apex-development` for Apex idioms, `apex-testing` for tests, `salesforce-data-model` for modelling decisions, `salesforce-automation` for Flow design, `salesforce-code-review` for reviews