Skip to content

fix(seo): comprehensive SEO audit cleanup - #213

Merged
ayoub3bidi merged 11 commits into
developfrom
fix/seo-audit-cleanup
Jul 25, 2026
Merged

fix(seo): comprehensive SEO audit cleanup#213
ayoub3bidi merged 11 commits into
developfrom
fix/seo-audit-cleanup

Conversation

@ayoub3bidi

@ayoub3bidi ayoub3bidi commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Contribution workflow

  • Base branch is develop: This PR targets develop, not main.
  • Guidelines and docs: I have read CONTRIBUTING.md and the docs relevant to my change.
  • This template: I kept the PR template structure and filled in the sections below.

Description

Comprehensive SEO audit cleanup addressing issues flagged by Seobility, SiteGuer, and Semrush external crawlers. 9 commits across 3 files changed, 2 new files added.

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • 🧪 Test addition or improvement

Related Issues

Internal SEO audit — no open issue.

Changes Made

  • Changed Header site name from <h1> to <span> to resolve duplicate H1 conflict with page content
  • Replaced Footer Privacy/Terms <motion.button> with <Link> for crawlable anchor tags
  • Added NotFoundPage component with i18n (en/fr/ar) + catch-all * route
  • Shortened meta description from 218 to ~155 chars (was exceeding 1000px pixel limit)
  • Fixed Twitter card tags from property= to name= per Twitter/X spec
  • Added twitter:site meta tag
  • Added dynamic hreflang alternate links for en/fr/ar + x-default
  • Added og:locale and og:locale:alternate meta tags
  • Added <meta name="theme-color"> for PWA browser chrome
  • Added <link rel="preconnect"> for Pyodide CDN
  • Removed hardcoded <link rel="canonical"> from index.html (already managed dynamically)
  • Added Content-Type: text/html; charset=utf-8 to Cloudflare _headers
  • Wrapped Roadmap and Pro page content in <main> landmarks
  • Removed dead titleKey prop from DocumentTitle on Pro page
  • Updated DocumentTitle.jsx to use name= for twitter selectors
  • Updated Footer tests to check href attributes instead of navigate calls
  • Updated DocumentTitle tests: twitter selectors property=name=, added 3 new tests for hreflang/og:locale

Testing

  • All existing tests pass (pnpm vitest run)
  • New tests added for new functionality (17 DocumentTitle tests, up from 14)
  • Lint passes with 0 errors

Test Results

Test Files  165 passed (165)
     Tests  1911 passed (1911)

Code Quality

  • ESLint passes (0 errors, 2 pre-existing warnings)
  • Prettier formatting applied
  • No console errors or warnings

Breaking Changes

  • None

Checklist

  • My code follows the project style guidelines
  • I have performed a self-review of my code
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • New Features
    • Added a localized 404 page for unmatched URLs, with a link back to the homepage.
    • Added language-aware hreflang and Open Graph locale metadata.
    • Added French and Arabic translations for the 404 page.
  • Improvements
    • Updated SEO, social sharing, Twitter Card, and theme-color metadata.
    • Improved Privacy and Terms navigation with direct links.
    • Updated page structure with more semantic HTML elements.
  • Bug Fixes
    • Corrected social metadata handling and HTML content-type headers.

Reserve <h1> for page content only (Hero section). The Header site name
now uses <span> to avoid duplicate h1 tags on the landing page, which
SEO crawlers and audit tools flag as an issue.
Privacy and Terms footer links were <motion.button onClick> elements
which are invisible to search engine crawlers. Replaced with <Link>
components that render proper <a> tags, making them crawlable and
improving internal link structure detection by SEO tools.
Unknown URLs previously showed a blank page with no feedback. Added a
catch-all Route path="*" with a NotFoundPage component that displays
a 404 heading, descriptive message, and link back to home. Includes
i18n support for en/fr/ar (RTL-safe).
- Shortened meta description from 218 to ~155 chars (was exceeding
  1000px pixel limit flagged by Seobility)
- Changed Twitter card tags from property= to name= per Twitter spec
- Added twitter:site meta tag for @bayanflow
- Updated DocumentTitle.jsx queries to match new name= selectors
- Unified meta, og:description, and twitter:description to same text
- Added dynamic hreflang alternate links for en/fr/ar + x-default
- Added og:locale and og:locale:alternate meta tags
- Added <meta name="theme-color"> for PWA browser chrome
- Added <link rel="preconnect"> for Pyodide CDN (cdn.jsdelivr.net)
- Locale-aware: tags update when user switches language
- Removed static <link rel="canonical"> from index.html (already
  managed dynamically by DocumentTitle.jsx ensureCanonicalLink())
  to avoid potential duplicate canonical conflicts
- Added Content-Type: text/html; charset=utf-8 to Cloudflare _headers
  to ensure explicit charset declaration for Seobility compliance
- Wrapped Roadmap content in <main> element for ARIA landmark
- Wrapped ProComingSoonPage content in <main> element
- Removed dead titleKey prop from DocumentTitle on Pro page (title
  is derived from ROUTE_TITLE_KEYS + pathname internally)
- Updated twitter meta tag selectors from property= to name= to match
  real Twitter card spec and index.html changes
- Added ensureMetaTag helper to create twitter tags with name= attr
- Added test for hreflang alternate links (en/fr/ar + x-default)
- Added test for og:locale and og:locale:alternate tags
- Added test for og:locale update when language changes to Arabic
- Added test for hreflang links updating on route change
- Total: 17 tests (up from 14)
- Removed unused currentLang param from ensureAlternateLinks
- Updated Footer tests to check href attributes instead of navigate
  calls (privacy/terms are now Link components, not buttons)
- Ran prettier to fix all formatting issues
@github-actions github-actions Bot added style Improve styling, design, and animation tests labels Jul 25, 2026
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ayoub3bidi, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 934f0d8f-f0a1-41be-89da-46cd063fd9aa

📥 Commits

Reviewing files that changed from the base of the PR and between afa4949 and 965e724.

📒 Files selected for processing (8)
  • index.html
  • public/_headers
  • src/components/DocumentTitle.jsx
  • src/components/DocumentTitle.test.jsx
  • src/constants/siteSeo.js
  • src/constants/siteSeo.test.js
  • src/pages/NotFoundPage.jsx
  • src/pages/Roadmap.jsx
📝 Walkthrough

Walkthrough

The PR updates SEO and social metadata, adds localized route-aware locale tags, introduces a localized wildcard 404 page, changes footer legal links to router links, and applies semantic markup updates to several pages.

Changes

SEO metadata and locale handling

Layer / File(s) Summary
SEO metadata and locale handling
index.html, public/_headers, src/components/DocumentTitle.jsx, src/components/DocumentTitle.test.jsx, src/constants/siteSeo.js
Static SEO, Twitter, theme-color, and response metadata are updated. DocumentTitle now maintains route-aware hreflang and Open Graph locale tags, with corresponding tests.

Localized not-found route

Layer / File(s) Summary
Localized not-found route
src/AppRoutes.jsx, src/pages/NotFoundPage.jsx, src/i18n/locales/*/translation.json
Unmatched routes render a localized 404 page with translated title, message, and home navigation.

Navigation and semantic markup

Layer / File(s) Summary
Navigation and semantic markup
src/components/Footer.jsx, src/components/Footer.test.jsx, src/components/Header.jsx, src/pages/ProComingSoonPage.jsx, src/pages/Roadmap.jsx
Privacy and Terms use router links, the header branding uses a span instead of an h1, and page content uses main landmarks while preserving existing content behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: config, tests

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.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 title accurately reflects the main theme of the PR: a broad SEO cleanup driven by an audit.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/seo-audit-cleanup

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.

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

Preview for Bayan Flow Staging ready!

Name Link
🔨 Latest commit 965e724
🔍 Latest deploy log https://github.com/ayoub3bidi/bayan-flow/actions/runs/30170276193
😎 Deploy Preview https://pr-213-bayan-flow-staging.ayoub3bidi.workers.dev
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

Preview alias pr-213 on the staging worker. Updates automatically with new commits.

@codecov

codecov Bot commented Jul 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.50000% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/pages/ProComingSoonPage.jsx 95.58% 6 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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 `@public/_headers`:
- Line 7: Remove the Content-Type: text/html; charset=utf-8 directive from the
catch-all rule in public/_headers, leaving asset MIME types to Cloudflare’s
defaults and preserving the remaining headers.

In `@src/components/DocumentTitle.jsx`:
- Around line 118-130: Update the alternate-locale reconciliation in
DocumentTitle to remove any existing og:locale:alternate meta element whose
data-lang matches the current lang before iterating through HREFLANG_LOCALES;
preserve creating or updating entries for other locales. In
src/components/DocumentTitle.test.jsx lines 300-312, add or update the
language-switching assertion to verify the current language has no
og:locale:alternate element.
- Around line 23-27: Update OG_LOCALE_MAP in DocumentTitle.jsx to use the Open
Graph territory matching the app’s Arabic content rather than ar_AR, and update
the corresponding og:locale:alternate expectations in DocumentTitle.test.jsx at
lines 281-298 to match the new locale value.

In `@src/pages/NotFoundPage.jsx`:
- Around line 23-25: Update the Button component’s `to` branch to render a
single interactive router link, using a styled Link or motion(Link) instead of
nesting a motion button inside Link. Preserve the existing styling, navigation
target, and behavior of the NotFoundPage home action.
- Around line 16-21: Update the heading structure in NotFoundPage so the
translated notFound.title becomes the sole semantic h1, retaining its existing
heading styling. Change the literal 404 into decorative or secondary content
rather than a heading, and preserve the existing notFound.message paragraph.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a103715b-c391-4a20-a7b4-6c3650156552

📥 Commits

Reviewing files that changed from the base of the PR and between 4cb0e39 and afa4949.

📒 Files selected for processing (15)
  • index.html
  • public/_headers
  • src/AppRoutes.jsx
  • src/components/DocumentTitle.jsx
  • src/components/DocumentTitle.test.jsx
  • src/components/Footer.jsx
  • src/components/Footer.test.jsx
  • src/components/Header.jsx
  • src/constants/siteSeo.js
  • src/i18n/locales/ar/translation.json
  • src/i18n/locales/en/translation.json
  • src/i18n/locales/fr/translation.json
  • src/pages/NotFoundPage.jsx
  • src/pages/ProComingSoonPage.jsx
  • src/pages/Roadmap.jsx

Comment thread public/_headers Outdated
Comment thread src/components/DocumentTitle.jsx
Comment thread src/components/DocumentTitle.jsx
Comment thread src/pages/NotFoundPage.jsx Outdated
Comment thread src/pages/NotFoundPage.jsx Outdated
- Removed Content-Type from catch-all _headers rule (would override
  MIME types for /assets/* causing app breakage with nosniff)
- Moved charset header to /index.html specific route only
- Fixed ar_AR (not a valid locale) to ar_SA in OG_LOCALE_MAP
- Added cleanup of og:locale:alternate when locale becomes active
- NotFoundPage: made translated title the semantic h1, 404 as
  decorative aria-hidden content for screen readers
- NotFoundPage: replaced Button with Link to avoid nested
  interactive elements (motion.button inside router Link)
Add buildMetaDescription() to siteSeo.js that computes the meta
description from CATEGORY_CONFIG algorithmKeys, so the count and
category list stay in sync automatically when algorithms are added.

- siteSeo.js: add CATEGORY_DISPLAY_NAMES map + buildMetaDescription()
- DocumentTitle.jsx: use buildMetaDescription() for landing + default
- index.html: sync static fallback with computed value + add comment
- siteSeo.test.js: add test for buildMetaDescription()
- DocumentTitle.test.jsx: update meta description assertion to match
- Roadmap.jsx: remove unused useTranslation import (lint cleanup)
@ayoub3bidi
ayoub3bidi merged commit 60809e4 into develop Jul 25, 2026
15 checks passed
@ayoub3bidi
ayoub3bidi deleted the fix/seo-audit-cleanup branch July 25, 2026 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

style Improve styling, design, and animation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant