Getting Started with LWC · Lesson 4 of 25
Deploy LWC and Add It to a Lightning Page
A component on your laptop helps no one. This lesson deploys it to an org, places it on a page with Lightning App Builder, and – the part that makes components truly reusable – exposes properties that admins can configure for each page without touching code.
In this lesson
- Deploying with the sf CLI
- Placing a component in Lightning App Builder
- Admin-configurable properties with targetConfigs
- Record pages and the recordId property
Deploy
sf project deploy start --source-dir force-app/main/default/lwc/announcementBanner
# or by metadata name
sf project deploy start --metadata LightningComponentBundle:announcementBanner
A successful deploy prints a table of the components it changed. Errors – a typo in the template, an unknown base component, a mismatched file name – are reported with the file and line, and nothing is saved.
Properties admins can set
Fields decorated with @api are public. Listing them in targetConfigs turns them into fields in App Builder's property panel:
<?xml version="1.0" encoding="UTF-8"?>
<!-- announcementBanner.js-meta.xml -->
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>65.0</apiVersion>
<isExposed>true</isExposed>
<masterLabel>Announcement Banner</masterLabel>
<targets>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
<target>lightning__RecordPage</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__AppPage,lightning__HomePage,lightning__RecordPage">
<property name="heading" type="String" label="Heading" default="Team update" />
<property name="message" type="String" label="Message" />
<property name="variant" type="String" label="Style" datasource="info,warning,success" default="info" />
<property name="showDismiss" type="Boolean" label="Allow dismiss" default="true" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
// announcementBanner.js
import { LightningElement, api } from 'lwc';
const ICONS = { info: 'ℹ️', warning: '⚠️', success: '✅' };
export default class AnnouncementBanner extends LightningElement {
@api heading = 'Team update';
@api message;
@api variant = 'info';
@api showDismiss = false;
dismissed = false;
get icon() {
return ICONS[this.variant] ?? ICONS.info;
}
get hasMessage() {
return Boolean(this.message);
}
handleDismiss() {
this.dismissed = true;
}
}
<!-- announcementBanner.html -->
<template>
<template lwc:if={dismissed}></template>
<template lwc:else>
<div class="slds-box slds-theme_shade">
<h2>{icon} {heading}</h2>
<template lwc:if={hasMessage}>
<p>{message}</p>
</template>
<template lwc:if={showDismiss}>
<lightning-button label="Dismiss" variant="base" onclick={handleDismiss}></lightning-button>
</template>
</div>
</template>
</template>
⚠️ Release freeze No deployments to production this Friday. [Dismiss] › click “Dismiss” (nothing rendered)
The panel mounts the component the way App Builder does: it sets the admin's values on the @api properties. One component, configured differently on every page.
| Property type | App Builder shows |
|---|---|
String | a text box; with datasource, a picklist |
Integer | a number box (supports min and max) |
Boolean | a checkbox |
Color | a colour picker (Experience Builder) |
Adding it to a page
In the org
- Opena record page → gear icon → Edit Page (or Setup → Lightning App Builder)
- Drag"Announcement Banner" from the Custom section onto the page
- Configurefill in Heading, Message and Style in the property panel
- Activatesave, then activate the page for an app, profile or record type
Record pages and recordId
On a record page, Lightning sets two special public properties automatically if your component declares them:
import { LightningElement, api } from 'lwc';
export default class RecordInfo extends LightningElement {
@api recordId; // the Id of the record being viewed, e.g. "001…"
@api objectApiName; // e.g. "Account"
}
You'll use recordId constantly – to load the record with Lightning Data Service or pass it to Apex. To limit the component to certain objects, add <objects><object>Account</object></objects> inside a lightning__RecordPage target config.
Design for admins
Good components expose a few clear properties with sensible defaults, so admins can reuse them without asking a developer. Avoid exposing technical settings (API names, JSON) unless the audience is technical.
Practice
Try it yourself
Add an Integer property
maxItems(1–10, default 5) to a component and show "Showing up to N items".Show solution
<!-- itemLimit.js-meta.xml --> <targetConfig targets="lightning__AppPage"> <property name="maxItems" type="Integer" label="Maximum items" default="5" min="1" max="10" /> </targetConfig>// itemLimit.js import { LightningElement, api } from 'lwc'; export default class ItemLimit extends LightningElement { @api maxItems = 5; }<!-- itemLimit.html --> <template> <p>Showing up to {maxItems} items</p> </template>Showing up to 8 items
Quick check
What makes a property editable in App Builder?
An @api field plus a <property> in the target config.
How does a component on a record page know which record it's on?
Declare @api recordId; Lightning sets it.
How do you turn a String property into a picklist?
Add a datasource attribute with comma-separated values.
Summary
- Deploy with sf project deploy start; place components in Lightning App Builder.
- @api fields listed in targetConfigs become admin-editable properties.
- Record pages set @api recordId and objectApiName automatically.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.