Account map in one tag
The account tree under the highlights panel: subsidiaries, their contacts, their open deals, one click to drill.
Overview
The account tree under the highlights panel: subsidiaries, their contacts, their open deals, one click to drill. One tag in your LWC, one nested query. The whole map is one Relationship Graph (avonni-dd-relationship-graph) on the Account record page, reading three levels of records through a query that carries its own children. This tutorial rebuilds the Northwind Distribution page of the Sales app in your own org.
What you build

Open Northwind Distribution and the map sits under the highlights panel. The account is the root label of the graph; New contact and New opportunity hang off it.
Accounts (3) in the first column: Northwind Canada (Montréal), Northwind Iberia (Lisbon), Northwind Nordics (Stockholm), all Furniture retail, each with its city and industry under the name.
Select Northwind Nordics and its Contacts (2) (Tomas Berg, CFO; Jonas Lindqvist, IT director) and Opportunities (1) (Nordics showroom refit, $126,500.00, Proposal) unfold to the right, the deal highlighted.
Add on every group, a menu with Open on every card.
Before you start
The Avonni LWC Components package is installed, and the sales users hold a license and the package permission set. See Installation & Licenses Management.
The Account record page of the app where the map goes. The examples below use Northwind Distribution, a furniture retailer, in the Sales app.
Standard objects only. The graph reads these fields:
Account
Name
Text
The card label
ParentId
Lookup (Account)
Makes an account a subsidiary. The root query filters on it.
BillingCity, Industry
Text, Picklist
The two facts under each subsidiary
Contact
Name, AccountId
Text, Lookup (Account)
The label and the link to the subsidiary
Title
Text
The fact under each contact
Opportunity
Name, AccountId
Text, Lookup (Account)
The label and the link to the subsidiary
Amount, StageName
Currency, Picklist
The two facts under each deal
Sample data. One account, Northwind Distribution (Type Partner, Industry Furniture retail), and three accounts whose Parent Account is Northwind Distribution, each with its contacts and one open opportunity:
Northwind Canada
Montréal
Furniture retail
Priya Nair (Store operations)
Spring catalog renewal (84,000, Negotiation, Oct 16, 2026)
Northwind Iberia
Lisbon
Furniture retail
Maya Chen (Procurement lead)
E-commerce integration (42,000, Qualification, Nov 20, 2026)
Northwind Nordics
Stockholm
Furniture retail
Tomas Berg (CFO), Jonas Lindqvist (IT director)
Nordics showroom refit (126,500, Proposal, Nov 6, 2026)
Use the stage names of your org. The org in the figure had Proposal and Negotiation added to the Opportunity Stage picklist; a default org has Proposal/Price Quote and Negotiation/Review instead, and the cards show whichever value the record holds.
Permissions. The Avonni query follows Salesforce sharing and field-level security: a user sees the subsidiaries, contacts and deals they can read, and nothing else. Creating a contact or a deal from the root actions needs Create on those objects.
Build it
Create the records
Create Northwind Distribution, then the three subsidiaries with Parent Account set to it, then the four contacts and the three opportunities on the subsidiaries.
Check the hierarchy from the account: the standard View Account Hierarchy action lists the three children.
Why: the graph is drawn from ParentId, AccountId and nothing else. If the hierarchy is right, the map is right.
Read the record id and write the nested query
On a record page the component receives the account id through @api recordId. Build the query from it once the component is connected:
Why: the first level of the graph is the result of the root query. Querying the subsidiaries (ParentId = <this account>) puts them in the first column. Querying the account itself would add a level, Accounts (1), holding one card that repeats the root label. Each child query names the lookup that points from the child to the parent level: Contact.AccountId, Opportunity.AccountId. filter is a SOQL WHERE clause without the keyword, orderBy a SOQL ORDER BY without the keyword.
Handle the events
Why: the component draws and the code decides. actionclick carries the action name; itemactionclick carries the name and the item's targetName, which is the record id set in the mapping, so Open is a navigation call. groupactionclick carries the group's internal name, not the object name, so a group action works best when it means the same thing on every group.
Expose the component and place it on the record page
In
accountMap.js-meta.xml, expose the component for record pages of Account:
Deploy, open Northwind Distribution, then Edit Page in Lightning App Builder. Drag Account Map into the main region under the highlights panel and Save, then Activate the page for the Sales app.
Why: the figure uses a page with the highlights panel and the map, no Details tab and no sidebar, so the three columns of the graph have the full width.

The settings that matter
query.filter
ParentId = '<this account>'
The root of the graph is the query result. Aiming at the children puts the subsidiaries in the first column, with no extra level repeating the account.
query.children[].relationshipField
AccountId on Contact and on Opportunity
The lookup from the child level to the parent level. That one field is the whole join.
mapping.<Object>.fields
BillingCity, Industry; Title; Amount, StageName
Two facts per card, read from the record and labeled with the field label.
variant
horizontal (default)
Three columns of groups that unfold to the right, which fits under a highlights panel.
Interactions
actionclick
name
newContact, newOpp: open the create form with the account prefilled.
groupactionclick
name, targetName
add: open your create form. targetName is the group's internal identifier, not the object name.
itemactionclick
name, targetName
open: navigate to targetName, the record id from the mapping.
select
record
Fires when a card is selected or unselected, with the record behind it.
Try it
Open Northwind Distribution. Under the highlights panel: the root label with its account icon, New contact and New opportunity, and Accounts (3) collapsed.
Expand Accounts (3) and select Northwind Nordics: Contacts (2) and Opportunities (1) appear to its right. Expand both, then select Nordics showroom refit: the card takes a blue border and Northwind Nordics shows the blue corner that marks the selected path.
Open the menu on Tomas Berg and click Open: the contact record opens.
Click New contact: a new Contact form opens with Account Name set to Northwind Distribution.
Take it further
The same component exists as Relationship Graph for Dynamic Components, on a Lightning page with no code. Flow Screen Components and Experience Sites have no equivalent.
Variations worth trying:
A fourth level: add
childrento the Contact query ({ objectApiName: 'Event', relationshipField: 'WhoId' }) and anEvententry in the mapping.Cards that open on click: add
linkify: trueto a mapping entry and the card navigates to its record without an action.A vertical map:
variant="vertical"stacks the levels top to bottom. It needs more height than the horizontal layout, which matters under a highlights panel.
Troubleshooting
The first column reads Accounts (1) and holds the account itself
The root query targets the account (Id = ...) instead of its children.
Filter the root query on ParentId. The root label already names the account.
A filter on a child query has no effect
The component builds each child query from objectApiName, relationshipField, orderBy, limit and children only; a child filter is documented on the type but not applied (checked in the component source on September 6, 2026).
Filter at the root level, or accept all children. "Open opportunities only" cannot be expressed on the child level today.
Every group shows a single card, whatever the count says
A limit on the root query is applied to the child queries as well (observed on September 5, 2026).
Remove the root limit, or set a limit on each child query instead.
The group reads Accounts (3) where you wanted Subsidiaries (3)
Group labels are the object's plural label. There is no property to rename them (September 5, 2026).
Keep the object labels, or rename the object's plural label in Object Manager if the whole org agrees.
Amount shows two decimals ($126,500.00)
The card renders the field in its currency format; the mapping has no format option (September 5, 2026).
Accept it, or point fields at a formula text field that formats the amount the way you want.
The Add handler cannot tell Contacts from Opportunities
groupactionclick carries the group's internal name, not the object name.
Give the action one meaning for every group, or drop group-actions and keep the root actions.
Was this helpful?
