lwc-light-dom

Use when a Lightning Web Component needs to escape shadow DOM isolation so Experience Cloud / LWR sites can be SEO-indexed, a third-party library can walk the DOM, global styling has to reach inside the component, or accessibility tooling must see the rendered tree. NOT for the default shadow DOM behavior most LWCs should use — reach for light DOM only when SEO, third-party DOM access, or global styling requires it, and never for components distributed through managed packages.

Best use case

lwc-light-dom is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use when a Lightning Web Component needs to escape shadow DOM isolation so Experience Cloud / LWR sites can be SEO-indexed, a third-party library can walk the DOM, global styling has to reach inside the component, or accessibility tooling must see the rendered tree. NOT for the default shadow DOM behavior most LWCs should use — reach for light DOM only when SEO, third-party DOM access, or global styling requires it, and never for components distributed through managed packages.

Teams using lwc-light-dom should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/lwc-light-dom/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/lwc/lwc-light-dom/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/lwc-light-dom/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How lwc-light-dom Compares

Feature / Agentlwc-light-domStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use when a Lightning Web Component needs to escape shadow DOM isolation so Experience Cloud / LWR sites can be SEO-indexed, a third-party library can walk the DOM, global styling has to reach inside the component, or accessibility tooling must see the rendered tree. NOT for the default shadow DOM behavior most LWCs should use — reach for light DOM only when SEO, third-party DOM access, or global styling requires it, and never for components distributed through managed packages.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# LWC Light DOM

Activate this skill when a Lightning Web Component needs to break out of shadow DOM isolation — usually because search engine crawlers, a third-party JavaScript library, a global stylesheet, or accessibility tooling cannot see into the shadow tree. Light DOM is an escape hatch, not a default.

---

## Before Starting

Gather this context before switching a component's render mode:

- What is the real blocker? (SEO indexing on Experience Cloud, a tooltip/chart library's `document.querySelector`, a global CSS system, screen-reader or analytics tooling.) Do not reach for light DOM to "fix" a CSS specificity issue you have not tried to solve with styling hooks.
- Where will the component run? Internal Lightning Experience pages rarely need light DOM. Experience Cloud LWR sites are the common home for it. Experience Cloud Aura sites and managed-package distribution have extra rules.
- Will the component ship through a managed package? Salesforce explicitly recommends **against** light DOM for managed-package components because their styles would leak into consumer orgs.
- Is the LWC ecosystem still subject to Lightning Web Security (LWS)? Yes — LWS sandboxes JavaScript regardless of render mode.

---

## Core Concepts

### Opting Into Light DOM

Light DOM is enabled two ways and both must line up:

1. On the class, set the static property `renderMode`:
   ```javascript
   import { LightningElement } from 'lwc';
   export default class FaqAccordion extends LightningElement {
       static renderMode = 'light';
   }
   ```
2. On the root `<template>` tag, set `lwc:render-mode="light"`. You cannot mix modes within one template — the root template sets the mode for the whole component.

Once both are in place, `this.template` no longer wraps a shadow root and standard DOM APIs such as `document.querySelector`, external CSS, and native screen-reader traversal can see the rendered markup.

### Scoped vs Unscoped Styles (the `*.scoped.css` Convention)

Light DOM styles **bleed** by default because there is no shadow boundary to contain them. Salesforce provides the `*.scoped.css` file-naming convention: a file named `faqAccordion.scoped.css` is compiled with synthesized, component-specific attribute selectors so its rules stay tied to this component's elements. A plain `faqAccordion.css` sitting next to a light-DOM component is **global** and will leak to every consumer on the page. You typically want the scoped file for component-owned styles and, if you need intentional global theming, an additional unscoped file — not the other way around.

### Why Light DOM Costs You Encapsulation

In shadow DOM, styles, IDs, and event retargeting stay inside the component. Light DOM gives that up on purpose: global CSS can reach in, so can third-party scripts, so can `aria` relationships that depend on IDs being visible across the page. That is the whole point — but it also means naming collisions, leaked selectors, and unsanitized HTML become your responsibility.

### Interop: Third-Party Libraries, SEO, Accessibility

- **Third-party libraries** (d3, Chart.js, tooltip/popover libs, any code that calls `document.querySelector`) cannot traverse into a shadow root from outside. Light DOM restores that access.
- **SEO on Experience Cloud LWR sites** requires that crawlers see the rendered HTML. Shadow DOM content is not reliably indexed; light DOM content is plain markup in the page source.
- **Accessibility and analytics tooling** (screen-reader testing harnesses, Selenium/WebDriver automation, heatmap and analytics scripts) can reach light-DOM elements with standard selectors, which simplifies integration.

### Lightning Web Security Still Applies

A common mistake is to assume light DOM disables LWS. It does not. LWS continues to sandbox JavaScript, intercept global APIs, and enforce namespace isolation. Light DOM only changes where the rendered markup lives — it does not open JS back up to the page.

### Managed Packages: Do Not Ship Light DOM

Salesforce guidance is explicit: do not distribute light-DOM components inside managed packages. Their un-encapsulated styles would bleed into any consumer org's pages, and consumers cannot scope them after install.

---

## Common Patterns

### Experience Cloud LWR Component That Must Be Indexed

**When to use:** Public-facing FAQ, blog post, product description, or marketing module on an LWR site that needs to rank in search.

**How it works:** Set `static renderMode = 'light'` on the class, `lwc:render-mode="light"` on the root template, and put component styles in `<name>.scoped.css`. Render the user-visible text as plain DOM (no shadowed slot tricks) so the crawler sees it.

**Why not the alternative:** Leaving the component in shadow DOM leaves the content invisible to many crawlers and broken for some third-party SEO/analytics scripts.

### Third-Party Library Integration

**When to use:** A library like a tooltip, chart, or drag-and-drop framework needs to call `document.querySelector` or attach listeners to a specific element inside the component.

**How it works:** Switch to light DOM, give the target element a stable class or ID, and let the library's external script find it from the document. Keep JS sandboxed — LWS will still enforce API restrictions.

**Why not the alternative:** Trying to bridge shadow DOM with `::part`, custom events, or manual ref passing usually ends up fighting the library and is fragile across versions.

### Intentional Global Theming From An Experience Cloud Branding Set

**When to use:** The site's branding system (fonts, color tokens, spacing) must reach all public-facing components uniformly.

**How it works:** Use light DOM for the components that must receive global theming, and let Experience Cloud branding CSS flow in. Keep layout and component-specific visual rules in the `*.scoped.css` file so they do not leak outward.

---

## Decision Guidance

| Situation | Recommended Approach | Reason |
|---|---|---|
| SEO indexing required on an Experience Cloud LWR site | Light DOM with `*.scoped.css` | Crawlers need to see rendered markup directly |
| Internal LEX-only admin or productivity component | Shadow DOM (default) | Encapsulation and style isolation win; no external consumers need DOM access |
| Third-party JS library must query/attach to a specific element | Light DOM | Libraries calling `document.querySelector` cannot cross the shadow boundary |
| Reusable widget meant to be embedded in many pages / flows | Shadow DOM (default) | Prevents cross-page style leaks and collisions |
| Managed-package component shipped to consumer orgs | Shadow DOM (required by Salesforce guidance) | Light-DOM styles would leak into every consumer org |
| Global theming system (Experience Cloud branding) must flow in | Light DOM for the themed components | Shadow DOM blocks inherited theming by design |
| Accessibility/screen-reader or analytics tooling needs to traverse | Light DOM with care | External tools can read the DOM; sanitize any user-provided HTML |

---

## Recommended Workflow

Step-by-step instructions for an AI agent or practitioner activating this skill:

1. Confirm the blocker — SEO, third-party DOM access, global styling, or a11y/analytics tooling. If none of these apply, stay in shadow DOM.
2. Verify the runtime and distribution model — LWR vs Aura vs internal LEX, and whether this ships through a managed package (if managed, stop and keep shadow DOM).
3. Enable light DOM — add `static renderMode = 'light'` in the JS and `lwc:render-mode="light"` on the root `<template>`.
4. Rename component CSS to `<name>.scoped.css` so styles do not bleed, and add a separate unscoped file only for deliberately global theme hooks.
5. Review sanitization, LWS behavior, and third-party script access — DOMPurify any user-controlled HTML; confirm LWS does not block the library's JS APIs.
6. Run the checker and validate with a smoke test on an Experience Cloud preview (view source, confirm content is in the page HTML) before release.

---

## Review Checklist

Run through these before marking work in this area complete:

- [ ] A concrete blocker (SEO, library DOM access, global theming, a11y tool) is documented for each light-DOM component.
- [ ] Both `static renderMode = 'light'` and `lwc:render-mode="light"` are set; no mixed-mode templates.
- [ ] Component styles live in `<name>.scoped.css`; any intentional global styles are in a clearly named unscoped file.
- [ ] No `:host` / `:host-context` selectors remain in the component CSS (they do not exist in light DOM).
- [ ] Component is NOT being distributed inside a managed package.
- [ ] Any user-supplied HTML is run through DOMPurify or an equivalent sanitizer before injection.
- [ ] Experience Cloud preview shows the content in the raw HTML source (for SEO components).
- [ ] LWS-sandboxed JS still functions with the third-party library end-to-end.

---

## Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

1. **Plain `<name>.css` in a light-DOM component is global** — one stray selector can leak across the whole page. Use `<name>.scoped.css`.
2. **You cannot mix render modes inside one template** — the root `<template>` sets it for the entire component tree it owns.
3. **`:host` selectors do nothing in light DOM** — there is no shadow host. Refactor to a wrapper element with a class.
4. **LWS is still on** — light DOM does not re-expose blocked JS globals or disable the sandbox.
5. **Managed-package components must stay shadow DOM** — Salesforce's docs explicitly warn against shipping light DOM through managed packages because of style leaks.
6. **Experience Cloud Aura sites behave differently from LWR sites** — confirm the site template before assuming light DOM fixes the SEO problem.
7. **Toggling an existing component from shadow to light is a breaking change** — existing consumers may rely on style isolation, and removing it can regress their layouts.

---

## Output Artifacts

| Artifact | Description |
|---|---|
| Render-mode decision memo | Which components stay shadow DOM and which move to light, with the blocker cited |
| Scoped-styles layout | Mapping of `<name>.scoped.css` vs unscoped global files per component |
| Checker report | File-level findings for missing `*.scoped.css`, forbidden `:host` selectors, and managed-package conflicts |
| LWS / sanitization review | Confirmation that LWS still passes and user-supplied HTML is sanitized |

---

## Related Skills

- `lwc/lwr-site-development` — use when the light-DOM decision is driven by an LWR Experience Cloud site and you need the full site-build context.
- `lwc/experience-cloud-lwc-components` — use for Experience Cloud-specific component targets, capabilities, and `js-meta.xml` shape.
- `lwc/lwc-security` — use for LWS, CSP, and DOM sanitization decisions that accompany any light-DOM adoption.
- `lwc/lwc-styling-hooks` — use first when the problem looks like a CSS issue; styling hooks often solve it without losing encapsulation.

Related Skills

tableau-embedding-in-lightning

8
from PranavNagrecha/AwesomeSalesforceSkills

Embedding Tableau dashboards (and Tableau Pulse insights) inside Lightning App / Record / Home pages — Tableau Embedding API v3 in an LWC, the connected-app + JWT trust pattern for SSO from Salesforce to Tableau, row-level security so a Salesforce user only sees their data in Tableau, CSP / Trusted Sites configuration for the Tableau host, and the Tableau Viz Lightning Web Component (drag-and-drop alternative to a custom LWC). NOT for building Tableau dashboards / data sources (that's Tableau-side work), NOT for CRM Analytics (Tableau is the separate product; see data/crm-analytics-patterns).

lwc-shadow-vs-light-dom-decision

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when deciding whether a Lightning Web Component should keep the default Shadow DOM or opt into Light DOM via `static renderMode = 'light'`. Covers CSS scoping, third-party CSS-framework compatibility, accessibility implications, Experience Cloud LWR vs internal-app constraints, performance differences, and event composition. NOT a generic Light DOM how-to (see lwc/lwc-light-dom). NOT a CSS styling reference (see lwc/lwc-styling-and-slds). NOT for managed-package distribution rules — that is a hard constraint and Light DOM is forbidden there.

lwc-lightning-record-forms

8
from PranavNagrecha/AwesomeSalesforceSkills

Lightning Data Service form components for LWC — when to use lightning-record-form vs lightning-record-edit-form vs lightning-record-view-form, output-field vs input-field, density modes, layout types (Compact/Full), and the platform-managed validation/save/error UI. NOT for fully custom form layouts (use lwc/lwc-custom-form-with-uiRecordApi) or aura:recordEditForm (Aura is deprecated for new work).

lwc-lightning-modal

8
from PranavNagrecha/AwesomeSalesforceSkills

LightningModal base class (Winter '23+): extending LightningModal, open() static method, modal headers/bodies/footers, close() with result, size variants, accessibility. NOT for lightning-dialog legacy patterns (deprecated). NOT for in-page overlays (use SLDS popover).

lightning-navigation-dead-link-handling

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when an LWC navigates via NavigationMixin to records or pages that may no longer exist, lack the user's access, or be permanently moved. Triggers: 'lightning navigation 404', 'navigate to deleted record', 'NavigationMixin error toast', 'graceful fallback when target page missing', 'permission denied on navigation'. NOT for general routing within an SPA or for Experience Cloud public-facing routing.

lightning-page-performance-tuning

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when a Lightning record page, home page, or app page is slow to load or render — covers Experienced Page Time (EPT) analysis, component count reduction, progressive disclosure via tabs and conditional rendering, Lightning Experience Insights diagnostics, and DOM/XHR minimization strategies. Triggers: 'Lightning page is slow', 'EPT is high', 'record page takes too long to load', 'too many components on page', 'Lightning Experience Insights shows slow page', 'how to optimize Lightning page performance'. NOT for Visualforce page performance (separate concern). NOT for Apex or SOQL query optimization (use apex/apex-cpu-and-heap-optimization or data/soql-query-optimization). NOT for report or dashboard performance (use admin/report-performance-tuning).

lightning-experience-transition

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when planning, sequencing, or troubleshooting an org-wide migration from Salesforce Classic to Lightning Experience. Covers the LEX Transition Assistant Readiness Check, asset triage matrix (Visualforce, JavaScript buttons, page layouts, Knowledge, email templates, list views, AppExchange), pilot/wave rollout sequencing, end-user adoption telemetry, and cutover criteria. Triggers: 'lightning experience transition', 'classic to lightning migration plan', 'LEX readiness check', 'why are some users still on Classic', 'turning on Lightning for everyone'. NOT for individual asset migrations like a single VF page (use lwc/visualforce-to-lwc-migration), a single JavaScript button (use admin/custom-button-to-action-migration), or Knowledge article migration (use admin/knowledge-classic-to-lightning) — this skill orchestrates the program. NOT for Lightning App Builder page design (use admin/lightning-app-builder-advanced).

lightning-bolt-template-authoring

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when an admin or partner needs to package an Experience Cloud (Community) site as a reusable Lightning Bolt Solution for distribution — covers the export workflow from Experience Builder, what gets bundled (ExperienceBundle, custom apps, flow categories, theme, layouts, navigation menus) versus what does NOT (data, CMS content, files), choosing Bolt vs managed package vs unlocked package vs cloning a site, sandbox-to-production promotion, multi-org distribution, AppExchange listing as a Bolt, and template versioning via the LightningBolt metadata `versionNumber`. Triggers: 'turn this community into a reusable template', 'package an Experience Cloud site to ship to multiple orgs', 'export Experience Builder template for AppExchange', 'should we use a Bolt or a managed package for this community', 'create an industry-specific community starter', 'how do we version our partner portal template', 'distribute branded Experience site across business units'. NOT for general Experience Cloud site build, content, or member setup (use admin/experience-cloud-site-setup, admin/experience-cloud-cms-content, admin/experience-cloud-member-management). NOT for shipping Apex / LWC / data-model functionality as a product (use devops/managed-package-development, devops/second-generation-managed-packages, devops/unlocked-package-development). NOT for moving a single Experience site between sandbox and prod as a one-off (use admin/experience-cloud-deployment-admin, devops/cicd-for-experience-cloud).

lightning-app-builder-advanced

8
from PranavNagrecha/AwesomeSalesforceSkills

Advanced Lightning App Builder usage: component visibility filters, custom page templates, Dynamic Forms, Dynamic Actions, page performance optimization, LWC targetConfig for record pages. Use when building complex record pages or custom app templates. NOT for basic page layout configuration. NOT for LWC component development (use lwc/* skills). NOT for Dynamic Forms basics (use dynamic-forms-and-actions).

knowledge-classic-to-lightning

8
from PranavNagrecha/AwesomeSalesforceSkills

Migrating Classic Knowledge (KnowledgeArticleVersion / Article Types) to Lightning Knowledge (Knowledge__kav with record types): article-type-to-record-type mapping, multi-language translation preservation, data category re-architecture, file attachment porting, version and publication-state retention, channel visibility translation, and downstream Case Feed / Community / Bot rewiring. NOT for new Lightning Knowledge setup (use admin/knowledge-base-administration) or for editorial workflow design (use admin/knowledge-publishing-workflow).

xss-and-injection-prevention

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when writing or reviewing Visualforce pages, Apex controllers, or LWC components that output user-supplied data, build dynamic queries, or construct HTTP responses. Triggers: 'XSS in Visualforce', 'SOQL injection vulnerability', 'how to encode output in Apex', 'JSENCODE Visualforce', 'open redirect prevention'. NOT for Apex CRUD/FLS enforcement (use soql-security or apex-crud-and-fls), NOT for Shield encryption (use shield-encryption-key-management), NOT for AppExchange security review process (use secure-coding-review-checklist).

visualforce-security-and-modernization

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when hardening or modernizing legacy Visualforce pages — covers the platform CSRF token model and when disabling it is a security regression, view state encryption guarantees and the 170 KB ceiling, FLS/CRUD enforcement gaps on `<apex:outputField>` and on getters that return sObjects, `<apex:includeScript>` interaction with the org Content Security Policy, hosting LWC inside a VF page via `lightning:container` / `lightning-out`, and the retire-vs-harden-vs-leave-alone decision for an inventory of legacy pages. Triggers: 'should I rewrite this Visualforce page in LWC', 'CSRF protection disabled on Visualforce page is that safe', 'community user sees a field they should not on a Visualforce page', 'view state encryption is that enough for sensitive data', 'how do I host an LWC inside a Visualforce page', 'apex:dynamicComponent and apex:actionFunction safe to keep'. NOT for greenfield Visualforce architecture (use apex/visualforce-fundamentals — controller types, view state pattern selection, PDF rendering); NOT for Visualforce email template authoring (use apex/visualforce-email-templates if/when that skill is authored); NOT for general Apex security review across triggers and async (use apex/soql-security and security/secure-coding-review-checklist).