feat: SEO & AI visibility - #57
Conversation
|
Warning Review limit reached
Next review available in: 41 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (8)
WalkthroughThe feed moves from ChangesRoot feed and SEO migration
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Browser
participant RootFeed
participant Convex
participant EventPage
Browser->>RootFeed: Request /
RootFeed->>Convex: Fetch feed events
Convex-->>RootFeed: Return event data
RootFeed-->>Browser: Render feed
Browser->>EventPage: Open event link
EventPage-->>Browser: Render event metadata and content
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/components/header.tsx`:
- Line 27: Update the isActive checks in the desktop and mobile navigation to
special-case the root route: treat “/” as active only when currentPath exactly
equals “/”, while preserving the existing startsWith behavior for non-root
destinations. Apply the same logic in both navigation locations so the Feed tab
is not active on other routes.
In `@apps/web/src/components/layout/MobileTabBar.tsx`:
- Around line 25-29: Update the Feed tab’s isActive check in MobileTabBar so
archived root URLs such as /?page=2 are not treated as the live Feed
destination. Include the current search/query state in the check or otherwise
ensure selecting Feed navigates to a clean “/” URL while preserving the existing
event-path behavior.
In `@apps/web/src/routes/event`.$slug.tsx:
- Around line 282-303: Reset cameFromFeed to false at the beginning of the
useEffect keyed by slug, before checking sessionStorage, so each event
navigation starts with a clean value. Preserve the existing storage-based
set-to-true behavior and cleanup logic.
In `@apps/web/src/routes/index.tsx`:
- Around line 859-864: Add role="status" and aria-live="polite" to the
no-results section rendered by the isSearching && searchResults?.length === 0
condition, matching the existing search-state accessibility behavior. Keep the
current no-match content and styling unchanged.
- Around line 357-376: Update FeedArchive’s !archive branch to render an error
state with a retry affordance instead of the feed.loading status message. Use
the existing route revalidation/navigation mechanism and translation symbols
available in the surrounding component, while preserving the current archive
rendering when loaderData contains archive.
In `@apps/web/src/routes/news-sitemap`[.]xml.ts:
- Around line 12-34: Extract the duplicated escapeXml helper and
SyndicationEvent type into a shared syndication module, then update both
news-sitemap and rss route implementations to import and reuse those shared
symbols. Remove the local duplicate definitions while preserving their existing
behavior and type usage.
In `@apps/web/src/routes/rss`[.]xml.ts:
- Around line 17-24: Extract the duplicated escapeXml implementation into a
shared XML utility, preserving its current escaping order and behavior. Update
the rss[.]xml, sitemap[.]xml, news-sitemap[.]xml, and shareAssetsNode consumers
to import and reuse the shared escapeXml function, removing their local copies.
In `@packages/i18n/src/strings.ts`:
- Line 295: Update the feed.meta.title string to use an em dash (—) instead of
the regular hyphen (-), matching the formatting used by the other meta-title
keys and seo.siteTitle.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e2bd5e86-839f-4ea6-8827-ee0c559f4a30
⛔ Files ignored due to path filters (1)
apps/web/src/routeTree.gen.tsis excluded by!**/routeTree.gen.ts
📒 Files selected for processing (28)
apps/web/src/components/MiezOnboarding.test.tsxapps/web/src/components/MiezOnboarding.tsxapps/web/src/components/bookmark-button.tsxapps/web/src/components/feed/event-card.tsxapps/web/src/components/header.tsxapps/web/src/components/layout/MobileTabBar.tsxapps/web/src/components/quiz-hidden.test.tsxapps/web/src/lib/feature-flags.tsapps/web/src/lib/i18n/getLocaleFromMatches.tsapps/web/src/lib/seo.tsapps/web/src/router.tsxapps/web/src/routes/__root.tsxapps/web/src/routes/activitate.tsxapps/web/src/routes/event.$slug.tsxapps/web/src/routes/feed.tsxapps/web/src/routes/index.tsxapps/web/src/routes/llms[.]txt.tsapps/web/src/routes/news-sitemap[.]xml.tsapps/web/src/routes/quiz.tsxapps/web/src/routes/robots[.]txt.tsapps/web/src/routes/rss[.]xml.tsapps/web/src/routes/salvate.tsxapps/web/src/routes/sitemap[.]xml.tsapps/web/src/routes/source.$sourceId.tsxdocs/seo-batch-2-runbook.mdpackages/backend/convex/events.tspackages/backend/convex/sitemap.tspackages/i18n/src/strings.ts
|
|
||
| const allLinks = [ | ||
| { to: "/feed", key: "tabs.feed", icon: Newspaper }, | ||
| { to: "/", key: "tabs.feed", icon: Newspaper }, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Feed tab is always active: currentPath.startsWith("/") matches every route.
Changing to from "/feed" to "/" at line 27 breaks the isActive check at lines 72 and 129. currentPath.startsWith(${to}/) becomes currentPath.startsWith("/"), which is true for every path. The feed tab will appear active on /quiz, /salvate, /activitate, /profil, and event pages simultaneously with the actual active tab.
As per path instructions for apps/web/**: verify proper React patterns and check TanStack Router usage patterns.
🐛 Proposed fix: special-case the root path in `isActive`
const isActive =
- currentPath === to || currentPath.startsWith(`${to}/`);
+ to === "/"
+ ? currentPath === "/"
+ : currentPath === to || currentPath.startsWith(`${to}/`);Apply this fix at both line 72 (desktop nav) and line 129 (mobile nav).
Also applies to: 72-72, 129-129
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/components/header.tsx` at line 27, Update the isActive checks in
the desktop and mobile navigation to special-case the root route: treat “/” as
active only when currentPath exactly equals “/”, while preserving the existing
startsWith behavior for non-root destinations. Apply the same logic in both
navigation locations so the Feed tab is not active on other routes.
Source: Path instructions
- MobileTabBar: keep Feed tab inactive on the /?page=N archive and route taps back to a clean "/" instead of a scroll-to-top no-op - event.$slug: reset cameFromFeed at the start of the slug effect so client-side jumps don't inherit the previous event's flag - feed archive: show an error state with retry (router.invalidate) when the loader query throws, instead of a permanent loading spinner - search no-results: add role=status/aria-live=polite - dedupe escapeXml + SyndicationEvent into @/lib/syndication across the rss/sitemap/news-sitemap routes - feed.meta.title: use em dash to match the other meta titles Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary by CodeRabbit