Part 72: The Basics of LWC in Salesforce
Welcome to Topic 3 of the Salesforce series — The Complete Guide to Lightning Web Components. If you have been following along, you know we just wrapped up the Apex section spanning Parts 38 through 71. That was a deep dive into everything from basic syntax and triggers to enterprise patterns, design principles, and advanced unit testing. You now have a solid backend foundation. It is time to move to the frontend.
Lightning Web Components, or LWC, is the modern framework Salesforce provides for building custom user interfaces on the Lightning Platform. Over the next several posts in this topic, we will go from zero to production-ready components. But first, you need to understand what LWC actually is, when you should reach for it, how it differs from older technologies, and how to get your environment ready to start building.
This post covers seven areas:
- What are LWC’s — The framework, its relationship to web standards, and why Salesforce built it.
- When to use LWC vs Aura — The older framework still exists, so when does each one make sense.
- When to build an LWC instead of using OOTB tools — Declarative tools are powerful, so when do you actually need custom code.
- The difference between frontend and backend code — Where each runs, what each is responsible for, and how they communicate.
- Prepping your org to develop LWC’s — My Domain, Lightning Debugger, session cache settings, and dev tools.
- How to create an LWC and its folder structure — The three files that make up every component and what each one does.
- How to place your LWC on a page in Salesforce — Getting your component visible to users through Lightning App Builder.
By the end you will have a working LWC deployed to a Salesforce page. Let’s get started.
What Are LWC’s?
Lightning Web Components is a UI framework built on modern web standards. Salesforce released it in early 2019 as the successor to the Aura Components framework (sometimes called Lightning Components). The key idea behind LWC is that it leans on the browser rather than fighting it.
Web Standards at the Core
LWC is built on three web standards that all modern browsers support natively:
- Custom Elements — The ability to define your own HTML tags like
<c-my-component>. - Shadow DOM — Encapsulation that keeps a component’s internal markup and styles isolated from the rest of the page.
- ES Modules — The standard JavaScript module system using
importandexport.
Because LWC uses these standards, the framework itself is thin. There is no massive runtime or virtual DOM sitting between your code and the browser. When you write an LWC, you are writing standard JavaScript with a small set of Salesforce-specific decorators and lifecycle hooks layered on top. If you know modern JavaScript, you are already halfway there.
How LWC Fits Into the Salesforce Stack
Think of the Salesforce Lightning Platform as a layered cake. At the bottom you have the database and metadata layer — objects, fields, records. Above that sits the business logic layer — Apex, flows, validation rules. At the top is the presentation layer — what the user actually sees and interacts with. LWC lives in that top layer.
Your LWC handles what the user sees: forms, tables, buttons, charts, modals. When it needs data or needs to perform a server-side operation, it calls down to Apex (or uses Lightning Data Service) to talk to the layers below. This separation is important and we will dig into it more later in this post.
Why Salesforce Built LWC
The Aura framework was released in 2014 and served the platform well, but it came with baggage. It had its own component model, its own expression language, its own event system, and its own rendering engine. Developers coming from the broader JavaScript ecosystem had to learn an entirely proprietary stack. LWC was Salesforce’s answer: keep the platform integration but align with how the rest of the web development world builds components.
The result is that LWC components are faster (less framework overhead), smaller (less code shipped to the browser), and easier to learn for anyone with JavaScript experience.
When to Use LWC vs Aura
Aura is not going away. Salesforce still supports it and there are millions of Aura components running in production orgs. But the direction is clear — new development should use LWC unless you have a specific reason not to.
Use LWC When
- You are building a new component from scratch. There is no reason to start a new project in Aura in 2025.
- You need better performance. LWC renders faster because it does less behind the scenes.
- You want to take advantage of modern JavaScript features like async/await, template literals, destructuring, and ES modules.
- You are building components that will be used in Experience Cloud (community) sites or mobile apps, where performance matters even more.
- You want a larger hiring pool. Developers who know React, Vue, or Angular can pick up LWC quickly because the patterns are similar.
Use Aura When
- You need to work with existing Aura components that cannot be rewritten right now. Aura components can contain LWC children, but LWC components cannot contain Aura children. If your page is heavily Aura-based, sometimes it is easier to stay in Aura for that particular feature.
- You need certain Aura-only features that LWC does not yet support. This list shrinks with every Salesforce release, but there are still edge cases. For example, some Lightning Out scenarios or certain deeply integrated Aura events may still require Aura.
- You are doing a quick fix to an existing Aura component and a full rewrite is not justified.
The General Rule
If you are starting fresh, use LWC. If you are maintaining existing Aura code and the effort to rewrite is not justified, stay in Aura for that component. Over time, migrate Aura components to LWC as you touch them.
When to Build an LWC Instead of Using OOTB Tools
Salesforce gives you a lot of power without writing a single line of code. Before you create a custom component, you should always ask: can I do this declaratively?
Out-of-the-Box Tools to Consider First
- Lightning App Builder — Drag-and-drop page layouts with standard components like Related Lists, Record Detail, Rich Text, and more.
- Dynamic Forms and Dynamic Actions — Field-level control on record pages without code.
- Flow — Screen Flows can build multi-step forms, wizards, and approval processes with a visual builder.
- Reports and Dashboards — For displaying data in charts and tables.
- List Views — Configurable views with filters, inline editing, and charts built in.
When Custom LWC is the Right Choice
You should build a custom LWC when:
- The user experience you need does not exist in any standard component. For example, a custom drag-and-drop Kanban board for managing opportunities.
- You need real-time interactivity that declarative tools cannot provide. Think auto-complete search fields, live-updating dashboards, or inline editing with complex validation.
- You need to integrate with external APIs or services on the frontend. Calling a third-party mapping API to render a custom map, for instance.
- You need complex conditional logic in the UI that would make a Flow unwieldy. If your Screen Flow has 40 decision nodes just to control field visibility, an LWC might be cleaner.
- You need reusable components that appear in multiple contexts — record pages, app pages, community pages, utility bars — with different configurations.
- You need pixel-perfect control over styling and layout that standard components do not offer.
The Decision Framework
Start declarative. If you hit a wall — the standard component does not exist, the Flow becomes unmanageable, the requirement demands interactivity that configuration cannot provide — then build an LWC. Custom code costs more to build, test, and maintain. Make sure you actually need it before you write it.
The Difference Between Frontend and Backend Code
If you have only worked with Apex and Flows up to this point, you have been writing backend code. LWC introduces frontend code into your Salesforce toolkit. Understanding where each runs and what each does is essential.
Backend Code (Server-Side)
Backend code runs on Salesforce’s servers. This includes:
- Apex classes and triggers — Business logic, data manipulation, callouts.
- SOQL and SOSL — Querying the database.
- Flows — Automation that runs on the server (record-triggered flows, scheduled flows, autolaunched flows).
- Validation rules, formula fields, workflow rules — Declarative logic that executes server-side.
Backend code has direct access to the database. It can query, insert, update, and delete records. It runs in a secure, governor-limit-enforced environment. The user never sees this code or interacts with it directly.
Frontend Code (Client-Side)
Frontend code runs in the user’s browser. This includes:
- LWC JavaScript — Component logic, event handling, UI state management.
- LWC HTML templates — The markup that defines what the user sees.
- CSS — Styling for your components.
Frontend code has no direct database access. It cannot run SOQL. It cannot insert records on its own. When it needs data, it has to ask the backend. This request-response pattern is how every web application works.
How They Communicate
LWC provides two main ways for the frontend to talk to the backend:
-
Apex Methods — You mark an Apex method with
@AuraEnabledand call it from your LWC JavaScript usingimport. The call is asynchronous — your LWC sends a request to the server, continues rendering, and handles the response when it comes back. -
Lightning Data Service (LDS) — A built-in data layer that lets you read and write Salesforce records without writing any Apex at all. LDS handles caching, sharing rules, and field-level security automatically. For simple CRUD operations, LDS is often all you need.
Here is a simplified mental model:
User's Browser Salesforce Server
----------------- ------------------
LWC (HTML + JS + CSS) <------> Apex (@AuraEnabled)
SOQL / DML
Database
The user clicks a button in your LWC. The JavaScript handles the click event, calls an Apex method, receives the data, and updates the component’s HTML to display the result. This round trip happens over the network and takes milliseconds to hundreds of milliseconds depending on complexity.
Prepping Your Org to Develop LWC’s
Before you write a single line of LWC code, your Salesforce org needs a few things configured. If you are using a Developer Edition org or a Trailhead Playground, most of this is already done, but it is worth checking.
Enable My Domain
My Domain is a custom subdomain for your Salesforce org. It is required for Lightning Components (both Aura and LWC) to function. Without it, your custom components will not render.
To check or enable it:
- Go to Setup.
- Search for My Domain in the Quick Find box.
- If My Domain is not set up, follow the prompts to choose a domain name and deploy it.
Most modern orgs have My Domain enabled by default. If yours does not, set it up now. Salesforce will not let you deploy LWC’s without it.
Enable Lightning Experience
This should go without saying in 2025, but your org must be running Lightning Experience, not Salesforce Classic. LWC only renders in the Lightning runtime.
Install and Configure Salesforce CLI
The Salesforce CLI (command line interface) is the primary tool for creating, deploying, and retrieving LWC’s. You can also use VS Code with the Salesforce Extension Pack, which wraps the CLI in a graphical interface.
To install:
- Download the Salesforce CLI from the Salesforce developer tools page.
- Install the Salesforce Extension Pack in VS Code.
- Authorize your org using
sf org login web(or the oldersfdx auth:web:login).
Once authorized, you can push and pull components between your local machine and your org.
Enable Debug Mode for Lightning Components
Debug mode gives you unminified JavaScript in the browser, which makes it much easier to read error messages and step through code in browser DevTools.
To enable it:
- Go to Setup.
- Search for Debug Mode in the Quick Find box.
- Find your user in the list and check the Enable checkbox.
Keep this turned on in your development org. Turn it off in production — minified code loads faster for end users.
Session Cache Settings
When you are developing and testing LWC’s, cached JavaScript can cause confusion. You make a change, deploy it, refresh the page, and see the old version. To avoid this:
- Go to Setup > Session Settings.
- Under the Caching section, uncheck Enable secure and persistent browser caching to improve performance.
This forces the browser to fetch fresh JavaScript on every page load. Again, only do this in development. In production you want caching enabled for performance.
Browser Developer Tools
Get comfortable with your browser’s DevTools. In Chrome, press F12 or Cmd+Option+I on Mac. The tabs you will use most:
- Console — JavaScript errors, log output from
console.log()statements in your LWC. - Elements — Inspect the rendered DOM of your components. Note that Shadow DOM elements appear nested under a
#shadow-rootnode. - Network — Watch the Apex calls your LWC makes. Look for requests to
/auraendpoints. - Sources — Set breakpoints in your JavaScript code and step through it line by line.
Salesforce also provides a Lightning Inspector Chrome extension that shows component hierarchy, event flow, and performance metrics. It is useful but not required.
How to Create an LWC (and Its Folder Structure)
Now we get to the good part. Let’s create your first Lightning Web Component.
The LWC Folder Structure
Every LWC lives inside the force-app/main/default/lwc/ directory in your Salesforce DX project. Each component gets its own folder, and the folder name IS the component name. The folder contains at minimum three files:
force-app/
main/
default/
lwc/
helloWorld/
helloWorld.html
helloWorld.js
helloWorld.js-meta.xml
Let’s break down each file.
The HTML File — helloWorld.html
This is your component’s template. It defines what the user sees. Every LWC HTML file must be wrapped in a <template> tag.
<template>
<lightning-card title="Hello World" icon-name="custom:custom14">
<div class="slds-m-around_medium">
<p>Hello, {greeting}!</p>
<lightning-input
label="Enter your name"
value={greeting}
onchange={handleChange}>
</lightning-input>
</div>
</lightning-card>
</template>
A few things to notice:
<template>is mandatory and wraps everything.{greeting}is a JavaScript expression bound to a property in your JS file. When the property changes, the template re-renders automatically.<lightning-card>and<lightning-input>are base Lightning components provided by Salesforce. You do not need to build these — they come with the platform and follow the Salesforce Lightning Design System (SLDS) styling.onchange={handleChange}binds a DOM event to a JavaScript method.
The JavaScript File — helloWorld.js
This is your component’s brain. It contains the logic, properties, and methods.
import { LightningElement } from 'lwc';
export default class HelloWorld extends LightningElement {
greeting = 'World';
handleChange(event) {
this.greeting = event.target.value;
}
}
Let’s walk through it:
import { LightningElement } from 'lwc'— Every LWC importsLightningElementas its base class. This is what makes your class a Lightning Web Component.export default class HelloWorld extends LightningElement— Your component class extendsLightningElement. The class name uses PascalCase while the folder and file names use camelCase.greeting = 'World'— A reactive property. When you change its value, any part of the template that references{greeting}re-renders automatically. This is reactivity out of the box — nosetState()calls needed.handleChange(event)— An event handler. Theeventobject is a standard DOM event.event.target.valuegives you the current value of the input field.
The Metadata File — helloWorld.js-meta.xml
This is the configuration file that tells Salesforce where your component can be used. It is XML and looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>62.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
This file is critical. Here is what each element does:
<apiVersion>— The Salesforce API version your component uses. Use a recent version. As of late 2025, version 62.0 is current.<isExposed>— Must betrueif you want the component to appear in Lightning App Builder. If this isfalseor missing, your component will not show up when you try to drag it onto a page.<targets>— Where the component can be placed. Common targets include:lightning__RecordPage— On a record detail page (Account, Contact, Opportunity, etc.).lightning__AppPage— On a custom app page.lightning__HomePage— On the Lightning Experience home page.lightning__FlowScreen— Inside a Screen Flow.lightningCommunity__Page— In an Experience Cloud site.
Without the correct targets, your component exists but has nowhere to live.
Optional Files
Your component folder can also include:
helloWorld.css— Component-scoped styles. These styles only apply inside your component thanks to Shadow DOM encapsulation.helloWorld.test.js— Jest unit tests for your component.__tests__/— A folder for organizing multiple test files.- Additional HTML files — Used as extra templates you can switch between dynamically.
Creating the Component
Using Salesforce CLI, run this command from your project root:
sf lightning generate component --type lwc --name helloWorld --output-dir force-app/main/default/lwc
This generates the folder and the three core files for you. You can also create them manually — there is no magic in the generator. It just saves you from creating boilerplate by hand.
Deploying to Your Org
Once your files are saved, deploy with:
sf project deploy start --source-dir force-app/main/default/lwc/helloWorld
Or if you are using VS Code with the Salesforce Extension Pack, right-click the component folder and select Deploy Source to Org. Both approaches do the same thing — push your local files to the connected Salesforce org.
How to Place Your LWC on a Page in Salesforce
You have written the code and deployed it. Now you need to put it somewhere a user can actually see it.
Using Lightning App Builder
- Navigate to the page where you want the component to appear. For example, go to any Account record.
- Click the gear icon in the upper right and select Edit Page. This opens Lightning App Builder.
- In the left-hand panel, look for the Custom section under Components. Your
helloWorldcomponent should appear there. If it does not, double-check thatisExposedistruein your metadata XML and that your targets include the correct page type. - Drag your component from the panel onto the page layout. Drop it wherever you want it to appear — the main content area, the sidebar, a tab, etc.
- Click Save.
- If this is the first time you are customizing this page, Lightning App Builder will ask you to activate the page. You can assign it as the org default, an app default, or a form-factor-specific default (desktop vs phone). For testing, assign it as the org default.
- Click Back to return to the record page. Your component should now be visible.
Verifying It Works
After placing the component, you should see a card titled “Hello World” with an input field. Type your name into the input. The greeting text above should update in real time as you type. No page refresh, no server call — this is all happening in the browser through LWC’s built-in reactivity.
If something is wrong:
- Component does not appear in App Builder — Check
isExposedandtargetsin the XML file. Redeploy if you made changes. - Component appears but shows an error — Open browser DevTools and check the Console tab. JavaScript errors will point you to the problem.
- Component appears but looks broken — Check that your HTML is wrapped in
<template>tags and that your JavaScript property names match the references in your template.
Other Places You Can Use LWC
Lightning App Builder is the most common way to place components, but it is not the only way:
- Lightning Tabs — Create a custom tab that renders your LWC as a full-page experience.
- Utility Bar — Add your component to the utility bar at the bottom of the screen for quick-access tools.
- Screen Flows — Embed your LWC inside a Flow screen for custom input forms.
- Experience Cloud — Use your component in community pages (requires the
lightningCommunity__Pagetarget). - Quick Actions — Launch your LWC as a modal from a record page action button.
Each of these requires specific targets in your metadata XML file, which we will explore in detail in later posts.
Section Notes
- LWC is built on web standards — Custom Elements, Shadow DOM, and ES Modules. It is not a proprietary framework. If you know JavaScript, you can learn LWC.
- Use LWC for new development. Aura still works but LWC is faster, lighter, and aligned with the direction Salesforce is heading. Only stay in Aura if you are maintaining existing Aura components and a rewrite is not justified.
- Start declarative. Before building a custom component, check if standard components, Dynamic Forms, or Flows can solve the problem. Custom code costs more to maintain.
- Frontend code runs in the browser, backend code runs on the server. LWC handles what the user sees. Apex handles data and business logic. They communicate through
@AuraEnabledmethods or Lightning Data Service. - Prep your org before developing. Enable My Domain, turn on Debug Mode for your user, disable session caching in development, and get comfortable with browser DevTools.
- Every LWC has three core files — an HTML template, a JavaScript class, and a metadata XML configuration file. The folder name is the component name.
- The metadata XML file controls visibility. Set
isExposedtotrueand definetargetsto make your component available in Lightning App Builder. - Deploy with Salesforce CLI or VS Code and place your component on a page using Lightning App Builder’s drag-and-drop interface.
In the next post, we will go deeper into LWC component structure — lifecycle hooks, decorators like @api, @track, and @wire, and how data flows between parent and child components. See you there.