Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📝 WalkthroughWalkthroughThis pull request refactors SEO metadata handling from a centralized SEO component to distributed React Router route-level meta functions. The SEO.tsx component is removed, App.tsx's title management logic is simplified, root.tsx now handles canonical URLs and meta tags directly, and route files gain new meta exports using translation hooks and SEO utilities. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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: 12
🤖 Fix all issues with AI agents
In `@web/app/pages/Project/View/ViewProject.tsx`:
- Around line 696-703: The effect that updates document.title inside the
useEffect for live visitor counts exits early when user?.showLiveVisitorsInTitle
is false, leaving a previously-set "👀 …" title in place; update the effect in
the useEffect tied to project, user?.showLiveVisitorsInTitle, and liveVisitors
(the block that references document.title, liveVisitors, project, and
TITLE_SUFFIX) so that when showLiveVisitorsInTitle is false or project is
missing it explicitly resets document.title to the default (e.g., using
project.name + TITLE_SUFFIX or a safe fallback) instead of returning early.
In `@web/app/root.tsx`:
- Around line 316-324: The canonicalUrl builder currently includes the fragment
via the `hash` variable which can produce multiple canonical URLs; update the
`canonicalUrl` construction in root.tsx (the IIFE that uses `MAIN_URL`,
`pathname`, `search`, `hash`, `i18n.language`, and `defaultLanguage`) to omit
fragments—either stop concatenating `hash` into the URL or explicitly clear
`url.hash` before returning—then preserve the existing logic that sets or
deletes the `lng` search param based on `i18n.language`.
- Around line 335-343: Replace the single meta tag setting theme-color (the meta
with name='theme-color' currently using '#818cf8') with two theme-color meta
tags that target light and dark modes: add <meta name='theme-color'
media='(prefers-color-scheme: light)' content='#4f46e5' /> for indigo-600
(light) and <meta name='theme-color' media='(prefers-color-scheme: dark)'
content='#6366f1' /> for indigo-500 (dark); update the meta near the existing
meta lines (around the component that renders canonicalUrl and language) and
remove the old '#818cf8' tag.
In `@web/app/routes/captcha._index.tsx`:
- Around line 10-19: The meta function currently calls the React hook
useTranslation('common') which is invalid outside a component; replace that hook
usage in the exported meta function with a non-hook i18n call (use
i18next.getFixedT or the same pattern used in recovery.tsx) to obtain
translations, then build the return array with getTitle('CAPTCHA'),
getDescription(t('description.captcha')) and getPreviewImage() using that fixed
translator; update the meta function to call i18next.getFixedT('common') (or
equivalent) instead of useTranslation so the meta generation runs safely outside
React.
In `@web/app/routes/change-email`.$id.tsx:
- Around line 16-25: The meta() function is calling the React hook
useTranslation outside a component; remove that hook call and instead obtain
translations server-side (do not call hooks in meta). Concretely, stop using
useTranslation inside the exported meta, and either (A) compute the
title/description/preview values in the route loader (using your server-side
translation helper or i18n.getFixedT) and return them in loader data, then read
those values in meta({ data }) to call getTitle/getDescription/getPreviewImage,
or (B) import and call a non-hook server translation function (e.g., i18n.t or
getFixedT) directly inside meta to produce the same strings; update meta,
loader, and references to getTitle/getDescription/getPreviewImage accordingly.
In `@web/app/routes/contact.tsx`:
- Around line 10-19: The meta function incorrectly calls the React hook
useTranslation (in export const meta: MetaFunction) which must not run outside a
component; replace this by using a non-hook i18n accessor (e.g., i18next.t) or a
shared helper that calls i18next directly, then build the meta array via
getTitle, getDescription, getPreviewImage using those translated strings; create
a reusable utility (e.g., translateMeta or getServerT) that returns translations
for keys like 'titles.contact' and 'description.contact' and use that inside
meta instead of useTranslation to fix all route files.
In `@web/app/routes/organisations`.$id.tsx:
- Around line 11-28: The page meta currently builds title with TITLE_SUFFIX and
then calls getTitle (which also appends TITLE_SUFFIX), causing duplicate
suffixes; update the meta export (function meta) to build the base title without
TITLE_SUFFIX (e.g., const title = `${t('project.settings.settings')}
${orgName}`) and then pass that to getTitle so the suffix is only appended once;
locate the meta function in organisations.$id.tsx to apply this change.
In `@web/app/routes/projects`.$id.tsx:
- Around line 91-123: The meta function is incorrectly calling the React hook
useTranslation and parsing pathname with _split; remove the useTranslation()
call from meta, accept and use the params argument (use params.id) to build
pid/previewURL/canonicalURL instead of parsing location.pathname, and source any
localized strings from the loader-provided data (e.g., data.titles or
data.description keys) or fallback constants rather than calling hooks; update
references in meta (previewURL, canonicalURL, projectName, and any
getTitle/getDescription calls) to use params.id and data for
translations/fallbacks.
In `@web/app/routes/projects.settings`.$id.tsx:
- Around line 24-27: The title string currently includes TITLE_SUFFIX and then
calls getTitle(title) which appends the suffix again; fix by removing
TITLE_SUFFIX from the constructed title (change const title =
`${t('project.settings.settings')} ${projectName}`) or alternatively call
getTitle(title, false) to disable double-suffixing—update the code that sets the
title variable and the subsequent getTitle(...) call so only one TITLE_SUFFIX is
appended (refer to the title const, getTitle function, and TITLE_SUFFIX symbol).
In `@web/app/routes/recovery.tsx`:
- Around line 16-25: The meta export uses the React hook useTranslation inside
meta (function meta) which is invalid; replace the hook with the i18next
server-side translation call (e.g. import the i18next/i18n instance and call
i18next.t('titles.recovery') and i18next.t('description.recovery')) and remove
the eslint-disable comment, then pass those translated strings into getTitle,
getDescription, and getPreviewImage; update references in this file to use the
i18next/t function instead of useTranslation so meta remains a plain function
(affecting symbols: meta, useTranslation, getTitle, getDescription,
getPreviewImage).
In `@web/app/routes/verify`.$id.tsx:
- Around line 12-21: The meta export is calling the React hook useTranslation
outside a component (in export const meta: MetaFunction), so replace hook usage
with a non-hook i18n getter: add a shared helper getMetaTranslation that returns
i18next.getFixedT(null, namespace) (or similar) and then in verify.$id.tsx
change the meta function to call that helper (const t = getMetaTranslation())
and continue to use getTitle, getDescription, and getPreviewImage as before;
ensure the helper is imported where meta is defined and remove the
useTranslation import from this file.
In `@web/public/locales/en.json`:
- Around line 2101-2109: The description key for the signup page is misspelled
as "singup", causing the meta in web/app/routes/signup.tsx to resolve to a
missing description; rename the key inside the "description" object from
"singup" to "signup" and update the same key in all other locale files to keep
translations in sync so the signup route meta correctly reads
description.signup.
🧹 Nitpick comments (3)
web/app/utils/seo.ts (1)
3-14: Reduce repeated title string construction.
This avoids duplication and makes future edits less error‑prone.♻️ Suggested refactor
-export const getTitle = (title: string, showSuffix = true) => [ - { - title: `${title} ${showSuffix ? TITLE_SUFFIX : ''}`.trim(), - }, - { - property: 'og:title', - content: `${title} ${showSuffix ? TITLE_SUFFIX : ''}`.trim(), - }, - { - name: 'twitter:title', - content: `${title} ${showSuffix ? TITLE_SUFFIX : ''}`.trim(), - }, -] +export const getTitle = (title: string, showSuffix = true) => { + const fullTitle = `${title} ${showSuffix ? TITLE_SUFFIX : ''}`.trim() + + return [ + { title: fullTitle }, + { property: 'og:title', content: fullTitle }, + { name: 'twitter:title', content: fullTitle }, + ] +}web/app/routes/tools._index.tsx (1)
12-14: Consider adding a meta description for SEO consistency.Unlike other tool routes (
tools.utm-generator.tsx,tools.roi-calculator.tsx), this route is missing agetDescription()call. Adding a description improves SEO and social sharing previews.♻️ Suggested improvement
export const meta: MetaFunction = () => { - return [...getTitle('Free Marketing Tools'), ...getPreviewImage()] + return [ + ...getTitle('Free Marketing Tools'), + ...getDescription( + 'Professional marketing calculators and generators to optimize your campaigns, track performance, and maximize ROI. No sign-up required.', + ), + ...getPreviewImage(), + ] }You'll also need to add
getDescriptionto the import:-import { getPreviewImage, getTitle } from '~/utils/seo' +import { getDescription, getPreviewImage, getTitle } from '~/utils/seo'web/app/routes/reports-unsubscribe.$token.tsx (1)
12-20: Consider localizing the title for i18n parity.Other routes use translated titles; this page’s meta title will stay English in non‑English locales. Consider moving it to the
commonlocale files.♻️ Suggested change
- ...getTitle('Unsubscribe from email reports'), + ...getTitle(t('titles.reportsUnsubscribe')),
Changes
If applicable, please describe what changes were made in this pull request.
Community Edition support
Database migrations
Documentation
Summary by CodeRabbit
Release Notes
Bug Fixes
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.