Skip to content

fix: Thread bar shows correct origin (Network, Profile, My Spaces)#2015

Open
webguru-hypha wants to merge 1 commit intomainfrom
cursor/web-application-issue-1614-711e
Open

fix: Thread bar shows correct origin (Network, Profile, My Spaces)#2015
webguru-hypha wants to merge 1 commit intomainfrom
cursor/web-application-issue-1614-711e

Conversation

@webguru-hypha
Copy link
Contributor

@webguru-hypha webguru-hypha commented Mar 16, 2026

Summary

Fixes #1614 - Navigation issue: thread bar

The breadcrumb/thread bar on space and profile pages was always showing "My Spaces" as the parent. It now correctly shows the origin based on where the user navigated from: Network, Profile, or My Space.

Changes

  • Breadcrumb root: Now reflects the correct origin (Network, Profile, or My Spaces) based on the from query parameter or persisted cookie
  • Space links: Added from param when linking to spaces from:
    • Network page (?from=network)
    • Profile page (?from=profile&profileSlug=xxx)
    • My Spaces page (?from=my-spaces)
  • Persistence: Origin is stored in a cookie when visiting a space with the from param, so it persists when navigating between spaces (e.g. via carousel or breadcrumb)
  • DHO carousel: "Spaces you might like" carousel preserves the from param when linking to other spaces
  • Breadcrumb items: Parent space links in the breadcrumb preserve the from param
  • i18n: Added "Profile" to Navigation translations (en, fr, de)

How it works

  1. When a user clicks a space from Network, Profile, or My Spaces, the link includes ?from=network, ?from=profile&profileSlug=xxx, or ?from=my-spaces
  2. Middleware sets a cookie when it detects the from param on DHO pages
  3. The breadcrumb client component reads the from param from the URL (or cookie as fallback) and displays the appropriate root link
  4. All internal links (carousel, breadcrumb items) preserve the from param so the origin stays consistent during the session
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features
    • Breadcrumbs now preserve navigation origin (Network, Profile, My Spaces) across pages, improving back-navigation and context.
    • Root breadcrumb is auto-selected and remembered, with seamless sync between URL and cookies.
    • Spaces carousels and lists include origin in links, keeping context when exploring or opening a space.
    • Profile and My Spaces links now carry origin parameters for consistent navigation.
    • Some links now use full URLs, improving sharing.
    • Added “Profile” translations in English, German, and French.

Fixes #1614 - Navigation issue: thread bar

- Breadcrumb root now reflects origin: Network, Profile, or My Spaces
- Add from param to space links from Network, Profile, My Spaces pages
- Persist origin via cookie when navigating between spaces
- Preserve from param in DHO carousel and breadcrumb item links
- Add Profile to Navigation i18n (en, fr, de)

Co-authored-by: webguru-hypha <webguru-hypha@users.noreply.github.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 16, 2026

📝 Walkthrough

Walkthrough

This PR implements breadcrumb origin tracking that persists the navigation source (Network, Profile, or My Spaces) via cookies and context. It propagates a "from" query parameter through space cards and breadcrumb links, enabling users to navigate back to their original entry point rather than defaulting to My Spaces.

Changes

Cohort / File(s) Summary
New Breadcrumb Root Components
apps/web/src/app/[lang]/dho/[id]/_components/breadcrumbs-root-selector.tsx, breadcrumb-space-item.tsx
Introduces BreadcrumbsRootSelector context provider and useBreadcrumbFrom/useBreadcrumbFromQuery hooks for managing breadcrumb origin state; adds BreadcrumbSpaceItem wrapper component that retrieves and passes fromQuery to underlying breadcrumb item.
Updated Breadcrumb Navigation
apps/web/src/app/[lang]/dho/[id]/_components/breadcrumbs.tsx, packages/epics/src/spaces/components/breadcrumbs.tsx
Replaces SpaceBreadcrumb wrapper with BreadcrumbsRootSelector and wires fromQuery prop through breadcrumb items; adds optional fromQuery parameter to SpaceBreadcrumbItem for appending origin to breadcrumb links.
Space Carousel & Layout Integration
apps/web/src/app/[lang]/dho/[id]/_components/spaces-carousel-with-from.tsx, layout.tsx, apps/web/src/app/[lang]/my-spaces/page.tsx
Introduces SpacesCarouselWithFrom component that retrieves breadcrumb origin and constructs space card links with from parameter; refactors layout to use new carousel component; wraps my-spaces links with addFromParam.
Space Card & Discovery Components
packages/epics/src/people/components/profile-member-spaces.tsx, explore-spaces.tsx, my-filtered-spaces.tsx, space-card-list.tsx, space-card.container.tsx
Propagates fromParam through SpaceCardList and SpaceCardContainer; adds from parameter handling in profile member spaces, explore view, and my-spaces view for consistent origin tracking across UI.
Path Utilities & Query Builders
packages/epics/src/common/get-path-function.ts
Adds BreadcrumbOrigin type and introduces getFromQueryString/addFromParam helpers to construct and append from query parameters; updates getDhoUrlAgreements to return absolute URLs.
Middleware & Cookie Persistence
apps/web/src/middleware.ts
Implements setBreadcrumbOriginCookie function to extract and persist breadcrumb origin from URL/query parameters; simplifies applyCsp signature by removing unused request parameter; integrates cookie logic into middleware flow.
Internationalization
packages/i18n/src/messages/en.json, de.json, fr.json
Adds "profile" translation key to Navigation section across English, German, and French language files.

Sequence Diagram

sequenceDiagram
    actor User as User/Browser
    participant Middleware
    participant CookieStore as Cookie Storage
    participant BreadcrumbRoot as BreadcrumbsRootSelector
    participant Components as Breadcrumb & Card Components

    User->>Middleware: Navigate to space from origin (Network/Profile/My-Spaces)
    Middleware->>Middleware: Detect origin from URL path/query
    Middleware->>CookieStore: Set breadcrumb_origin cookie (max-age: 1 day)
    Middleware-->>User: Return response with cookie

    User->>BreadcrumbRoot: Mount BreadcrumbsRootSelector context provider
    BreadcrumbRoot->>BreadcrumbRoot: Read from URL query or cookie
    BreadcrumbRoot->>BreadcrumbRoot: Provide origin via context (useBreadcrumbFrom)

    Components->>BreadcrumbRoot: Read origin using useBreadcrumbFromQuery
    Components->>Components: Build link href with from parameter
    Components-->>User: Render breadcrumb/card with from=origin

    User->>User: Click breadcrumb or space card link
    User->>Middleware: Navigate with from query parameter preserved
    Middleware->>CookieStore: Update cookie if origin changed
    Middleware-->>User: Navigate to target with origin context maintained
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #1829: Modifies the same path helper exports in packages/epics/src/common/get-path-function.ts for query parameter construction.
  • #1225: Updates breadcrumb component implementation including SpaceBreadcrumbItem and breadcrumb link construction logic.
  • #1986: Modifies middleware surface and CSP function signatures in apps/web/src/middleware.ts.

Suggested reviewers

  • evgenibir
  • DSanich
  • plitzenberger

Poem

🐰 A breadcrumb trail so fine and clear,
Through Networks wide and Profiles dear,
A cookie marks where you have been,
So back you hop to where you've seen!
No more lost paths through endless space,
The trail remembers your true place. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main fix: the breadcrumb/thread bar now shows the correct origin (Network, Profile, or My Spaces) based on navigation context.
Linked Issues check ✅ Passed The PR fully implements the objective from issue #1614: breadcrumb now reflects correct origin (Network, Profile, My Spaces) via query parameters and cookie persistence across navigation.
Out of Scope Changes check ✅ Passed All changes are scoped to the breadcrumb origin feature: middleware cookie logic, breadcrumb components, carousel navigation, query parameter threading, and i18n translation additions. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/web-application-issue-1614-711e
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use TruffleHog to scan for secrets in your code with verification capabilities.

Add a TruffleHog config file (e.g. trufflehog-config.yml, trufflehog.yml) to your project to customize detectors and scanning behavior. The tool runs only when a config file is present.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/web/src/app/[lang]/dho/[id]/_components/breadcrumbs-root-selector.tsx (1)

98-116: Move cookie writes out of useMemo to eliminate impure side effects.

The useMemo hook at line 111 calls setBreadcrumbOriginCookie(), which creates a side effect inside a pure function. The same operation is duplicated in the useEffect at line 145. Remove the cookie write from the useMemo block (lines 111–113) and rely solely on the useEffect for this side effect. Apply this change in isolation to verify it resolves the behavior correctly before making additional refactors.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/`[lang]/dho/[id]/_components/breadcrumbs-root-selector.tsx
around lines 98 - 116, The useMemo block that computes { rootHref, rootLabel,
fromQuery } currently performs an impure side effect by calling
setBreadcrumbOriginCookie(resolvedFrom, resolvedProfileSlug ?? undefined);
remove that call from the useMemo so the memo remains pure (leave the logic that
reads getBreadcrumbOriginFromCookie() and sets resolvedFrom/resolvedProfileSlug
intact), and ensure the existing useEffect that already calls
setBreadcrumbOriginCookie is the only place that writes the cookie; update
references to resolvedFrom/resolvedProfileSlug inside useEffect if needed to use
the memoized values from useMemo rather than repeating the write here.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/app/`[lang]/dho/[id]/_components/breadcrumbs-root-selector.tsx:
- Around line 61-63: The code currently casts searchParams.get('from') to
BreadcrumbOrigin without validation; add a validation step (e.g., an
isValidBreadcrumbOrigin type guard or whitelist check) and only
use/persist/forward `from` when it passes that check, otherwise treat it as
null/undefined; update all usages that currently do `const from =
searchParams.get('from') as BreadcrumbOrigin` and the later propagation sites
(the cookie/query propagation logic around the `fromQuery` and cookie set code
referenced near lines 95-97, 111-114, 138-140) to call the validator and guard
before writing to cookies or including in `fromQuery`.

In `@packages/epics/src/spaces/components/space-card.container.tsx`:
- Around line 22-25: getHref currently always appends fromParam with a "?" which
breaks URLs that already contain query params; update getHref (and usage of
baseUrl from getDhoPathAgreements) to detect whether baseUrl already contains
"?" and choose "&" instead of "?" when appending fromParam, and sanitize
fromParam (strip any leading "?" or "&") before concatenation so the produced
href is valid.

---

Nitpick comments:
In `@apps/web/src/app/`[lang]/dho/[id]/_components/breadcrumbs-root-selector.tsx:
- Around line 98-116: The useMemo block that computes { rootHref, rootLabel,
fromQuery } currently performs an impure side effect by calling
setBreadcrumbOriginCookie(resolvedFrom, resolvedProfileSlug ?? undefined);
remove that call from the useMemo so the memo remains pure (leave the logic that
reads getBreadcrumbOriginFromCookie() and sets resolvedFrom/resolvedProfileSlug
intact), and ensure the existing useEffect that already calls
setBreadcrumbOriginCookie is the only place that writes the cookie; update
references to resolvedFrom/resolvedProfileSlug inside useEffect if needed to use
the memoized values from useMemo rather than repeating the write here.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b69d7730-7b95-4923-93ac-53ee8204a6cb

📥 Commits

Reviewing files that changed from the base of the PR and between 6d3ff9a and 254806d.

📒 Files selected for processing (17)
  • apps/web/src/app/[lang]/dho/[id]/_components/breadcrumb-space-item.tsx
  • apps/web/src/app/[lang]/dho/[id]/_components/breadcrumbs-root-selector.tsx
  • apps/web/src/app/[lang]/dho/[id]/_components/breadcrumbs.tsx
  • apps/web/src/app/[lang]/dho/[id]/_components/spaces-carousel-with-from.tsx
  • apps/web/src/app/[lang]/dho/[id]/layout.tsx
  • apps/web/src/app/[lang]/my-spaces/page.tsx
  • apps/web/src/middleware.ts
  • packages/epics/src/common/get-path-function.ts
  • packages/epics/src/people/components/profile-member-spaces.tsx
  • packages/epics/src/spaces/components/breadcrumbs.tsx
  • packages/epics/src/spaces/components/explore-spaces.tsx
  • packages/epics/src/spaces/components/my-filtered-spaces.tsx
  • packages/epics/src/spaces/components/space-card-list.tsx
  • packages/epics/src/spaces/components/space-card.container.tsx
  • packages/i18n/src/messages/de.json
  • packages/i18n/src/messages/en.json
  • packages/i18n/src/messages/fr.json

Comment on lines +61 to +63
const from = searchParams.get('from') as BreadcrumbOrigin | null;
const profileSlug = searchParams.get('profileSlug');

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Validate from before using it in cookie/query propagation.

Line 61 and Line 95 trust from via type-cast only. A crafted value (e.g. ?from=foo) can be persisted to cookie and forwarded in fromQuery, creating inconsistent breadcrumb behavior across navigation.

🔧 Proposed fix
 type BreadcrumbOrigin = 'network' | 'profile' | 'my-spaces';
+const BREADCRUMB_ORIGINS: readonly BreadcrumbOrigin[] = [
+  'network',
+  'profile',
+  'my-spaces',
+];
+
+function parseBreadcrumbOrigin(value: string | null): BreadcrumbOrigin | null {
+  if (!value) return null;
+  return BREADCRUMB_ORIGINS.includes(value as BreadcrumbOrigin)
+    ? (value as BreadcrumbOrigin)
+    : null;
+}
@@
-  const from = searchParams.get('from') as BreadcrumbOrigin | null;
+  const from = parseBreadcrumbOrigin(searchParams.get('from'));
@@
-  const from = searchParams.get('from') as BreadcrumbOrigin | null;
+  const from = parseBreadcrumbOrigin(searchParams.get('from'));

Also applies to: 95-97, 111-114, 138-140

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/`[lang]/dho/[id]/_components/breadcrumbs-root-selector.tsx
around lines 61 - 63, The code currently casts searchParams.get('from') to
BreadcrumbOrigin without validation; add a validation step (e.g., an
isValidBreadcrumbOrigin type guard or whitelist check) and only
use/persist/forward `from` when it passes that check, otherwise treat it as
null/undefined; update all usages that currently do `const from =
searchParams.get('from') as BreadcrumbOrigin` and the later propagation sites
(the cookie/query propagation logic around the `fromQuery` and cookie set code
referenced near lines 95-97, 111-114, 138-140) to call the validator and guard
before writing to cookies or including in `fromQuery`.

Comment on lines +22 to +25
const getHref = (slug: string) => {
const baseUrl = getDhoPathAgreements(lang, slug);
return fromParam ? `${baseUrl}?${fromParam}` : baseUrl;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Handle existing query strings when appending fromParam.

getHref always uses ?. If baseUrl already has query params, the result is invalid.

🔧 Proposed fix
   const getHref = (slug: string) => {
     const baseUrl = getDhoPathAgreements(lang, slug);
-    return fromParam ? `${baseUrl}?${fromParam}` : baseUrl;
+    if (!fromParam) return baseUrl;
+    const separator = baseUrl.includes('?') ? '&' : '?';
+    return `${baseUrl}${separator}${fromParam}`;
   };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const getHref = (slug: string) => {
const baseUrl = getDhoPathAgreements(lang, slug);
return fromParam ? `${baseUrl}?${fromParam}` : baseUrl;
};
const getHref = (slug: string) => {
const baseUrl = getDhoPathAgreements(lang, slug);
if (!fromParam) return baseUrl;
const separator = baseUrl.includes('?') ? '&' : '?';
return `${baseUrl}${separator}${fromParam}`;
};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/epics/src/spaces/components/space-card.container.tsx` around lines
22 - 25, getHref currently always appends fromParam with a "?" which breaks URLs
that already contain query params; update getHref (and usage of baseUrl from
getDhoPathAgreements) to detect whether baseUrl already contains "?" and choose
"&" instead of "?" when appending fromParam, and sanitize fromParam (strip any
leading "?" or "&") before concatenation so the produced href is valid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Navigation issue: thread bar

2 participants