Salesforce · · 13 min read

The LWC Navigation Service

A complete guide to the LWC Navigation Service — how to set it up, and an overview of every pageReference type for navigating to records, objects, apps, tabs, web pages, and more.

Part 88: The LWC Navigation Service

Welcome back to the Salesforce series. Over the past several parts we have been building up a strong foundation in Lightning Web Components. We covered data binding and templates (Part 74), events (Part 75), lifecycle hooks and decorators (Part 76), the @wire decorator and Apex integration (Parts 78-79), the Lightning Data Service (Part 83), and exception handling (Part 87). All of those posts focused on getting data into your components and rendering it on the page. But there is another core requirement that almost every real-world LWC needs to handle — navigating the user somewhere.

Maybe you need to send the user to a record detail page after they create a new account. Maybe you need to open an external URL in a new tab. Maybe you need to redirect them to a custom tab, a specific app, or a named page like the home page. In Aura components, navigation was handled through events like navigateToSObject and navigateToURL. In LWC, Salesforce provides a dedicated service for this called the Navigation Service, and it is built around a single, consistent concept: the page reference.

In this section we will cover what the navigation service is, how to set up your component to use it, and then walk through every major page reference type with working code examples. By the end you will be able to navigate to just about anything in Salesforce from a Lightning Web Component.

Let us get into it.


What Is the Navigation Service?

The LWC Navigation Service is a module provided by Salesforce that allows your Lightning Web Components to navigate users to different pages, records, objects, apps, tabs, and external URLs. It is exposed through a mixin called NavigationMixin, which you import from the lightning/navigation module and apply to your component class.

A mixin, if the term is new to you, is a pattern in JavaScript where you extend a class with additional functionality without using traditional inheritance. When you apply NavigationMixin to your LightningElement, your component gains two new methods:

  1. this[NavigationMixin.Navigate] — navigates the user to a new page.
  2. this[NavigationMixin.GenerateUrl] — generates a URL string without actually navigating. This is useful when you want to build an anchor tag or display a link the user can click on their own.

Both methods accept a page reference object as their argument. The page reference is a plain JavaScript object that describes where you want to go. It has a type property that tells Salesforce what kind of page you are targeting, and then additional properties like attributes and state that provide the specifics.

The navigation service handles all the heavy lifting behind the scenes. It resolves the correct URL based on your org configuration, respects Lightning Experience navigation rules, and works seamlessly with both standard and console navigation. You do not need to hardcode URLs or worry about URL formats changing between Salesforce releases.


How to Prep Your LWC to Use the Navigation Service

Setting up your component for navigation takes three steps. First, import the mixin and the NavigationMixin symbol. Second, apply the mixin to your class. Third, call the navigate or generate URL method wherever you need it.

Here is the basic scaffold:

import { LightningElement } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';

export default class MyNavigationComponent extends NavigationMixin(LightningElement) {
    handleNavigate() {
        this[NavigationMixin.Navigate]({
            type: 'standard__recordPage',
            attributes: {
                recordId: '001XXXXXXXXXXXXXXX',
                objectApiName: 'Account',
                actionName: 'view'
            }
        });
    }
}

Notice that the class extends NavigationMixin(LightningElement) rather than just LightningElement. This is how the mixin pattern works — you wrap the base class in the mixin function, and the result is a new class that has all of the original LightningElement behavior plus the navigation methods.

The this[NavigationMixin.Navigate] call looks a bit unusual because of the bracket notation. The NavigationMixin.Navigate symbol is used as a property key. This is a deliberate design choice by Salesforce to avoid naming collisions with your own methods. You will get used to it quickly.

There is also a second optional parameter on the Navigate method. If you pass true as the second argument, it replaces the current page in the browser history instead of pushing a new entry. This is useful when you want to redirect the user without letting them hit the back button to return to the current page:

this[NavigationMixin.Navigate](pageReference, true); // replaces current history entry

For generating URLs without navigating, use GenerateUrl. It returns a promise that resolves to a URL string:

connectedCallback() {
    this[NavigationMixin.GenerateUrl]({
        type: 'standard__recordPage',
        attributes: {
            recordId: this.accountId,
            objectApiName: 'Account',
            actionName: 'view'
        }
    }).then(url => {
        this.recordUrl = url;
    });
}

You can then bind this.recordUrl to an anchor tag in your template so the user gets a proper link they can right-click, copy, or open in a new tab.

One more thing before we move on. Your component’s XML configuration file does not need any special configuration for navigation. The NavigationMixin import is all you need. However, the component does need to be deployed in an environment that supports Lightning navigation, meaning Lightning Experience, the Salesforce mobile app, or an Experience Cloud site. Navigation calls in a standalone LWC outside of these contexts will not work.


An Overview of the Page Reference Types

The page reference object is the heart of the navigation service. Every navigation call requires one, and the type property determines what kind of destination you are targeting. Let us go through each of the major types with examples.

standard__recordPage

This is the most commonly used page reference type. It navigates the user to a record detail page, an edit page, or a record creation page.

To view a record:

this[NavigationMixin.Navigate]({
    type: 'standard__recordPage',
    attributes: {
        recordId: this.contactId,
        objectApiName: 'Contact',
        actionName: 'view'
    }
});

To edit a record:

this[NavigationMixin.Navigate]({
    type: 'standard__recordPage',
    attributes: {
        recordId: this.contactId,
        objectApiName: 'Contact',
        actionName: 'edit'
    }
});

The actionName attribute accepts three values: view, edit, and clone. The clone action opens the record creation page with all the field values pre-populated from the existing record. Note that objectApiName is required for view in some contexts and always required for edit and clone.

standard__objectPage

This type navigates to an object’s home page, which is typically the list view for that object. It also supports navigating directly to a specific list view or opening the new record creation page for an object.

To navigate to the object home (list view):

this[NavigationMixin.Navigate]({
    type: 'standard__objectPage',
    attributes: {
        objectApiName: 'Opportunity',
        actionName: 'home'
    }
});

To navigate to a specific list view:

this[NavigationMixin.Navigate]({
    type: 'standard__objectPage',
    attributes: {
        objectApiName: 'Opportunity',
        actionName: 'list'
    },
    state: {
        filterName: '00BXXXXXXXXXXXXXXX' // list view ID
    }
});

To open the new record creation page:

this[NavigationMixin.Navigate]({
    type: 'standard__objectPage',
    attributes: {
        objectApiName: 'Opportunity',
        actionName: 'new'
    }
});

You can also pass default field values when opening the new record form by using the state property with defaultFieldValues. The values need to be encoded using the encodeDefaultFieldValues function from lightning/pageReferenceUtils:

import { encodeDefaultFieldValues } from 'lightning/pageReferenceUtils';

handleCreateWithDefaults() {
    const defaultValues = encodeDefaultFieldValues({
        Name: 'New Opportunity',
        StageName: 'Prospecting',
        CloseDate: '2025-12-31'
    });

    this[NavigationMixin.Navigate]({
        type: 'standard__objectPage',
        attributes: {
            objectApiName: 'Opportunity',
            actionName: 'new'
        },
        state: {
            defaultFieldValues: defaultValues
        }
    });
}

This is extremely useful for workflows where you want to pre-fill some fields to reduce data entry for the user.

standard__namedPage

Named pages are standard Salesforce pages that have a fixed name. These include the home page, the Chatter feed, and other built-in pages.

To navigate to the home page:

this[NavigationMixin.Navigate]({
    type: 'standard__namedPage',
    attributes: {
        pageName: 'home'
    }
});

To navigate to the Chatter page:

this[NavigationMixin.Navigate]({
    type: 'standard__namedPage',
    attributes: {
        pageName: 'chatter'
    }
});

The pageName attribute accepts a limited set of values. The most common ones are home, chatter, today, and dataAssessment. You cannot use this type to navigate to arbitrary custom pages — it is strictly for the built-in named pages that Salesforce recognizes.

standard__webPage

This type navigates to an external URL. It opens the URL in a new browser tab by default.

this[NavigationMixin.Navigate]({
    type: 'standard__webPage',
    attributes: {
        url: 'https://developer.salesforce.com'
    }
});

This is the go-to page reference for any URL outside of Salesforce. Keep in mind that the navigation service will open external URLs in a new tab in Lightning Experience. You cannot force the URL to open in the same tab when using this type.

A common pattern is to build the URL dynamically based on data in your component:

handleOpenMap() {
    const address = encodeURIComponent(this.account.BillingStreet + ', ' + this.account.BillingCity);
    this[NavigationMixin.Navigate]({
        type: 'standard__webPage',
        attributes: {
            url: `https://maps.google.com/?q=${address}`
        }
    });
}

standard__app

This type navigates the user to a specific Lightning app. You need the app’s API name or its developer name.

this[NavigationMixin.Navigate]({
    type: 'standard__app',
    attributes: {
        appTarget: 'standard__Sales'
    }
});

For a custom app, you would use the namespace and developer name:

this[NavigationMixin.Navigate]({
    type: 'standard__app',
    attributes: {
        appTarget: 'c__MyCustomApp'
    }
});

When the navigation executes, Salesforce switches the user to that app in the App Launcher. The page they land on depends on the app’s default landing page configuration.

standard__navItemPage

This type navigates to a specific tab in the navigation bar. This is particularly useful for custom tabs that are tied to Lightning components, Visualforce pages, or web tabs.

this[NavigationMixin.Navigate]({
    type: 'standard__navItemPage',
    attributes: {
        apiName: 'My_Custom_Tab'
    }
});

The apiName corresponds to the tab’s API name as defined in Setup. If your tab is tied to a custom Lightning component page, navigating to it will render that component. This is a clean way to link between different functional areas of your application without hardcoding URLs.

standard__component (Aura Only)

It is worth mentioning this type even though it only works for Aura components. The standard__component page reference type lets you navigate to an Aura component by its fully qualified name. It does not work with LWC targets, but if you are in a mixed environment with both Aura and LWC, you may encounter it:

this[NavigationMixin.Navigate]({
    type: 'standard__component',
    attributes: {
        componentName: 'c__MyAuraComponent'
    },
    state: {
        c__paramName: 'paramValue'
    }
});

State parameters prefixed with c__ are passed to the Aura component as URL parameters that can be read using $CurrentPageReference.

standard__knowledgeArticlePage

If your org uses Salesforce Knowledge, you can navigate directly to a knowledge article using its URL name:

this[NavigationMixin.Navigate]({
    type: 'standard__knowledgeArticlePage',
    attributes: {
        articleType: 'FAQ__kav',
        urlName: 'how-to-reset-password'
    }
});

comm__namedPage (Experience Cloud)

For Experience Cloud sites (formerly Community Cloud), there is a separate page reference type for navigating to named community pages:

this[NavigationMixin.Navigate]({
    type: 'comm__namedPage',
    attributes: {
        name: 'My_Custom_Page__c'
    }
});

This only works within the context of an Experience Cloud site. If your component runs in Lightning Experience, this type will not resolve.


Putting It All Together

In practice, you will usually combine the navigation service with some kind of user interaction — a button click, a row action in a data table, or a redirect after a successful record save. Here is a more complete example that demonstrates several patterns in a single component:

import { LightningElement, api } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import { encodeDefaultFieldValues } from 'lightning/pageReferenceUtils';

export default class NavigationDemo extends NavigationMixin(LightningElement) {
    @api recordId;
    accountUrl;

    connectedCallback() {
        this[NavigationMixin.GenerateUrl]({
            type: 'standard__recordPage',
            attributes: {
                recordId: this.recordId,
                objectApiName: 'Account',
                actionName: 'view'
            }
        }).then(url => {
            this.accountUrl = url;
        });
    }

    handleViewRecord() {
        this[NavigationMixin.Navigate]({
            type: 'standard__recordPage',
            attributes: {
                recordId: this.recordId,
                objectApiName: 'Account',
                actionName: 'view'
            }
        });
    }

    handleCreateOpportunity() {
        const defaults = encodeDefaultFieldValues({
            AccountId: this.recordId,
            StageName: 'Prospecting'
        });

        this[NavigationMixin.Navigate]({
            type: 'standard__objectPage',
            attributes: {
                objectApiName: 'Opportunity',
                actionName: 'new'
            },
            state: {
                defaultFieldValues: defaults
            }
        });
    }

    handleOpenDocs() {
        this[NavigationMixin.Navigate]({
            type: 'standard__webPage',
            attributes: {
                url: 'https://developer.salesforce.com/docs'
            }
        });
    }

    handleGoHome() {
        this[NavigationMixin.Navigate]({
            type: 'standard__namedPage',
            attributes: {
                pageName: 'home'
            }
        });
    }
}

The corresponding template might look like this:

<template>
    <lightning-card title="Navigation Demo">
        <div class="slds-p-around_medium">
            <p class="slds-m-bottom_small">
                <a href={accountUrl}>View Account (link)</a>
            </p>
            <lightning-button label="View Account" onclick={handleViewRecord}
                class="slds-m-right_small"></lightning-button>
            <lightning-button label="New Opportunity" onclick={handleCreateOpportunity}
                class="slds-m-right_small"></lightning-button>
            <lightning-button label="Open Docs" onclick={handleOpenDocs}
                class="slds-m-right_small"></lightning-button>
            <lightning-button label="Go Home" onclick={handleGoHome}></lightning-button>
        </div>
    </lightning-card>
</template>

Notice how we used GenerateUrl in connectedCallback to build a real URL for the anchor tag, while the button handlers use Navigate directly. This gives you the best of both worlds — proper link behavior for accessibility and right-click support, plus programmatic navigation for button-driven flows.


Common Pitfalls

A few things to watch out for when working with the navigation service:

Navigation does not work in test contexts. If you are writing Jest tests for a component that uses the navigation mixin, you need to mock the NavigationMixin. The @salesforce/sfdx-lwc-jest package provides utilities for this. You will not get real navigation in a test environment, but you can verify that the correct page reference was passed to the Navigate method.

External URLs always open in a new tab. There is no way to force an external URL to open in the same tab using the navigation service. If you need that behavior, you would have to fall back to window.open or assign to window.location, but be aware that this can break the Lightning Experience shell.

The page reference must be well-formed. If you pass a malformed page reference — missing the type, misspelling an attribute, or using an invalid actionName — the navigation call will silently fail or throw a runtime error. Double-check your page reference structure against the Salesforce documentation when something does not work.

GenerateUrl returns a promise. Do not try to use the URL synchronously. Always handle the result in a .then() callback or use async/await.


Section Notes

The LWC Navigation Service gives you a single, consistent API for moving users around your Salesforce org. The NavigationMixin provides two methods — Navigate for immediate navigation and GenerateUrl for building URLs — and both work with the same page reference object structure. The page reference types cover records, objects, named pages, external URLs, apps, nav items, knowledge articles, and Experience Cloud pages.

The key ideas from this section:

  • Import NavigationMixin from lightning/navigation and apply it to your class with NavigationMixin(LightningElement).
  • Every navigation call takes a page reference object with a type, attributes, and optional state.
  • Use standard__recordPage for record view, edit, and clone operations.
  • Use standard__objectPage for list views and new record creation, including pre-filled default values.
  • Use standard__namedPage for built-in Salesforce pages like home and chatter.
  • Use standard__webPage for external URLs.
  • Use standard__app and standard__navItemPage for switching apps and tabs.
  • Use GenerateUrl when you need a URL string for anchor tags rather than immediate navigation.

In the next section we will continue building on our LWC knowledge with more advanced component patterns. See you there.