Skip to content

Feat seo serp preview#373

Merged
AlemTuzlak merged 18 commits intoTanStack:mainfrom
abedshaaban:feat-seo-serp-preview
Mar 30, 2026
Merged

Feat seo serp preview#373
AlemTuzlak merged 18 commits intoTanStack:mainfrom
abedshaaban:feat-seo-serp-preview

Conversation

@abedshaaban
Copy link
Copy Markdown
Contributor

@abedshaaban abedshaaban commented Mar 7, 2026

🎯 Changes

Implemented an SERP (Search Engine Results Page) section inside the SEO tab beside Social previews section. This enables users to view meta tags and check how they will be shown.

Examples:

Normal

Screenshot 2026-03-07 at 21 55 54

No Favicon or Description

Screenshot 2026-03-07 at 21 56 42

Tag Exceeds Length

Screenshot 2026-03-07 at 23 25 52

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • New Features
    • Added SEO tab with SERP (Search Engine Results Page) preview functionality
    • Displays desktop and mobile previews showing your site's favicon, title, and description
    • Includes error reporting for missing SEO elements and content exceeding recommended character limits

This commit deletes the SeoTab component from the devtools package, which included social media preview functionality and meta tag analysis. The removal streamlines the codebase by eliminating unused features.
This commit updates the naming of the SocialPreviewSection component to SocialPreviewsSection for consistency and clarity in the SEO tab of the devtools package. The change improves code readability and aligns with the pluralization of the component's purpose.
… update import path

This commit renames the social-preview.tsx file to social-previews.tsx for consistency with the component naming convention. The import path in the SeoTab component is also updated accordingly, enhancing code clarity and maintainability.
This commit introduces a navigation bar in the SeoTab component, allowing users to switch between 'Social Previews' and 'SERP Preview' sections. It also updates the SocialPreviewsSection to conditionally render its title based on a new prop, improving flexibility in display options. New styles for the navigation elements are added to enhance the user interface.
…data handling

This commit introduces new styles for the SERP snippet and updates the SERP and Social Previews sections to dynamically display data from the current page's metadata. The SocialPreviewsSection and SerpPreviewSection components are refactored to improve clarity and functionality, removing unnecessary props and enhancing the user interface with better styling.
This commit refactors the SERP snippet styles by renaming the `serpSnippetUrlRow` to `serpSnippetTopRow` and introduces new styles for site name and URL. The structure of the SERP preview is enhanced to better organize the display of site information, improving the overall layout and visual consistency.
…ow reporting

This commit adds functionality to the SERP preview section, implementing text truncation for the title and description based on specified width limits. It introduces new state management for overflow detection and displays warnings when the title or description exceeds the defined character limits. Additionally, new styles are added to support the hidden measurement elements for accurate text sizing.
This commit enhances the SERP preview section by introducing a new overflow reporting mechanism for the title and description. It adds a list of issues when the title or description exceeds specified limits, improving user feedback. Additionally, new styles are implemented for better visual presentation of error messages in the SERP preview.
This commit enhances the SEO capabilities of the basic example by adding a meta description tag for improved search engine visibility. Additionally, it introduces new styles for a default favicon, ensuring a consistent visual representation when no favicon is provided. This improves user feedback in the SERP preview section.
This commit introduces new styles for the SERP preview section, including a dedicated block for the preview and a label for better organization. The layout improvements enhance the visual presentation of the desktop preview, ensuring a clearer display of the site name, URL, title, and description.
…verflow reporting

This commit introduces new styles for the mobile SERP preview, including a dedicated snippet layout and improved overflow reporting for the title and description. It adds functionality to handle mobile-specific text truncation and displays warnings for descriptions exceeding a three-line limit, enhancing user feedback and visual consistency across devices.
…nce component structure

This commit introduces a robust mechanism for reporting SERP issues, including checks for favicon, title, and description validity. It refactors the SERP preview component to utilize a more structured approach for handling overflow conditions and displaying relevant warnings. Additionally, it enhances the layout for both desktop and mobile previews, ensuring a consistent and informative user experience across devices.
…character limits

This commit refines the SERP preview component by replacing pixel-based truncation with character-based limits for titles and descriptions. It introduces constants for maximum character counts, enhancing the clarity of the truncation logic. Additionally, it simplifies the component structure by removing unnecessary measurement elements, improving overall readability and maintainability.
…racter limit handling

This commit refines the SERP preview component by enhancing the character limit handling for titles and descriptions. It simplifies the component structure, removing redundant elements, and improves the overall readability and maintainability of the code. Additionally, it ensures consistent behavior across different display scenarios.
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 7, 2026

🦋 Changeset detected

Latest commit: d11c81e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@tanstack/devtools Patch
@tanstack/preact-devtools Patch
@tanstack/react-devtools Patch
@tanstack/solid-devtools Patch
@tanstack/vue-devtools Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Mar 11, 2026

View your CI Pipeline Execution ↗ for commit 6be382a

Command Status Duration Result
nx affected --targets=test:eslint,test:sherif,t... ✅ Succeeded 1m 33s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-30 12:46:48 UTC

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 11, 2026

More templates

@tanstack/devtools

npm i https://pkg.pr.new/@tanstack/devtools@373

@tanstack/devtools-a11y

npm i https://pkg.pr.new/@tanstack/devtools-a11y@373

@tanstack/devtools-client

npm i https://pkg.pr.new/@tanstack/devtools-client@373

@tanstack/devtools-ui

npm i https://pkg.pr.new/@tanstack/devtools-ui@373

@tanstack/devtools-utils

npm i https://pkg.pr.new/@tanstack/devtools-utils@373

@tanstack/devtools-vite

npm i https://pkg.pr.new/@tanstack/devtools-vite@373

@tanstack/devtools-event-bus

npm i https://pkg.pr.new/@tanstack/devtools-event-bus@373

@tanstack/devtools-event-client

npm i https://pkg.pr.new/@tanstack/devtools-event-client@373

@tanstack/preact-devtools

npm i https://pkg.pr.new/@tanstack/preact-devtools@373

@tanstack/react-devtools

npm i https://pkg.pr.new/@tanstack/react-devtools@373

@tanstack/solid-devtools

npm i https://pkg.pr.new/@tanstack/solid-devtools@373

@tanstack/vue-devtools

npm i https://pkg.pr.new/@tanstack/vue-devtools@373

commit: 6be382a

@AlemTuzlak
Copy link
Copy Markdown
Collaborator

@abedshaaban this looks awesome, can you fix the failing tests?

@abedshaaban
Copy link
Copy Markdown
Contributor Author

Sure

@abedshaaban
Copy link
Copy Markdown
Contributor Author

@AlemTuzlak all done and ready to check

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 30, 2026

📝 Walkthrough

Walkthrough

The SEO tab functionality has been expanded with a new SERP preview feature. A secondary navigation state was introduced to switch between social previews and SERP preview views. New styles support the sub-navigation and SERP snippet layout. The SERP preview component renders desktop and mobile search result previews with metadata validation and error reporting.

Changes

Cohort / File(s) Summary
Release Documentation
.changeset/vast-apes-attend.md
Added changeset entry for patch release documenting SERP section feature in SEO tab.
Example Assets
examples/react/basic/index.html
Added meta description tag to HTML head element.
Styling
packages/devtools/src/styles/use-styles.ts
Added SERP-related style definitions including sub-navigation styling, SERP preview blocks, snippet layouts, measurement helpers, and error reporting UI styles.
SEO Tab Refactor
packages/devtools/src/tabs/seo-tab/index.tsx, packages/devtools/src/tabs/seo-tab/social-previews.tsx, packages/devtools/src/tabs/seo-tab/serp-preview.tsx
Restructured SEO tab with dual-view navigation logic. Extracted SocialPreviewsSection from previous monolithic SeoTab. Added new SerpPreviewSection component that reads page metadata, validates against SEO constraints (favicon, title, description), truncates text to search engine character limits, and renders both desktop and mobile SERP previews with error reporting.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hops of joy! A SERP so fine,
Desktop, mobile side-by-side they shine,
Metadata checked with bunny care,
SEO previews beyond compare! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat seo serp preview' clearly and concisely describes the main change—implementing a SERP preview feature in the SEO tab, which aligns with the changeset and file modifications.
Description check ✅ Passed The PR description addresses the template's 'Changes' section with detailed explanation and screenshots, completes the checklist, and specifies the release impact. All required sections are present and substantively filled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (3)
packages/devtools/src/tabs/seo-tab/index.tsx (1)

16-38: Expose tab semantics for assistive tech on the SEO sub-navigation.

The toggle works visually, but adding tablist/tab/tabpanel roles and aria-selected would make state and structure explicit to screen readers.

Suggested diff
-      <nav class={styles().seoSubNav} aria-label="SEO sections">
+      <nav class={styles().seoSubNav} aria-label="SEO sections" role="tablist">
         <button
           type="button"
+          role="tab"
+          id="seo-social-previews-tab"
+          aria-controls="seo-social-previews-panel"
+          aria-selected={activeView() === 'social-previews'}
           class={`${styles().seoSubNavLabel} ${activeView() === 'social-previews' ? styles().seoSubNavLabelActive : ''}`}
           onClick={() => setActiveView('social-previews')}
         >
           Social previews
         </button>
         <button
           type="button"
+          role="tab"
+          id="seo-serp-preview-tab"
+          aria-controls="seo-serp-preview-panel"
+          aria-selected={activeView() === 'serp-preview'}
           class={`${styles().seoSubNavLabel} ${activeView() === 'serp-preview' ? styles().seoSubNavLabelActive : ''}`}
           onClick={() => setActiveView('serp-preview')}
         >
           SERP Preview
         </button>
       </nav>
 
       <Show when={activeView() === 'social-previews'}>
-        <SocialPreviewsSection />
+        <div role="tabpanel" id="seo-social-previews-panel" aria-labelledby="seo-social-previews-tab">
+          <SocialPreviewsSection />
+        </div>
       </Show>
       <Show when={activeView() === 'serp-preview'}>
-        <SerpPreviewSection />
+        <div role="tabpanel" id="seo-serp-preview-panel" aria-labelledby="seo-serp-preview-tab">
+          <SerpPreviewSection />
+        </div>
       </Show>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/tabs/seo-tab/index.tsx` around lines 16 - 38, The SEO
sub-nav currently toggles views visually but lacks ARIA tab semantics; update
the nav and view elements so assistive tech recognizes them as tabs: give the
nav the role="tablist", change each toggle button (the ones using
styles().seoSubNavLabel and onClick that call setActiveView with
'social-previews'/'serp-preview') to role="tab" and include
aria-selected={activeView() === '...'} plus aria-controls that reference the
corresponding tabpanel id; wrap SocialPreviewsSection and SerpPreviewSection
outputs in containers with role="tabpanel", matching id attributes referenced by
aria-controls, and set aria-hidden appropriately (or toggle rendering) based on
activeView() so screen readers see the active panel.
packages/devtools/src/styles/use-styles.ts (1)

129-143: Add explicit keyboard focus styling for sub-nav buttons.

seoSubNavLabel has hover styling but no explicit :focus-visible rule. Adding one makes keyboard navigation feedback consistent.

Suggested diff
     seoSubNavLabel: css`
       padding: 0.5rem 1rem;
       font-size: 0.875rem;
       font-weight: 500;
       color: ${t(colors.gray[600], colors.gray[400])};
       background: none;
       border: none;
       border-bottom: 2px solid transparent;
       margin-bottom: -1px;
       cursor: pointer;
       font-family: inherit;
       &:hover {
         color: ${t(colors.gray[800], colors.gray[200])};
       }
+      &:focus-visible {
+        outline: 2px solid ${t(colors.gray[900], colors.gray[100])};
+        outline-offset: 2px;
+      }
     `,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/styles/use-styles.ts` around lines 129 - 143, The
seoSubNavLabel style lacks keyboard focus styling; add a :focus-visible rule to
seoSubNavLabel so keyboard users get the same visible feedback as hover (e.g.,
set color to the hover color, and/or change border-bottom color or add an
outline) and ensure font-family/cursor remain; update the css block for
seoSubNavLabel to include &:focus-visible { color: ${t(colors.gray[800],
colors.gray[200])}; /* and set border-bottom or outline for visible focus */ }
so keyboard navigation is consistent and accessible.
packages/devtools/src/tabs/seo-tab/serp-preview.tsx (1)

212-247: Align mobile snippet text with the mobile overflow threshold.

Right now both previews consume the desktop-truncated description. Passing a mobile-specific truncation value will keep preview text and mobile warnings in sync.

Suggested diff
   const serpPreviewState = createMemo(() => {
     const data = serp()
     const titleText = data.title || 'No title'
     const descText = data.description || 'No meta description.'
 
     const displayTitle = truncateToChars(titleText, TITLE_MAX_CHARS)
     const displayDescription = truncateToChars(descText, DESCRIPTION_MAX_CHARS)
+    const displayDescriptionMobile = truncateToChars(
+      descText,
+      DESCRIPTION_MOBILE_MAX_CHARS,
+    )
 
     return {
       displayTitle,
       displayDescription,
+      displayDescriptionMobile,
       overflow: {
         titleOverflow: titleText.length > TITLE_MAX_CHARS,
         descriptionOverflow: descText.length > DESCRIPTION_MAX_CHARS,
         descriptionOverflowMobile:
           descText.length > DESCRIPTION_MOBILE_MAX_CHARS,
@@
             <SerpSnippetPreview
               data={serp()}
               displayTitle={serpPreviewState().displayTitle}
-              displayDescription={serpPreviewState().displayDescription}
+              displayDescription={
+                preview.isMobile
+                  ? serpPreviewState().displayDescriptionMobile
+                  : serpPreviewState().displayDescription
+              }
               isMobile={preview.isMobile}
               label={preview.label}
               issues={issues()}
             />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/devtools/src/tabs/seo-tab/serp-preview.tsx` around lines 212 - 247,
The mobile preview is using the desktop-truncated description, causing
mismatched text and mobile overflow warnings; update the render so
SerpSnippetPreview receives a mobile-specific truncated description when
preview.isMobile by using truncateToChars with DESCRIPTION_MOBILE_MAX_CHARS (or
add a mobileDisplayDescription to serpPreviewState) and ensure
getSerpIssues/overflow checks use the same mobile threshold so preview text and
overflow flags (SERP_PREVIEWS, serpPreviewState, truncateToChars,
DESCRIPTION_MOBILE_MAX_CHARS, SerpSnippetPreview) stay in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/devtools/src/styles/use-styles.ts`:
- Around line 129-143: The seoSubNavLabel style lacks keyboard focus styling;
add a :focus-visible rule to seoSubNavLabel so keyboard users get the same
visible feedback as hover (e.g., set color to the hover color, and/or change
border-bottom color or add an outline) and ensure font-family/cursor remain;
update the css block for seoSubNavLabel to include &:focus-visible { color:
${t(colors.gray[800], colors.gray[200])}; /* and set border-bottom or outline
for visible focus */ } so keyboard navigation is consistent and accessible.

In `@packages/devtools/src/tabs/seo-tab/index.tsx`:
- Around line 16-38: The SEO sub-nav currently toggles views visually but lacks
ARIA tab semantics; update the nav and view elements so assistive tech
recognizes them as tabs: give the nav the role="tablist", change each toggle
button (the ones using styles().seoSubNavLabel and onClick that call
setActiveView with 'social-previews'/'serp-preview') to role="tab" and include
aria-selected={activeView() === '...'} plus aria-controls that reference the
corresponding tabpanel id; wrap SocialPreviewsSection and SerpPreviewSection
outputs in containers with role="tabpanel", matching id attributes referenced by
aria-controls, and set aria-hidden appropriately (or toggle rendering) based on
activeView() so screen readers see the active panel.

In `@packages/devtools/src/tabs/seo-tab/serp-preview.tsx`:
- Around line 212-247: The mobile preview is using the desktop-truncated
description, causing mismatched text and mobile overflow warnings; update the
render so SerpSnippetPreview receives a mobile-specific truncated description
when preview.isMobile by using truncateToChars with DESCRIPTION_MOBILE_MAX_CHARS
(or add a mobileDisplayDescription to serpPreviewState) and ensure
getSerpIssues/overflow checks use the same mobile threshold so preview text and
overflow flags (SERP_PREVIEWS, serpPreviewState, truncateToChars,
DESCRIPTION_MOBILE_MAX_CHARS, SerpSnippetPreview) stay in sync.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aebef872-197a-4a04-a45e-3ae626adcb5e

📥 Commits

Reviewing files that changed from the base of the PR and between e89cff4 and 6be382a.

📒 Files selected for processing (6)
  • .changeset/vast-apes-attend.md
  • examples/react/basic/index.html
  • packages/devtools/src/styles/use-styles.ts
  • packages/devtools/src/tabs/seo-tab/index.tsx
  • packages/devtools/src/tabs/seo-tab/serp-preview.tsx
  • packages/devtools/src/tabs/seo-tab/social-previews.tsx

@AlemTuzlak AlemTuzlak merged commit e04bb11 into TanStack:main Mar 30, 2026
10 of 11 checks passed
@github-actions github-actions bot mentioned this pull request Mar 30, 2026
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.

2 participants