Naming Conventions

Start with naming rules first (component identifiers, code symbols, and styling tokens), then move to folder/class organization.

Project code prefix

LWC bundle names use a leading camelCase segment for your project (for example acme in acmeDetail and acmeLookup). The JavaScript class is PascalCase with that segment as a word (AcmeDetail, AcmeLookup).

Why the prefix is lowercase in the bundle name (not PascalCase or ALL_CAPS): In the browser, custom components are referenced with a kebab-case tag built from the bundle name (for example acmeDetail<c-acme-detail>). If you use capitals in the wrong places in the folder / bundle name, the tag string splits awkwardly and is hard to read in markup and DevTools—for example:

  • AcmeComponentName → rendered and referenced like c-a-cme-component-name
  • ACMEComponentName → rendered and referenced like c-a-c-m-e-component-name

A lowercase leading segment plus camelCase (acmeDetail, acmeLookup) keeps the generated tag predictable and readable (<c-acme-detail>). Apex still uses an ALL_CAPS prefix with an underscore; only the LWC bundle's first segment stays lowercase for this HTML tagging behavior.

Composition examples in this document use exampleParent and exampleChild as bundle names so parent/child relationships are clear without implying a specific product prefix.

Components

  • Format: camelCase (typically acmeComponentName with your project segment)

  • Naming: Descriptive camelCase name that clearly indicates the component's purpose

  • Pattern: Component folder and files use the same camelCase name

  • Examples:

    // Parent/child composition (generic bundle names)
    // Component folder: exampleParent/
    // Files: exampleParent.js, exampleParent.html, exampleParent.css (compiled), exampleParent.js-meta.xml
    // Source: __styles__/exampleParent.scss (compiles to exampleParent.css)
    export default class ExampleParent extends LightningElement { }
    
    // Component folder: exampleChild/
    // Files: exampleChild.js, exampleChild.html, exampleChild.css (compiled), exampleChild.js-meta.xml
    // Source: __styles__/exampleChild.scss (compiles to exampleChild.css)
    export default class ExampleChild extends LightningElement { }

Properties

  • Format: camelCase

  • Naming: Descriptive names that indicate purpose

  • Public Properties: Use @api decorator

  • Private Properties: Prefix with underscore (_) for backing properties

  • Private Property Scope: Properties prefixed with _ should only be referenced within the same JavaScript file. They must not be referenced in:

    • Component HTML templates
    • Other JavaScript files
    • Parent or child components
  • Examples:

    // Public properties
    @api recordId;
    @api label = 'Click Me';
    @api disabled = false;
    
    // Private backing properties (for getters/setters)
    // These should ONLY be used within this JS file
    _customClass = 'default-class';
    _align = 'Left';
    
    // Private reactive properties (no underscore - used in templates)
    actionClass = '';
    isLoading = false;

Important: Underscore-prefixed properties (_propertyName) are implementation details and should never be accessed from templates or other files. Use getters/setters or public properties for template access.

Variables

  • Format: camelCase

  • Naming: Descriptive names that clearly indicate what the variable holds

  • Meaningful Names Required: Variable names must be meaningful and self-documenting

  • Single/Double Character Variables: Not allowed except for loop index variables (i, j, k, etc.)

  • Examples:

    // Good: Meaningful variable names
    const accountName = 'Test Account';
    const recordCount = 10;
    const isLoading = true;
    const buttonElement = this.template.querySelector('button');
    const accountData = await fetchAccountData();
    const errorMessage = error.body?.message || 'Unknown error';
    
    // Good: Loop index variables (exception to the rule)
    for (let i = 0; i < items.length; i++) {
        processItem(items[i]);
    }
    
    for (let j = 0; j < rows.length; j++) {
        for (let k = 0; k < columns.length; k++) {
            processCell(rows[j], columns[k]);
        }
    }
    
    // Bad: Single/double character variables (except loop indices)
    const a = 'Test Account'; // Bad - use accountName
    const x = 10; // Bad - use recordCount
    const el = this.template.querySelector('button'); // Bad - use buttonElement
    const d = await fetchAccountData(); // Bad - use accountData
    
    // Bad: Unclear abbreviations
    const accNm = 'Test Account'; // Bad - use accountName
    const btn = this.template.querySelector('button'); // Bad - use buttonElement
    const err = error.message; // Bad - use errorMessage
    
    // Good: Meaningful names even in short scopes
    const selectedItem = items[selectedIndex];
    const currentUser = getCurrentUser();
    const formData = new FormData();

Best Practices:

  • Use full words, not abbreviations (unless the abbreviation is widely understood)
  • Be specific about what the variable contains (e.g., accountName not name, buttonElement not element)
  • Use descriptive names even for temporary variables
  • Only use single-character variables (i, j, k) for loop indices

Methods

  • Format: camelCase

  • Naming: Verb-based names that describe the action performed

  • Event Handlers: Prefix with handle (e.g., handleClick, handleChange)

  • Private Methods: Do not use _ prefix. The absence of @api is the indicator that a method is private. Use descriptive verb-based names.

  • Examples:

    // Public methods
    @api focus() {
        this.template.querySelector('button').focus();
    }
    
    // Event handlers
    handleClick() {
        // Handle click
    }
    
    handleInputChange(event) {
        // Handle input change
    }
    
    // Private methods
    setColorClasses() {
        // Set color classes
    }
    
    validateInput(input) {
        // Validate input
    }

Constants

  • Format: UPPER_SNAKE_CASE

  • Naming: Descriptive names in all caps with underscores

  • Location: Define at the top of the file, outside the class

  • Examples:

    const DEFAULT_CLASS = 'example-component';
    const ICON_CLASS = 'slds-button__icon slds-current-color';
    const DEFAULT_COPY_TEXT = 'URL has been copied to your clipboard.';
    const MAX_RETRY_ATTEMPTS = 3;

Style Naming

Apply these naming rules to styles after core JavaScript naming conventions are established.

CSS Classes

  • Format: kebab-case or BEM methodology

  • Naming: Use SLDS classes when possible, custom classes should be descriptive

  • Examples:

    /* SLDS classes */
    .slds-button
    .slds-button_brand
    .slds-text-align_center
    
    /* Custom classes */
    .example-component
    .example-child-custom-color
    .example-parent-heading

CSS Custom Properties (Variables)

  • Format: kebab-case with component prefix

  • Naming: Use component prefix followed by descriptive name

  • Examples:

    :host {
        --example-child-color-background: #0070d2;
        --example-child-color-border: #0070d2;
        --example-parent-text-font-size: 1rem;
        --example-parent-text-font-weight: 700;
    }

Component Structure and Organization

Read this section from outside-in: repository/package layout, then component files, then class member order.

File Organization

Each component must consist of the following files in a single folder:

  • componentName.js - Component JavaScript class
  • componentName.html - Component template
  • componentName.css - Compiled CSS file (generated from SASS/SCSS)
  • componentName.js-meta.xml - Component metadata
  • __styles__/ - Folder containing SASS/SCSS source files

Style Files:

  • Use SASS/SCSS for component stylesheets (source files)
  • SASS/SCSS source files should be placed in a __styles__ folder within the component directory
  • The main SASS/SCSS file should be named componentName.scss or componentName.sass
  • Additional SASS files (mixins, variables, etc.) can be organized as partials within the __styles__ folder
  • SASS/SCSS files compile to CSS files that are stored in the main component directory (same level as .js, .html, .js-meta.xml)
  • The compiled CSS file (componentName.css) is what LWC uses at runtime

Example:

src/lwc/exampleParent/
├── exampleParent.js
├── exampleParent.html
├── exampleParent.css (compiled from __styles__/exampleParent.scss)
├── exampleParent.js-meta.xml
└── __styles__
    ├── exampleParent.scss (SASS source)
    ├── _variables.scss (SASS partial)
    └── _mixins.scss (SASS partial)

Alternative Simple Structure:

src/lwc/exampleParent/
├── exampleParent.js
├── exampleParent.html
├── exampleParent.css (compiled from __styles__/exampleParent.scss)
├── exampleParent.js-meta.xml
└── __styles__
    └── exampleParent.scss (SASS source)

Note: The componentName.css file is generated during the build/compilation process from the SASS/SCSS files in the __styles__ folder. Developers should edit the SASS/SCSS source files, not the compiled CSS files directly.

Package Organization

Organize LWC bundles in Salesforce DX paths so components are easy to locate and group by feature/domain:

force-app/
└── main/
    └── default/
        └── lwc/
            ├── account/
            ├── sharedButton/
            └── searchPanel/

Component Class Structure Order

Components should follow this order. Method visibility matches the Apex standard: @api (public) methods appear above any method that is not @api (private). Place @wire immediately after @api properties when adapters use reactive parameters such as $recordId. @api methods follow @wire, then lifecycle hooks. Event handlers and other helpers are private and come last.

  1. Imports - All import statements
  2. Constants - Constants defined outside the class
  3. Class Declaration - Class definition extending LightningElement
  4. Private Properties - Private backing properties (prefixed with _) - ONLY used within this JS file, never in templates
  5. Private Reactive Properties - Private reactive properties (can be used in templates)
  6. Computed Properties (Getters) - Getter methods
  7. Public Properties - @api properties
  8. Wire Methods - @wire properties (typically after @api fields the wire uses)
  9. Public Methods - @api methods (must appear before non-@api methods below)
  10. Lifecycle Hooks - connectedCallback, renderedCallback, disconnectedCallback, errorCallback
  11. Private Methods - All non-@api methods: event handlers (handle*) first, then other private helpers (no _ prefix on methods; absence of @api indicates privacy)

Example:

// 1. Imports
import { LightningElement, api } from 'lwc';
import { isEmpty } from 'c/exampleUtils';

// 2. Constants
const DEFAULT_CLASS = 'example-component';

// 3. Class Declarations
export default class ExampleParent extends LightningElement {
    // 4. Private Properties
    // Note: These underscore-prefixed properties should ONLY be used within this JS file
    // They must NOT be referenced in templates or other files
    _customClass = DEFAULT_CLASS;
    _align = 'Left';

    // 5. Private Reactive Properties
    // Note: These properties (no underscore) can be used in templates
    contentClass = '';
    textClass = 'example-component';
    isLoading = false;

    // 6. Computed Properties (Getters)
    get isHeading() {
        return !this.type.includes('p');
    }

    // Good: Private property accessed within same file (via getter)
    get align() {
        return this._align?.toLowerCase() || 'left';
    }

    // 7. Public Properties
    @api recordId;
    @api label = 'Default Label';

    @api get customClass() {
        return this._customClass;
    }

    set customClass(value) {
        this._customClass = value || DEFAULT_CLASS;
    }

    // 8. Wire Methods
    @wire(getRecord, { recordId: '$recordId', fields: ACCOUNT_FIELDS })
    wiredAccount({ error, data }) {
        if (data) {
            this.account = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.account = undefined;
        }
    }

    // 9. Public Methods
    @api focus() {
        const button = this.template.querySelector('button');
        if (button) {
            button.focus();
        }
    }

    // 10. Lifecycle Hooks
    connectedCallback() {
        this.classList.add(...this.customClass.split(' '));
    }

    renderedCallback() {
        // DOM manipulation if needed
    }

    disconnectedCallback() {
        // Cleanup if needed
    }

    // 11. Private Methods (public @api methods above; handlers first, then helpers)
    handleClick() {
        this.dispatchEvent(new CustomEvent('click'));
    }

    setColorClasses() {
        // Set color classes
    }
}

Component Metadata

.js-meta.xml Structure

Usage: Define component metadata in .js-meta.xml file.

Required Elements:

  • apiVersion - API version for the component
  • isExposed - Whether component is exposed for use
  • masterLabel - Display label for the component
  • description - Description of the component
  • targets - Where the component can be used
  • targetConfigs - Configuration for specific targets

Example:

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>65.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Action Button</masterLabel>
    <description>Reusable action button component with multiple variants and customization options.</description>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
        <target>lightningCommunity__Page</target>
        <target>lightningCommunity__Default</target>
        <target>lightning__FlowScreen</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__AppPage,lightning__RecordPage,lightning__HomePage">
            <property name="label" type="String" label="Button Label" description="The text displayed on the button." />
            <property name="variant" type="String" label="Variant" datasource="brand,neutral,destructive" description="The button variant style." />
            <property name="disabled" type="Boolean" label="Disabled" description="Whether the button is disabled." default="false" />
        </targetConfig>
        <targetConfig targets="lightningCommunity__Default">
            <property name="label" type="String" label="Button Label" description="The text displayed on the button." />
            <property name="variant" type="String" label="Variant" datasource="brand,neutral,destructive" description="The button variant style." />
        </targetConfig>
        <targetConfig targets="lightning__FlowScreen">
            <property name="label" type="String" label="Button Label" role="inputOnly" />
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

API Version

Usage: Use the latest API version from the project (currently 65.0).

Guidelines:

  • Keep API versions consistent across components
  • Update API versions as part of regular maintenance
  • Don't manually set API version unless necessary

Targets

Common Targets:

  • lightning__AppPage - Lightning App pages
  • lightning__RecordPage - Record detail pages
  • lightning__HomePage - Home pages
  • lightningCommunity__Page - Experience Cloud pages
  • lightningCommunity__Default - Experience Cloud default pages
  • lightning__FlowScreen - Flow screens

TargetConfigs

Usage: Define different property configurations for different targets.

Guidelines:

  • Use targetConfigs to customize properties per target
  • Use datasource for property values with predefined options
  • Use role="inputOnly" for Flow input-only properties
  • Provide meaningful label and description for each property

Property Types:

  • String - Text values
  • Boolean - True/false values
  • Integer - Numeric values
  • Object - Complex objects

Component Metadata Best Practices

  • Always provide meaningful masterLabel and description
  • Define appropriate targets for component usage
  • Use targetConfigs to customize properties per target
  • Provide helpful description text for each property
  • Use datasource for properties with predefined options
  • Keep API versions consistent

Import Organization

Import Order

Guidelines:

  1. Lightning Web Component imports (lwc)
  2. Lightning platform imports (lightning/*)
  3. Salesforce imports (@salesforce/*)
  4. Third-party library imports
  5. Local utility imports (c/*)

Examples:

// 1. LWC imports
import { LightningElement, api, wire } from 'lwc';

// 2. Lightning platform imports
import { NavigationMixin } from 'lightning/navigation';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
import { getRecord } from 'lightning/uiRecordApi';
import { MessageContext } from 'lightning/messageService';

// 3. Salesforce imports
import getAccountData from '@salesforce/apex/AccountController.getAccountData';
import SELECTED_CHANNEL from '@salesforce/messageChannel/exampleChild__c';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';

// 4. Third-party imports (if any)
// import { Chart } from 'chart.js';

// 5. Local utility imports
import { isEmpty, showToast } from 'c/exampleUtils';
import ExampleRecordUtils from 'c/exampleRecordUtils';

Import Grouping

Guidelines:

  • Group imports by category
  • Use blank lines between import groups
  • Sort imports alphabetically within each group (optional but recommended)

Import Best Practices

  • Organize imports by category
  • Use consistent import ordering
  • Remove unused imports
  • Use named imports when possible
  • Group related imports together

Change History

Version 1.0 - 2026-03-26

  • Added initial version history tracking for this document.

Last Updated: 2026-03-26 Version: 1.0