Skip to content
SalesforceSkills

External Sites

Build customer-facing websites and portals with Experience Cloud. Handles branding, navigation, and SEO.

Brand-first, not SLDS-firstGuest-safePerformanceSEO-awareResponsive

Skill Details

Install this skill

Versionv1.1.0AuthorJorge ArteagaLicenseMITSections11

Works with

Claude CodeCursorWindsurf

Build Lightning Web Components for external-facing Experience Cloud sites. Different design rules apply compared to internal Lightning pages — public audiences, branding requirements, SEO, and guest user security.

Core Principles

1
Brand-first, not SLDS-first — external sites use customer branding, not Salesforce blue
2
Guest-safe — every component must handle unauthenticated users gracefully
3
Performance — external sites face real-world network conditions
4
SEO-aware — content must be crawlable and metadata-rich
5
Responsive — external users are on any device, not just desktop

Experience Cloud vs Internal Lightning

Theme Customization

Experience Cloud sites use a separate theme system. Components should consume theme tokens, not hardcode brand colors.

Theme Token Consumption

CSS
.hero-banner {
    background-color: var(--dxp-g-root, var(--slds-g-color-surface-1, #ffffff));
    color: var(--dxp-g-root-contrast, var(--slds-g-color-on-surface-1, #181818));
}

.brand-accent {
    color: var(--dxp-s-brand-1, var(--slds-g-color-accent-1, #0176d3));
}

.brand-button {
    background: var(--dxp-s-brand-1, var(--slds-g-color-accent-1, #0176d3));
    color: var(--dxp-s-brand-1-contrast, var(--slds-g-color-on-accent-1, #ffffff));
    border-radius: var(--dxp-s-button-radius,
        var(--slds-g-radius-border-2, 0.25rem));
}

.nav-link {
    color: var(--dxp-s-link-text-color, var(--slds-g-color-accent-1, #0176d3));
}

.nav-link: hover {
    color: var(--dxp-s-link-text-color-hover, var(--slds-g-color-accent-2, #014486));
}

DXP Token Categories

Fallback Chain

Always fall back from DXP tokens to SLDS hooks to literal values:

CSS
color: var(--dxp-s-brand-1, var(--slds-g-color-accent-1, #0176d3));

This ensures the component works in Experience Cloud (DXP tokens), internal Lightning (SLDS hooks), and degraded environments (literal fallback).

Guest User Design

Authentication-Aware Components

JavaScript
import { LightningElement, wire } from class="code-string">'lwc';
import isGuest from class="code-string">'@salesforce/user/isGuest';
import Id from class="code-string">'@salesforce/user/Id';

export default class MyComponent extends LightningElement {
    get isAuthenticated() {
        return !isGuest;
    }

    get userId() {
        return Id;
    }
}
HTML
<class="code-tag">template>
    class="code-comment"><!-- Authenticated: full experience -->
    <class="code-tag">template if:true={isAuthenticated}>
        <class="code-tag">c-full-dashboard></class="code-tag">c-full-dashboard>
    </class="code-tag">template>

    class="code-comment"><!-- Guest: limited experience with CTA to log in -->
    <class="code-tag">template if:false={isAuthenticated}>
        <class="code-tag">div class="guest-cta">
            <class="code-tag">h2 class="guest-cta__title">Sign in to view your dashboard</class="code-tag">h2>
            <class="code-tag">p class="guest-cta__description">
                Access your account details, open cases, and recent activity.
            </class="code-tag">p>
            <class="code-tag">lightning-button label="Sign In" variant="brand" onclick={handleLogin}>
            </class="code-tag">lightning-button>
        </class="code-tag">div>
    </class="code-tag">template>
</class="code-tag">template>

Guest User Security Checklist

  • Never expose record IDs, org IDs, or internal URLs to guests
  • Never query data without WITH SECURITY_ENFORCED or FLS checks
  • Use @AuraEnabled(cacheable=true) for guest-visible Apex methods
  • Validate all input from guest users (treat as untrusted)
  • Never expose admin email addresses or internal team names

Community Navigation

JavaScript
import { NavigationMixin } from class="code-string">'lightning/navigation';

export default class MyComponent extends NavigationMixin(LightningElement) {
    navigateToPage(pageName) {
        this[NavigationMixin.Navigate]({
            type: class="code-string">'comm__namedPage',
            attributes: { name: pageName }
        });
    }

    navigateToRecord(recordId) {
        this[NavigationMixin.Navigate]({
            type: class="code-string">'standard__recordPage',
            attributes: {
                recordId: recordId,
                actionName: class="code-string">'view'
            }
        });
    }

    navigateToExternalUrl(url) {
        this[NavigationMixin.Navigate]({
            type: class="code-string">'standard__webPage',
            attributes: { url }
        });
    }
}
HTML
<class="code-tag">template>
    <class="code-tag">nav aria-label="Breadcrumb">
        <class="code-tag">ol class="breadcrumb">
            <class="code-tag">template for:each={breadcrumbs} for:item="crumb">
                <class="code-tag">li key={crumb.id} class="breadcrumb__item">
                    <class="code-tag">a if:false={crumb.isCurrent}
                       href={crumb.url}
                       onclick={handleNavigate}
                       data-page={crumb.page}>
                        {crumb.label}
                    </class="code-tag">a>
                    <class="code-tag">span if:true={crumb.isCurrent} aria-current="page">
                        {crumb.label}
                    </class="code-tag">span>
                </class="code-tag">li>
            </class="code-tag">template>
        </class="code-tag">ol>
    </class="code-tag">nav>
</class="code-tag">template>

Experience Builder Configuration

meta.xml for Experience Cloud

XML
<?xml version="1.0" encoding="UTF-8"?>
<class="code-tag">LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <class="code-tag">apiVersion>62.0</class="code-tag">apiVersion>
    <class="code-tag">isExposed>true</class="code-tag">isExposed>
    <class="code-tag">masterLabel>Customer Knowledge Base</class="code-tag">masterLabel>
    <class="code-tag">description>Searchable knowledge articles for site visitors.</class="code-tag">description>
    <class="code-tag">targets>
        <class="code-tag">target>lightningCommunity__Page</class="code-tag">target>
        <class="code-tag">target>lightningCommunity__Default</class="code-tag">target>
    </class="code-tag">targets>
    <class="code-tag">targetConfigs>
        <class="code-tag">targetConfig targets="lightningCommunity__Default">
            <class="code-tag">property name="heading" type="String" label="Section Heading"
                      default="Knowledge Base" />
            <class="code-tag">property name="maxArticles" type="Integer" label="Articles to Show"
                      default="10" min="3" max="50" />
            <class="code-tag">property name="showSearch" type="Boolean" label="Show Search Bar"
                      default="true" />
        </class="code-tag">targetConfig>
    </class="code-tag">targetConfigs>
</class="code-tag">LightningComponentBundle>

Target Reference

Demo Portal Templates

Pre-built patterns for common SE demo scenarios using Experience Cloud.

Customer Self-Service Portal

COMPONENTS NEEDED:
  - Hero banner with brand colors and welcome message
  - Case submission form (guest-aware)
  - Open cases list (authenticated only)
  - Knowledge article search
  - FAQ accordion

PAGE LAYOUT:
  ┌──────────────────────────────────────┐
  │  Hero: "Welcome to {Brand} Support"  │
  ├──────────────────────────────────────┤
  │  Search Bar: "How can we help?"      │
  ├──────────┬───────────────────────────┤
  │  My Cases │  Knowledge Articles      │
  │  (list)   │  (card grid)             │
  ├──────────┴───────────────────────────┤
  │  FAQ Accordion                       │
  └──────────────────────────────────────┘

DEMO STORY:
  "A customer visits the support portal. They search for an answer,
   find a knowledge article, but still need help. They submit a case
   directly from the portal and track its progress."

Partner Portal

COMPONENTS NEEDED:
  - Partner dashboard with KPIs (deal reg, MDF balance, certifications)
  - Deal registration form
  - Co-branded marketing assets library
  - Training/certification tracker

PAGE LAYOUT:
  ┌──────────────────────────────────────┐
  │  Welcome, {Partner Name}             │
  ├────────┬────────┬────────┬───────────┤
  │  Deal  │  MDF   │ Certs  │ Pipeline  │
  │  Regs  │Balance │ Status │  Value    │
  ├────────┴────────┴────────┴───────────┤
  │  Recent Deal Registrations (table)   │
  ├──────────────────────────────────────┤
  │  Marketing Assets | Training         │
  └──────────────────────────────────────┘

Patient Portal (Health Cloud)

COMPONENTS NEEDED:
  - Patient greeting with upcoming appointments
  - Care plan progress tracker
  - Appointment scheduler
  - Secure messaging
  - Health record summary

PAGE LAYOUT:
  ┌──────────────────────────────────────┐
  │  Hi {Patient Name} — Next appt: 3/15│
  ├──────────┬───────────────────────────┤
  │  Care    │  Upcoming Appointments    │
  │  Plan    │  ┌─────────────────────┐  │
  │  Progress│  │ Dr. Smith | Mar 15  │  │
  │  (gauge) │  │ Lab Work  | Mar 22  │  │
  ├──────────┴──┴─────────────────────┴──┤
  │  Messages (2 unread)                 │
  └──────────────────────────────────────┘

Performance for External Sites

Critical Rendering Path

HTML
<class="code-tag">template>
    class="code-comment"><!-- Above the fold: render immediately -->
    <class="code-tag">div class="hero">
        <class="code-tag">h1>{headline}</class="code-tag">h1>
        <class="code-tag">p>{subheadline}</class="code-tag">p>
    </class="code-tag">div>

    class="code-comment"><!-- Below the fold: lazy load -->
    <class="code-tag">template if:true={belowFoldVisible}>
        <class="code-tag">c-article-grid articles={articles}></class="code-tag">c-article-grid>
    </class="code-tag">template>
</class="code-tag">template>
JavaScript
_belowFoldVisible = false;

connectedCallback() {
    requestAnimationFrame(() => {
        this._belowFoldVisible = true;
    });
}

Image Optimization

HTML
<class="code-tag">img src={imageUrl}
     alt={imageAlt}
     loading="lazy"
     width="400"
     height="300"
     class="responsive-img" />
CSS
.responsive-img {
    width: 100%;
    height: auto;
    border-radius: var(--slds-g-radius-border-2, 0.25rem);
}

SEO Considerations

  • Use semantic HTML:

    for page title,

    for sections,
    for content blocks

  • Add tags via Head Markup in Experience Builder (not in LWC)
  • Use meaningful link text: View case details not Click here
  • Provide alt text on all images
  • Structured data (JSON-LD) via Head Markup for articles and FAQs

Scoring Rubric (100 Points)Reference

Cross-Skill IntegrationReference

AspectInternal LightningExperience Cloud
AudienceEmployeesCustomers, partners, public
BrandingSalesforce/org themeCustom brand colors, fonts, logos
AuthenticationAlways logged inGuest users, self-registration
CSS scopeShadow DOM onlyShadow DOM + global theme CSS
NavigationLightning tabs/appCommunity navigation, URL routing
PerformanceCorporate networkPublic internet, mobile, slow
SEONot applicableCritical for public sites
PrefixCategoryExamples
--dxp-g-Globalroot, root-contrast, root-inverse
--dxp-s-brand-Brand colorsbrand-1, brand-1-contrast, brand-2
--dxp-s-link-Linkslink-text-color, link-text-color-hover
--dxp-s-button-Buttonsbutton-radius, button-color
--dxp-s-text-Typographytext-heading-large, text-body
TargetWhere
lightningCommunity__PageExperience Builder page (any)
lightningCommunity__DefaultDefault community layout
lightningCommunity__Page_LayoutPage layout region
CategoryPointsPass Criteria
Theme Compliance20Uses --dxp-* tokens with SLDS fallbacks; no hardcoded brand colors
Guest User Handling20Auth-aware rendering; secure data access; graceful guest CTA
Navigation15Uses NavigationMixin; breadcrumbs; accessible link patterns
Experience Builder Config15Correct targets; configurable properties; sensible defaults
Performance15Lazy loading; optimized images; minimal DOM
SEO & Accessibility15Semantic HTML; alt text; meaningful link text; aria labels
SkillRelationship
sf-lwc-designSLDS 2 hooks used as fallbacks when DXP tokens aren't available
sf-lwc-themingCustom theme creation for Experience Cloud sites
sf-lwc-mobileExternal sites have high mobile traffic — mobile patterns critical
sf-lwc-contentMicrocopy must be guest-friendly, no internal jargon
sf-se-demo-scriptsPortal templates feed directly into demo flows

Navigate Salesforce Platform