Route types
ThePageRoutes component supports three types of routes to handle different navigation scenarios.
Index routes
The index route is your app’s home page, rendered when users navigate to the root URL of your app. Every app pages implementation should include an index route.https://app.hubspot.com/app/{HubID}/{appId}
The index route is always accessed with an empty path or /. You don’t need to specify a path prop for index routes.
Named routes
Named routes define specific pages within your app. Each route has a unique path that users can navigate to.Route paths are normalized automatically, so both
"docs" and "/docs" will work. See path normalization for details.https://app.hubspot.com/app/{HubID}/{appId}/docshttps://app.hubspot.com/app/{HubID}/{appId}/supporthttps://app.hubspot.com/app/{HubID}/{appId}/analytics
AnyRoute component
TheAnyRoute component defines a fallback route that renders when no other routes match. This is useful for displaying custom 404 pages or redirecting users.
AnyRoute will render for any path that doesn’t match defined routes, such as /invalid-path or /does-not-exist.
It’s recommended to always include an
AnyRoute to provide a better user experience when users navigate to undefined paths.Wildcard routes (splat routes)
Wildcard routes, also known as “splat” routes, allow you to match any characters following a specific path prefix. If a route path ends with/*, it will match any characters following the /, including other / characters.
Accessing the wildcard value
The matched portion of the URL is available asparams["*"]:
* parameter by assigning it a more descriptive name:
Wildcard routes vs AnyRoute
While both match multiple paths, they serve different purposes: AnyRoute component:- Catches any unmatched path at that nesting level
- Typically used for 404 pages or fallback routes
- Does not provide the matched path as a parameter
path="prefix/*"):
- Match a specific path pattern (e.g.,
/docs/*only matches paths starting with/docs/) - The matched portion is accessible as a parameter
- Useful for file browsers, documentation sites, or any hierarchical content
Nested routes
You can nestPageRoutes components within the route tree to create hierarchical page structures. Nest routes by adding a <PageRoutes> with a path prop as a child of the parent <PageRoutes>:
/- Home page/support- Support index page/support/contact-us- Contact us page/support/faq- FAQ page
Nested route behavior
When using nested routes:- A
<PageRoutes>with apathprop defines a group of nested routes under that path - The nested
IndexRouterenders when the path matches exactly the parent path (/support) - Named routes within the nested
PageRoutesextend the parent path (/support/contact-us) - Each nested level can have its own
AnyRoutefor unmatched paths within that section
Nesting with path parameters
You can combine nested routes with path parameters to create hierarchical structures:/deals/123- Deal overview/deals/123/notes- Deal notes list/deals/123/notes/456- Specific note details
Layout components
Layout components let you wrap groups of routes with shared UI, such as navigation bars, sidebars, or other persistent elements. A layout component receiveschildren as a prop and renders the matched route’s content within it.
Basic layout
Pass a layout component to<PageRoutes> using the layoutComponent prop:
AppLayout component will wrap every page rendered by these routes. The matched page component is rendered in place of {children}.
Nested layouts
You can apply different layout components at different nesting levels. Nested<PageRoutes> can define their own layoutComponent, which will render inside the parent layout:
/customers, the rendered output will be AppLayout > CustomersLayout > ListCustomersPage. Each layout wraps the content below it in the route tree.
Path parameters
Path parameters allow you to create dynamic routes that can capture values from the URL path. This is useful for pages that display specific items, such as viewing a particular contact, deal, or custom object record.Defining routes with path parameters
To define a route with path parameters, use a colon (:) followed by the parameter name in the route path:
documents/:folderId/:documentId example.
Understanding path parameters
Path parameters are placeholders in your route definitions that capture values from the URL. When a user navigates to a URL that matches the route pattern, the parameter values are extracted and made available to your component. Example route pattern:/view-contact/:contactId
This pattern will match URLs like:
/view-contact/123(contactId = “123”)/view-contact/abc-def(contactId = “abc-def”)/view-contact/contact-456(contactId = “contact-456”)
/view-contact(missing contactId)/view-contact/123/edit(additional path segment)
Multiple path parameters
When using multiple path parameters, each segment of the URL path can capture a different value:/deals/456/notes/789matches withdealId="456"andnoteId="789"- The path segments between parameters (
dealsandnotes) must match exactly - Both parameters are required for the route to match
Best practices for path parameters
- Use descriptive parameter names: Choose names that clearly indicate what the parameter represents (e.g.,
:contactId,:dealId, not:id) - Keep parameter counts reasonable: While you can have multiple path parameters, too many can make URLs hard to read
- Validate parameter values: Always validate path parameter values before using them (e.g., check if an ID exists)
- Use path parameters for resource IDs: Path parameters work well for resource identifiers that define what page you’re viewing
- Use query parameters for optional state: Use query parameters for filtering, sorting, or view state that doesn’t change what resource you’re viewing
- Use wildcards for hierarchical paths: When you need to match multiple nested segments and preserve the full path (e.g., file systems, documentation), use wildcard routes instead of multiple path parameters
Accessing route information
Use theusePageRoute hook to access the current page path, route ID, and all parameters (both path parameters and query parameters) in your page components. The hook returns an object with path, routeId, and params.
Basic usage
https://app.hubspot.com/app/{HubID}/{appId}/docs?section=api&topic=authentication, the hook will return:
path:"/docs"params.section:"api"params.topic:"authentication"
Accessing path parameters
Path parameters are included inparams alongside query parameters - the usePageRoute hook returns all parameters regardless of their source:
/view-contact/123?tab=activity:
contactId:"123"(from path)tab:"activity"(from query string)
Accessing wildcard parameters
Wildcard values are accessed through theparams["*"] property:
* parameter by assigning it a more descriptive name:
/files/documents/2024/report.pdf with a route defined as path="/files/*":
params["*"]:"documents/2024/report.pdf"
Like all page parameters, wildcard values are strings. Remember to validate and sanitize the wildcard value before using it, especially if using it to access files or resources.
Route IDs
Each route can be assigned a stableid prop that uniquely identifies it. When a route matches, its id is available as routeId from the usePageRoute hook. This is particularly useful in layout components where you need to determine which route is currently active without relying on path matching.
Defining route IDs
Add anid prop to any route component:
Accessing the route ID
Use therouteId property from the usePageRoute hook:
Using route IDs in layout components
Route IDs are especially useful in layout components where you need to render different breadcrumbs, titles, or other shared UI based on the active route. Unlike path-based matching, route IDs remain stable even if route paths change, and they work reliably with dynamic path parameters.Parameter limitations
Understanding parameter limitations helps you avoid common issues when working with app pages.All values are strings
Parameters are always received as strings, regardless of the type you pass.No complex objects
You cannot pass objects, arrays, or other complex data structures as parameters. Only simple string values are supported.URL length limits
Query parameters are part of the URL, which has practical length limits:- Browsers: Most browsers support URLs up to 2,000-8,000 characters
- Best practice: Keep URLs under 2,000 characters for maximum compatibility
- Recommendation: Use parameters for IDs and simple state, not for large data payloads
- Store the data on your backend
- Pass only an ID through a URL parameter
- Fetch the full data using the ID when the page loads
Path normalization
When navigating to pages or defining routes, the routing system automatically normalizes paths to ensure consistent behavior. Understanding these normalization rules can help you avoid unexpected routing issues.Normalization rules
The following transformations are applied to paths:-
Leading slashes are added: If a path doesn’t start with
/, one is automatically added."foo"→"/foo""docs"→"/docs"
-
Trailing slashes are removed: Paths should not end with a slash, and any trailing slashes are automatically removed.
"foo/"→"/foo""docs/"→"/docs""support/contact/"→"/support/contact"
-
Multiple consecutive slashes are collapsed: Any sequence of multiple slashes is reduced to a single slash.
"foo//bar"→"/foo/bar""docs///api"→"/docs/api""//support"→"/support"
-
Empty paths are treated as root: An empty string or single slash both represent the home page.
""→"/""/"→"/"
Examples
Here are some examples of how different path formats are normalized:Practical implications
Because of path normalization:- You can use either format in route definitions: Both
path="docs"andpath="/docs"will work the same way after normalization.
- Navigation calls are forgiving: When navigating to pages, you don’t need to worry about exact path formatting. See the Page linking and navigation guide for more details.
-
Consistency in comparisons: When comparing paths using
usePageRoute(), always compare against normalized paths.
Getting the current page path
Use theusePageRoute hook to get the current page path. This is useful for determining which page is currently active, which can help with navigation highlighting and conditional rendering.
path value returned by usePageRoute is always the normalized path, so you can reliably compare it against expected values.