guideCard, guideLibrary, guideArticle, guideEditor
Series: Build a Salesforce Guide App with AI
Page: 5 of 10
Time to complete: 60–90 minutes
Prerequisites: Page 4 complete (Apex deployed and tested)
How Lightning Web Components Work
Each LWC component is a folder containing three files:
componentName.html— the template (what renders)componentName.js— the controller (the logic)componentName.css— the stylescomponentName.js-meta.xml— metadata telling Salesforce where the component can be used
Components talk to each other via Custom Events (child to parent) and @api properties (parent to child). They talk to Apex via @wire (reactive, cached) or imperative calls (on-demand, not cached).
The four core components have this hierarchy:
guideLibrary (manages view state)
├── guideCard (individual card in the grid)
├── guideArticle (full article reader)
└── guideEditor (admin authoring form)
guideLibrary is the parent. It decides whether to show the library grid, an article, or the editor. The child components communicate back via events.
The Context-Setting Prompt for Components
Start a new Claude conversation (or continue the same one if it hasn’t been too long) with this context:
💬 Context prompt for LWC phase:
I’m continuing to build a Salesforce Guide Hub app. The Apex service class
GuideServiceis already deployed with these methods: getGuides, getGuideDetail, getTopics, saveGuide, saveVideos, submitForApproval, publishAdminGuide, submitVote, getGuidesForModal, getAdminGuides, getGuidesByTopic.Now I need to build four Lightning Web Components. Key requirements:
- Use imperative Apex calls in guideLibrary (not @wire) — @wire caches results and causes stale data bugs with category filtering
- guideLibrary manages all view state: ‘library’, ‘article’, ‘editor’
- guideCard fires a ‘select’ CustomEvent with { guideId } payload
- guideArticle fires ‘back’ and ‘edit’ CustomEvents
- guideEditor fires ‘saved’ and ‘back’ CustomEvents
- All components must handle loading, empty, and error states explicitly
- guideLibrary has an @api isAdmin property — when true, shows the New Guide button
I’m on Windows and will use base64-encoded PowerShell scripts to write the files to avoid copy-paste corruption issues. Please generate complete files — do not truncate.
Please confirm before I ask for the first component.
Building Each Component
Request them in order — guideCard first because guideLibrary depends on it.
guideCard
💬 Prompt:
Build the guideCard LWC component. It:
- Accepts an @api guide property (a Guide__c record or a Knowledge article object with isKnowledge: true)
- Shows a category badge with a colour matching the category (Sales=blue, Support=amber, Onboarding=pink, CPQ=green, Data Management=purple, Productivity=slate, General=gray)
- For Knowledge articles: shows a blue “Knowledge” badge instead, and “Opens in new tab” in the footer
- Shows title, summary (truncated), read time, and helpful count in the footer
- On click: fires ‘select’ CustomEvent with { guideId } for guides; navigates to standard__navItemPage Guide_Article with state { c__guideId } for Knowledge articles
- Uses NavigationMixin for Knowledge navigation
- Has hover animation (slight lift and shadow)
Generate all four files: html, js, css, js-meta.xml (isExposed: false).
guideLibrary
💬 Prompt:
Build the guideLibrary LWC component. It:
- Has @api isAdmin property (Boolean, default false)
- Manages view state: ‘library’, ‘article’, ‘editor’
- In library view: shows a search input, category filter pills (All/Sales/Support/Onboarding/CPQ/Data Management/Productivity/General), and a card grid using c-guide-card
- When isAdmin is true: shows a New Guide button
- Fetches guides AND Knowledge articles in parallel using Promise.all — getGuides + getKnowledgeArticles (imported from GuideService)
- Knowledge articles are given isKnowledge: true and their Title mapped to Name, Summary to Summary__c
- Uses CurrentPageReference @wire to read c__guideId from URL state — if present on load, opens article view for that guide
- handleCategoryClick guard: if clicked category is already active, return immediately (prevents infinite spinner)
- In article view: renders c-guide-article with record-id and is-admin, handles ‘back’ and ‘edit’ events
- In editor view: renders c-guide-editor with record-id, handles ‘back’ and ‘saved’ events
- handleGuideSaved: returns to library, resets search and category, re-fetches
Generate all four files. Use sentence-case labels throughout.
⚠️ Common issue: @wire caching
If Claude uses
@wire(getGuides, ...)instead of imperative calls, ask it to rewrite:“Please rewrite guideLibrary.js to use imperative Apex calls instead of @wire for getGuides. The @wire adapter caches results by parameter — if a category returns empty results once, that empty result is cached and shown even after new guides are published. Use a fetchAll() method called from connectedCallback and whenever search or category changes.”
guideArticle
💬 Prompt:
Build the guideArticle LWC component. It:
- Has @api recordId and @api isAdmin properties
- Uses @wire getGuideDetail to fetch the guide
- Renders: category badge (with colour matching category), title, metadata row (read time, version, last updated date), summary, body using lightning-formatted-rich-text
- Videos: the guide has Video_Position__c (Top/After Introduction/Bottom) and a Guide_Videos__r subquery. Render videos at the correct position. Each video is passed to a c-video-block child component.
- Sidebar: shows category, helpful count, and topic tags (from Topic_Assignments__r subquery)
- Helpful voting: Yes/No buttons. On click, calls submitVote() Apex method optimistically (updates UI immediately, then fires Apex in background)
- When isAdmin is true: shows an Edit Guide button that fires ‘edit’ CustomEvent with { guideId }
- Back button fires ‘back’ CustomEvent
- White background on the article container (not transparent — it should not inherit the page background colour)
Generate all four files.
videoBlock
This is a small child component used by guideArticle.
💬 Prompt:
Build a small videoBlock LWC child component used inside guideArticle. It accepts @api video (a Guide_Video__c record).
- If Video_Type__c is YouTube or Vimeo: render a responsive 16:9 iframe wrapper with the embed URL
- If Video_Type__c is External Link: render a styled link card with a link icon, the video Name, and a new_window icon. Opens in new tab.
- If Video_Type__c is Salesforce File: render a dark thumbnail card with a play button circle in the centre, the video Name below it, and “Click to play · Opens in new tab” hint text. Links to /apex/GuideVideoPlayer?contentDocumentId={Video_URL__c}
- Optional description shown above the video if present
isExposed: false. Generate all four files.
guideEditor
💬 Prompt:
Build the guideEditor LWC component. It:
- Has @api recordId (null for new guide, populated when editing)
- Uses @wire getGuideDetail to pre-populate when editing
- Uses @wire getTopics to populate the topic dual listbox
- Form fields: Title (required), Summary (textarea), Category (combobox), Audience (combobox: User/Admin), Read Time, Tags, Body (lightning-input-rich-text), Topics (lightning-dual-listbox)
- Video section: Add Video button that adds a row with URL input and description input. URL auto-detects type (YouTube/Vimeo/SF File starting with 069/External Link) and shows a colour-coded type badge. Remove button per row.
- Video Position combobox (Top/After Introduction/Bottom)
- Three action buttons at the bottom:
- Cancel (fires ‘back’ event)
- Save as Draft (saves guide + videos, shows success toast, STAYS on editor)
- When Audience = User: Submit for Approval (saves, submits, fires ‘saved’ event returning to library)
- When Audience = Admin: Publish Now (saves, calls publishAdminGuide, fires ‘saved’ event)
- buildRecord() must include Is_Active__c: true — field defaults don’t apply to Apex upserts
Generate all four files.
Deploying the Components
Ask Claude to generate a PowerShell deployment script for all the components at once:
💬 Prompt:
Generate a PowerShell script that writes all five LWC components (guideCard, guideLibrary, guideArticle, videoBlock, guideEditor) to my project at C:\Users[username]\Desktop\guide-hub\force-app\main\default\lwc.
Base64-encode all file content. Use [System.IO.File]::WriteAllBytes(). Create the component directories with New-Item -ItemType Directory -Force before writing files. Print a success message when done.
Download, unblock, run:
Unblock-File -Path .\write-lwc.ps1
.\write-lwc.ps1
sf project deploy start --source-dir force-app/main/default/lwc
Common Deployment Errors
LWC1503: Parsing error: Expecting Unicode escape sequence
A $ in a @wire decorator got escaped. In guideLibrary.js, the wire adapter uses reactive properties like '$searchTerm' and '$activeCategory'. If these get mangled, ask Claude to regenerate the file.
Unable to find Apex action method referenced as 'GuideService.methodName'
The LWC references a method that doesn’t exist in the deployed Apex. Check the method name matches exactly. Remember Apex is case-sensitive on the JavaScript side.
The 'propertyName' property doesn't exist on the component
A meta.xml file declares a property that the JS doesn’t have an @api declaration for. Usually a leftover from a previous version of the component. Check the meta.xml against the JS.
Check Your Work
- ✅ All five components deploy without errors
- ✅ Components appear in Setup → Custom Code → Lightning Components
- ✅ No errors in the VS Code Problems panel
Move to Page 6 — wiring everything together in Lightning App Builder.