I’m working on a project that requires implementing breadcrumb navigation to display the datasheets the user has previously visited. For example: xz-search/x-datasheet/x-datasheet-contracts/contract-item/supplier The current implementation uses a manual approach, where a from value is passed through query parameters (e.g., ...plan/datasheet/123/data?from=order-datasheet&order=432&customOrderId=123123). In each component that includes a breadcrumb, a switch statement manually handles the various possible routes leading to the component. export interface Breadcrumb { label?: string navList: BreadcrumbNav[] } export interface BreadcrumbNav { label: string description?: string url: string[] urlExtras?: NavigationExtras } const from = queryParams['from'] private createBreadcrumb(from?: string, planId?: string, customPlanId?: string) { let claimBaseNavItem: BreadcrumbNav[] switch (from) { case 'search': claimBaseNavItem = [ { label: `Search`, url: ['/', this.entityType, 'plan', 'search'] } ] break.... However, as the project has grown with more modules and navigation links, this approach has become unmanageable. Additionally, users need consistent breadcrumb navigation even when copying or sharing URLs. Constraints: Libraries cannot be used. Breadcrumbs may contain submenus or independent URLs. Breadcrumb IDs differ from the IDs in the URL, and components can only access these IDs through the URL. Challenges: Preventing circular references: For instance, if a datasheet links to related contracts, contracts link to suppliers, and suppliers link back to the same datasheet, the breadcrumb should truncate the loop after the datasheet. Query parameters: I tested a solution using bc query parameters containing a hashed, stringified array of {label: string} objects. Testing new solution: public createBreadcrumbQueryParams(actualLabel: string) { const currentBreadcrumbData = this.route.snapshot.queryParams['bc'] ? JSON.parse(atob(this.route.snapshot.queryParams['bc'])) : null if (currentBreadcrumbData) { //find if current page is already in breadcrumb const index = currentBreadcrumbData.findIndex( (item) => item.label === formatStringToBase64Compatible(actualLabel) ) const urlsToProcess = index !== -1 ? currentBreadcrumbData.slice(0, index) : currentBreadcrumbData urlsToProcess.push({ url: this.router.url.split('?bc=')[0], urlExtras: { queryParams: this.route.snapshot.queryParams['bc'] }, label: formatStringToBase64Compatible(actualLabel) }) const bc = btoa(JSON.stringify(urlsToProcess)) return bc } return null } Example for created url: claim/datasheet/123/data?bc=W3sidXJsIjoiL29yZ2FuaXphdGlvbi9jbGFpbS90YX... that contains an object like this: breadcrumbData[ { "url": "/claim/task-organization/preparation", "label": "Search" }, { "url": "/claim/datasheet/321/plan-part", "urlExtras": { "queryParams": "W3sidXJsIjoiL29yZ2FuaXphd..." }, "label": "Claim - 123" } ] However, this can result in excessively long query parameters if many pages were visited 2-3000 characters long which is not good i suppose... What approach can I use to pass on or store the previous URLs while addressing these constraints? Continue reading...