Skip to content

Improve PortalJS template's SEO features #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

Datopian-Shreyas
Copy link
Member

@Datopian-Shreyas Datopian-Shreyas commented Jun 17, 2025

Summary by CodeRabbit

  • New Features
    • Introduced a web app manifest to enable app-like behavior and improved device integration.
    • Added structured data components to enhance SEO and search functionality on the homepage, organizations, search, individual organization, dataset, groups, group individual, and resource pages.
  • Enhancements
    • Updated SEO metadata to reflect the new branding, including revised titles, descriptions, Open Graph, and Twitter card settings.
    • Added additional meta and link tags for improved search engine visibility and device compatibility.
    • Simplified homepage, organizations, search, individual organization, dataset, groups, group individual, and resource page metadata management by consolidating SEO elements into dedicated components.

Copy link

vercel bot commented Jun 17, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
portaljs-cloud-frontend-template ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 19, 2025 2:05pm

Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

Walkthrough

The SEO configuration was extensively revised to reflect the "PortalJS frontend template," updating all metadata, Open Graph, and Twitter card properties. Additional meta and link tags were added for improved semantic coverage. A new web application manifest file was introduced, defining app metadata and icon resources for a more native-like experience. New React components were added to provide structured JSON-LD data for the homepage, organizations, individual organization, dataset, group, search, and resource pages, replacing manual head elements in their respective main page components. Error handling was added when fetching datasets for individual organizations, and dataset page validation was introduced.

Changes

File(s) Change Summary
next-seo.config.js Overhauled SEO config: updated title, description, Open Graph, Twitter card, meta and link tags.
public/site.webmanifest Added new web app manifest with app metadata, theme colors, and icon definition.
components/schema/HomePageStructuredData.tsx Added React component providing multiple JSON-LD structured data elements for homepage SEO.
components/schema/OrganizationPageStructuredData.tsx Added React component providing JSON-LD structured data elements for organizations page SEO.
components/schema/OrganizationIndividualPageStructuredData.tsx Added React component providing JSON-LD structured data elements for individual organization page SEO.
components/schema/DatasetPageStructuredData.tsx Added React component providing JSON-LD structured data elements for dataset page SEO.
components/schema/SearchPageStructuredData.tsx Added React component providing structured data and SEO metadata for search page.
components/schema/GroupPageStructuredData.tsx Added React component providing structured data elements for Groups page SEO.
components/schema/GroupIndividualPageStructuredData.tsx Added React component providing JSON-LD structured data elements for individual group page SEO.
components/schema/ResourcePageStructuredData.tsx Added React component providing structured data and SEO metadata for resource page.
pages/index.tsx Removed manual <Head> metadata; added <HomePageStructuredData /> component to embed structured data.
pages/organizations.tsx Removed manual <Head> metadata; added <OrganizationPageStructuredData /> component for SEO data.
pages/search.tsx Removed manual <Head> metadata; added <SearchPageStructuredData /> component for SEO data.
pages/groups/index.tsx Removed manual <Head> metadata; added <GroupPageStructuredData /> component for SEO data.
pages/[org]/index.tsx Added error handling when fetching datasets; replaced manual <Head> metadata with <OrganizationIndividualPageStructuredData />.
pages/[org]/[dataset]/index.tsx Added validation to ensure dataset org matches URL org; replaced manual <Head> metadata with <DatasetPageStructuredData />.
pages/[org]/[dataset]/r/[resourceId].tsx Removed manual <Head> metadata; added <ResourcePageStructuredData /> component for SEO data.
pages/groups/[groupName].tsx Removed manual <Head> metadata; added <GroupIndividualPageStructuredData /> component for SEO data.

Poem

In the meadow of metadata, I hop with glee,
New titles and icons for all to see!
PortalJS shines with a manifest bright,
SEO bunnies dance in the moonlight.
With every tag and favicon in place,
This frontend template wins the race!
🥕✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-19T14_06_07_059Z-debug-0.log


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a49b231 and 634245b.

📒 Files selected for processing (1)
  • components/schema/GroupIndividualPageStructuredData.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/schema/GroupIndividualPageStructuredData.tsx
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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)
next-seo.config.js (1)

47-57: Redundant meta tags – Next-SEO already outputs them

og:image:width, og:image:height, and og:locale are automatically emitted
from openGraph.images and openGraph.locale. Duplicating them clutters the
head and can confuse parsers if values diverge in future edits.
Consider pruning these three entries from additionalMetaTags.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4aa231b and 974340e.

⛔ Files ignored due to path filters (3)
  • public/apple-touch-icon.png is excluded by !**/*.png
  • public/favicon.ico is excluded by !**/*.ico
  • public/images/portaljs-frontend.png is excluded by !**/*.png
📒 Files selected for processing (2)
  • next-seo.config.js (1 hunks)
  • public/site.webmanifest (1 hunks)
🔇 Additional comments (1)
next-seo.config.js (1)

60-72: Verify that the manifest link path matches build output

The link tag points to /site.webmanifest, which is fine as long as the file
lives under public/ (Next.js copies it to the root). If the location changes,
adjust the href accordingly.

Comment on lines +4 to +14
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3F59B1",
"icons": [
{
"src": "/apple-touch-icon.png",
"sizes": "180x180",
"type": "image/png"
}
]
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add larger & maskable icons + scope for full PWA compliance

Lighthouse will flag the manifest because it only declares a 180×180 icon. Modern browsers expect at least one 192×192 and one 512×512 icon marked purpose: "any maskable".
Adding a "scope" (usually the same as start_url) avoids fallback to the origin root when the user navigates.

   "start_url": "/",
+  "scope": "/",
   "display": "standalone",
   "background_color": "#ffffff",
   "theme_color": "#3F59B1",
   "icons": [
+    {
+      "src": "/android-chrome-192x192.png",
+      "sizes": "192x192",
+      "type": "image/png",
+      "purpose": "any maskable"
+    },
+    {
+      "src": "/android-chrome-512x512.png",
+      "sizes": "512x512",
+      "type": "image/png",
+      "purpose": "any maskable"
+    },
     {
       "src": "/apple-touch-icon.png",
       "sizes": "180x180",
       "type": "image/png"
     }
   ]
📝 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
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3F59B1",
"icons": [
{
"src": "/apple-touch-icon.png",
"sizes": "180x180",
"type": "image/png"
}
]
"start_url": "/",
"scope": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#3F59B1",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "/apple-touch-icon.png",
"sizes": "180x180",
"type": "image/png"
}
]
🤖 Prompt for AI Agents
In public/site.webmanifest around lines 4 to 14, the manifest currently only
includes a 180x180 icon and lacks a scope property. To fix this, add additional
icons with sizes 192x192 and 512x512, each including the property "purpose":
"any maskable" to support modern PWA requirements. Also, add a "scope" property
with the same value as "start_url" ("/") to define the navigation scope and
avoid fallback to the origin root.

Comment on lines 7 to 8
const url = "https://portaljs-cloud-frontend-template.vercel.app/";
const imageUrl = `${url}images/portaljs-frontend.png`;
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

Fix double-slash bug in generated imageUrl and canonical URL

Because url already ends with /, interpolating ${url}images/... produces
…vercel.app//images/… (note the double slash), which some crawlers treat as a
different asset. Remove the trailing slash or add it when concatenating.

-const url = "https://portaljs-cloud-frontend-template.vercel.app/";
-const imageUrl = `${url}images/portaljs-frontend.png`;
+const url = "https://portaljs-cloud-frontend-template.vercel.app";
+const imageUrl = `${url}/images/portaljs-frontend.png`;

Remember to update canonical and openGraph.url to use the amended url.

📝 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 url = "https://portaljs-cloud-frontend-template.vercel.app/";
const imageUrl = `${url}images/portaljs-frontend.png`;
// next-seo.config.js
- const url = "https://portaljs-cloud-frontend-template.vercel.app/";
- const imageUrl = `${url}images/portaljs-frontend.png`;
+ const url = "https://portaljs-cloud-frontend-template.vercel.app";
+ const imageUrl = `${url}/images/portaljs-frontend.png`;
// Don't forget to update `canonical` and `openGraph.url` to use the new `url` constant.
🤖 Prompt for AI Agents
In next-seo.config.js around lines 7 to 8, the base URL ends with a trailing
slash causing double slashes when concatenated with paths, leading to incorrect
URLs. Remove the trailing slash from the `url` constant or adjust the
concatenation to avoid double slashes. Also, update the `canonical` and
`openGraph.url` fields to use the corrected base URL without the trailing slash
to ensure consistent and correct URLs throughout the configuration.

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: 0

🧹 Nitpick comments (2)
pages/index.tsx (1)

2-2: Remove unused import.

The Head import from next/head is no longer needed since SEO metadata is now handled by the HomePageStructuredData component.

-import Head from "next/head";
components/schema/HomePageStructuredData.tsx (1)

7-10: Ensure URL consistency in structured data.

There's an inconsistency in URL usage: nextSeoConfig.canonical for the url prop and ${url}/favicon.ico for the logo prop. Consider using the same base URL reference for consistency.

       <LogoJsonLd
-        url={nextSeoConfig.canonical}
+        url={url}
         logo={`${url}/favicon.ico`}
       />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b779116 and 92a0ae8.

📒 Files selected for processing (3)
  • components/schema/HomePageStructuredData.tsx (1 hunks)
  • next-seo.config.js (1 hunks)
  • pages/index.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • next-seo.config.js
🧰 Additional context used
🧬 Code Graph Analysis (2)
components/schema/HomePageStructuredData.tsx (1)
next-seo.config.js (2)
  • url (7-7)
  • url (7-7)
pages/index.tsx (1)
components/schema/HomePageStructuredData.tsx (1)
  • HomePageStructuredData (4-40)
🔇 Additional comments (3)
pages/index.tsx (1)

8-8: Excellent SEO consolidation approach!

Great architectural decision to centralize SEO metadata and structured data into a dedicated component. This improves maintainability and ensures consistent SEO implementation across the application.

Also applies to: 43-43

components/schema/HomePageStructuredData.tsx (2)

4-40: Comprehensive structured data implementation!

Excellent implementation of JSON-LD structured data covering multiple SEO aspects:

  • Logo and branding information
  • Breadcrumb navigation
  • Webpage metadata
  • Site search functionality

This will significantly improve the site's SEO performance and search engine understanding.


29-37: Verify the search endpoint exists.

The SiteLinksSearchBoxJsonLd assumes a search endpoint at /search?q={search_term_string}. Ensure this search route is implemented in your application.

#!/bin/bash
# Description: Check if search endpoint/page exists in the codebase
# Expected: Find search page implementation or API route

# Search for search-related pages and API routes
fd -e tsx -e ts -e js | xargs rg -l "search.*query|q.*search" | head -10

# Look for search page specifically
fd -t f -e tsx -e ts "search" pages/

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: 0

🧹 Nitpick comments (1)
pages/organizations.tsx (1)

1-1: Remove unused import.

The Head import from "next/head" is no longer needed since the explicit <Head> components have been replaced with the structured data component.

-import Head from "next/head";
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 92a0ae8 and 417d2eb.

📒 Files selected for processing (3)
  • components/schema/HomePageStructuredData.tsx (1 hunks)
  • components/schema/OrganizationPageStructuredData.tsx (1 hunks)
  • pages/organizations.tsx (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/schema/OrganizationPageStructuredData.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/schema/HomePageStructuredData.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
pages/organizations.tsx (1)
components/schema/OrganizationPageStructuredData.tsx (1)
  • OrganizationPageStructuredData (4-50)
🔇 Additional comments (2)
pages/organizations.tsx (2)

9-9: Excellent SEO improvement with structured data component.

The addition of OrganizationPageStructuredData component is a great improvement for SEO. This provides comprehensive structured data markup including JSON-LD, breadcrumbs, and other SEO metadata in a consistent and maintainable way.

Also applies to: 28-28


28-28: ```shell
#!/bin/bash

Locate and display next-seo.config files to verify exports of url and nextSeoConfig

echo "Searching for next-seo.config.* files at project root..."
find . -maxdepth 1 -type f -name "next-seo.config.*"

echo -e "\nDisplaying contents of found config file(s) (up to 200 lines each)..."
for file in $(find . -maxdepth 1 -type f -name "next-seo.config.*"); do
echo "==== $file ===="
sed -n '1,200p' "$file"
done


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

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: 0

🧹 Nitpick comments (2)
pages/search.tsx (1)

2-2: Remove unused import.

The Head import from next/head is no longer used since SEO metadata is now handled by the SearchPageStructuredData component.

-import Head from "next/head";
components/schema/SearchPageStructuredData.tsx (1)

6-7: Improve title and description for better SEO.

The current title "Search page" is generic and the description concatenation creates awkward phrasing ("Browse through multiple datasets available on Search page").

Consider this improvement:

-const title = "Search page"
-const description = "Browse through multiple datasets available on " + title
+const title = "Search Datasets"
+const description = "Browse and search through our comprehensive collection of datasets"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 417d2eb and 3ebfdd6.

📒 Files selected for processing (3)
  • components/schema/OrganizationPageStructuredData.tsx (1 hunks)
  • components/schema/SearchPageStructuredData.tsx (1 hunks)
  • pages/search.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/schema/OrganizationPageStructuredData.tsx
🧰 Additional context used
🧬 Code Graph Analysis (2)
pages/search.tsx (1)
components/schema/SearchPageStructuredData.tsx (1)
  • SearchPageStructuredData (5-57)
components/schema/SearchPageStructuredData.tsx (1)
next-seo.config.js (2)
  • title (3-3)
  • description (4-5)
🪛 Biome (1.9.4)
components/schema/SearchPageStructuredData.tsx

[error] 44-44: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (8)
pages/search.tsx (2)

13-13: LGTM! Good architectural improvement.

The import of SearchPageStructuredData component centralizes SEO metadata management, which improves maintainability and consistency.


50-50: LGTM! Proper structured data integration.

The placement of SearchPageStructuredData at the top level of the component is correct for SEO metadata injection.

components/schema/SearchPageStructuredData.tsx (6)

8-14: LGTM! Proper JSON-LD structure for DataCatalog.

The JSON-LD object correctly implements the schema.org DataCatalog specification with appropriate context, type, and metadata properties.


17-20: LGTM! Correct logo structured data implementation.

The LogoJsonLd component properly associates the logo with the search page URL for enhanced SEO.


21-26: LGTM! Well-configured NextSeo component.

The NextSeo configuration properly sets canonical URL, title, description, and spreads the shared SEO config for consistency.


27-40: LGTM! Proper breadcrumb structured data.

The BreadcrumbJsonLd correctly defines the navigation hierarchy with proper position indices and item URLs.


41-45: Acknowledge legitimate use of dangerouslySetInnerHTML for JSON-LD.

The static analysis tool flagged the use of dangerouslySetInnerHTML, but this is a legitimate and standard practice for injecting JSON-LD structured data. The content is controlled (not user-generated) and properly JSON-stringified, making it safe from XSS attacks.

The implementation follows established patterns for structured data injection and poses no security risk in this context.


46-54: LGTM! Excellent site search box implementation.

The SiteLinksSearchBoxJsonLd properly configures the search functionality with the correct URL pattern and query parameter mapping for enhanced search engine integration.

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: 3

🧹 Nitpick comments (1)
components/schema/OrganizationIndividualPageStructuredData.tsx (1)

20-31: Consider adding the current organization to breadcrumbs.

The breadcrumb structure only shows Home → Organizations, but it should include the current organization as the final item for better navigation context.

Apply this diff to add the current organization to breadcrumbs:

       <BreadcrumbJsonLd
         itemListElements={[
           {
             position: 1,
             name: 'Home',
             item: url,
           },
           {
             position: 2,
             name: 'Organizations',
             item: `${url}/organizations`,
           },
+          {
+            position: 3,
+            name: title,
+            item: orgUrl,
+          },
         ]}
       />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3ebfdd6 and 61bf865.

📒 Files selected for processing (2)
  • components/schema/OrganizationIndividualPageStructuredData.tsx (1 hunks)
  • pages/[org]/index.tsx (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
components/schema/OrganizationIndividualPageStructuredData.tsx (1)
next-seo.config.js (2)
  • title (3-3)
  • description (4-5)
🔇 Additional comments (3)
pages/[org]/index.tsx (3)

15-15: LGTM! Good SEO architecture improvement.

The import of the structured data component aligns with the PR's objective to improve SEO features by centralizing metadata management.


32-50: Excellent error handling implementation.

The try-catch blocks around dataset fetching prevent the page from breaking when individual datasets fail to load, and filtering out null values ensures only valid datasets are passed to the component.


88-88: Good replacement of manual Head elements.

Using the structured data component centralizes SEO metadata management and provides consistent JSON-LD markup across the application.

return (
<>
<LogoJsonLd
url={`${url}/@${title}`}
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

URL construction needs proper encoding and correction.

Multiple issues with URL construction:

  1. Using title directly in URLs without encoding can cause issues if the title contains special characters
  2. The breadcrumb Organizations URL is incorrect - should point to /organizations not /@${title}

Apply this diff to fix URL construction:

+  const encodedOrgName = encodeURIComponent(org.name || org.title || '')
+  const orgUrl = `${url}/@${encodedOrgName}`
+
   return (
     <>
       <LogoJsonLd
-        url={`${url}/@${title}`}
+        url={orgUrl}
         logo={org.image_display_url || `${url}/favicon.ico`}
       />
       <NextSeo
-        canonical={`${url}/@${title}`}
+        canonical={orgUrl}
         title={title}
         description={description}
         {...nextSeoConfig}
       />
       <BreadcrumbJsonLd
         itemListElements={[
           {
             position: 1,
             name: 'Home',
             item: url,
           },
           {
             position: 2,
             name: 'Organizations',
-            item: `${url}/@${title}`,
+            item: `${url}/organizations`,
           },
         ]}
       />
       <WebPageJsonLd
-        id={`${url}/@${title}#webpage`}
-        url={`${url}/@${title}`}
+        id={`${orgUrl}#webpage`}
+        url={orgUrl}
         name={title}
         description={description}
       />

Also applies to: 14-14, 29-29, 34-35

🤖 Prompt for AI Agents
In components/schema/OrganizationIndividualPageStructuredData.tsx at lines 10,
14, 29, and 34-35, the URL construction uses the raw title without encoding and
incorrectly sets the Organizations breadcrumb URL. Fix this by encoding the
title using encodeURIComponent before inserting it into URLs and correct the
Organizations breadcrumb URL to point to '/organizations' instead of using the
title.

Comment on lines 5 to 6
const title = org.name || org.title
const description = org.notes || "Organizations page of " + org
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

Fix title logic and description fallback.

The current implementation has two issues:

  1. Using org.name || org.title may not be optimal for SEO titles
  2. The description fallback will stringify the org object as "[object Object]"

Apply this diff to fix both issues:

-  const title = org.name || org.title
-  const description = org.notes || "Organizations page of " + org
+  const title = org.title || org.name || 'Organization'
+  const description = org.notes || `Learn more about ${org.title || org.name || 'this organization'} and explore their datasets.`
📝 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 title = org.name || org.title
const description = org.notes || "Organizations page of " + org
const title = org.title || org.name || 'Organization'
const description = org.notes || `Learn more about ${org.title || org.name || 'this organization'} and explore their datasets.`
🤖 Prompt for AI Agents
In components/schema/OrganizationIndividualPageStructuredData.tsx around lines 5
to 6, the title logic uses org.name || org.title which may not be optimal for
SEO, and the description fallback concatenates a string with the org object
causing it to stringify as "[object Object]". Fix this by prioritizing org.title
over org.name for the title, and update the description fallback to use a
meaningful string such as "Organizations page of " plus org.title or org.name
instead of the org object directly.

import nextSeoConfig, { url } from "@/next-seo.config";
import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, WebPageJsonLd, SiteLinksSearchBoxJsonLd } from "next-seo";

export function OrganizationIndividualPageStructuredData({ org }) {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add TypeScript types for better type safety.

The org parameter lacks type definitions, which reduces type safety and IDE support.

Apply this diff to add proper typing:

-export function OrganizationIndividualPageStructuredData({ org }) {
+interface Organization {
+  name?: string;
+  title?: string;
+  notes?: string;
+  image_display_url?: string;
+}
+
+export function OrganizationIndividualPageStructuredData({ org }: { org: Organization }) {
📝 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
export function OrganizationIndividualPageStructuredData({ org }) {
interface Organization {
name?: string;
title?: string;
notes?: string;
image_display_url?: string;
}
export function OrganizationIndividualPageStructuredData({ org }: { org: Organization }) {
🤖 Prompt for AI Agents
In components/schema/OrganizationIndividualPageStructuredData.tsx at line 4, the
org parameter lacks TypeScript type definitions, reducing type safety and IDE
support. Define an appropriate interface or type for the org parameter
reflecting its expected structure, then update the function signature to include
this type for org. This will improve type safety and developer experience.

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: 5

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61bf865 and 3abf4c4.

📒 Files selected for processing (3)
  • components/schema/DatasetPageStructuredData.tsx (1 hunks)
  • components/schema/OrganizationIndividualPageStructuredData.tsx (1 hunks)
  • pages/[org]/[dataset]/index.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/schema/OrganizationIndividualPageStructuredData.tsx
🧰 Additional context used
🧬 Code Graph Analysis (2)
pages/[org]/[dataset]/index.tsx (1)
components/schema/DatasetPageStructuredData.tsx (1)
  • DatasetPageStructuredData (4-42)
components/schema/DatasetPageStructuredData.tsx (1)
next-seo.config.js (2)
  • title (3-3)
  • description (4-5)
🔇 Additional comments (2)
pages/[org]/[dataset]/index.tsx (2)

91-91: Excellent refactoring to centralize SEO metadata.

The replacement of manual Head elements with the structured data component improves maintainability and consistency across the application.


44-48: Consider URL encoding consistency in organization name validation.

The validation compares the raw organization name with the URL parameter, but URL parameters are typically encoded. This could cause mismatches if the organization name contains special characters.

Run the following script to check how organization names with special characters are handled in the routing:

#!/bin/bash
# Description: Check for organization names with special characters and URL encoding patterns
# Expected: Find examples of how organization names are encoded in URLs

# Search for organization name usage in routing or URL construction
rg -A 3 -B 3 "org.*name.*encodeURI|encodeURI.*org.*name" 

# Search for organization parameter handling
rg -A 5 -B 5 "params.*org|org.*params"

# Look for existing URL encoding patterns in the codebase
rg -A 3 "encodeURIComponent|decodeURIComponent"

return (
<>
<LogoJsonLd
url={`${url}/@${owner_org}/${title}`}
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

Implement URL encoding for title to prevent invalid URLs.

The title variable is directly used in URL construction without encoding, which could create invalid URLs if the title contains special characters or spaces.

+  const encodedTitle = encodeURIComponent(title);
+  const encodedOwnerOrg = encodeURIComponent(owner_org);
+  const datasetUrl = `${url}/@${encodedOwnerOrg}/${encodedTitle}`;

-        url={`${url}/@${owner_org}/${title}`}
+        url={datasetUrl}
-        canonical={`${url}/@${owner_org}/${title}`}
+        canonical={datasetUrl}
-            item: `${url}/@${owner_org}/${title}`
+            item: datasetUrl
-        id={`${url}/@${owner_org}/${title}#webpage`}
-        url={`${url}/@${owner_org}/${title}`}
+        id={`${datasetUrl}#webpage`}
+        url={datasetUrl}

Also applies to: 15-15, 30-30, 35-36

🤖 Prompt for AI Agents
In components/schema/DatasetPageStructuredData.tsx at lines 11, 15, 30, and
35-36, the title variable is used directly in URL construction without encoding,
which can cause invalid URLs if the title contains special characters or spaces.
Fix this by applying URL encoding (e.g., using encodeURIComponent) to the title
variable wherever it is included in the URL string to ensure the URLs are valid
and safe.

import nextSeoConfig, { url } from "@/next-seo.config";
import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, WebPageJsonLd, SiteLinksSearchBoxJsonLd, DatasetJsonLd } from "next-seo";

export function DatasetPageStructuredData({ dataset }) {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add TypeScript interface for better type safety.

The component lacks proper TypeScript typing for the dataset prop, which could lead to runtime errors if the expected properties are missing.

+interface Dataset {
+  title?: string;
+  name: string;
+  notes?: string;
+  organization: {
+    name: string;
+  };
+}
+
+interface DatasetPageStructuredDataProps {
+  dataset: Dataset;
+}
+
-export function DatasetPageStructuredData({ dataset }) {
+export function DatasetPageStructuredData({ dataset }: DatasetPageStructuredDataProps) {
📝 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
export function DatasetPageStructuredData({ dataset }) {
interface Dataset {
title?: string;
name: string;
notes?: string;
organization: {
name: string;
};
}
interface DatasetPageStructuredDataProps {
dataset: Dataset;
}
-export function DatasetPageStructuredData({ dataset }) {
+export function DatasetPageStructuredData({ dataset }: DatasetPageStructuredDataProps) {
// …rest of component
}
🤖 Prompt for AI Agents
In components/schema/DatasetPageStructuredData.tsx at line 4, the
DatasetPageStructuredData component lacks TypeScript typing for its dataset
prop. Define a TypeScript interface describing the expected shape of the dataset
object with all required properties, then update the component's props to use
this interface for type safety and to prevent runtime errors.

Comment on lines +44 to +48
if ("@" + dataset.organization.name !== orgName) {
return {
notFound: true,
};
}
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

Add null safety for organization property access.

The validation assumes dataset.organization.name exists without checking if dataset.organization is null or undefined, which could cause a runtime error.

-    if ("@" + dataset.organization.name !== orgName) {
+    if (!dataset.organization || "@" + dataset.organization.name !== orgName) {
       return {
         notFound: true,
       };
     }
📝 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
if ("@" + dataset.organization.name !== orgName) {
return {
notFound: true,
};
}
if (!dataset.organization || "@" + dataset.organization.name !== orgName) {
return {
notFound: true,
};
}
🤖 Prompt for AI Agents
In pages/[org]/[dataset]/index.tsx around lines 44 to 48, the code accesses
dataset.organization.name without verifying if dataset.organization is null or
undefined, risking a runtime error. Add a null check to ensure
dataset.organization exists before accessing its name property, and handle the
case where it does not by returning notFound or an appropriate fallback.

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: 0

🧹 Nitpick comments (1)
pages/groups/index.tsx (1)

1-1: Remove unused import.

Based on the AI summary, the explicit <Head> component was removed and replaced with the structured data component, making this import unused.

-import Head from "next/head";
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3abf4c4 and e38930e.

📒 Files selected for processing (3)
  • components/schema/DatasetPageStructuredData.tsx (1 hunks)
  • components/schema/GroupPageStructuredData.tsx (1 hunks)
  • pages/groups/index.tsx (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • components/schema/GroupPageStructuredData.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/schema/DatasetPageStructuredData.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
pages/groups/index.tsx (1)
components/schema/GroupPageStructuredData.tsx (1)
  • GroupPageStructuredData (4-50)
🔇 Additional comments (1)
pages/groups/index.tsx (1)

10-10: LGTM! Well-structured SEO implementation.

The addition of GroupPageStructuredData component follows the established pattern for centralizing SEO metadata and JSON-LD markup. The component provides comprehensive structured data including logo, breadcrumbs, webpage metadata, and site links search box, which should improve the page's SEO performance.

Also applies to: 29-29

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 (3)
pages/[org]/[dataset]/r/[resourceId].tsx (1)

10-10: Remove unused import.

The Head import from "next/head" is no longer used after switching to the structured data component.

-import Head from "next/head";
pages/groups/[groupName].tsx (1)

2-2: Remove unused import.

The Head import is no longer needed after the structured data refactoring.

-import Head from "next/head";
components/schema/ResourcePageStructuredData.tsx (1)

2-2: Remove unused import.

DatasetJsonLd is imported but not used in this component.

-import { BreadcrumbJsonLd, LogoJsonLd, NextSeo, DatasetJsonLd } from "next-seo";
+import { BreadcrumbJsonLd, LogoJsonLd, NextSeo } from "next-seo";
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e38930e and 41f9399.

📒 Files selected for processing (5)
  • components/schema/DatasetPageStructuredData.tsx (1 hunks)
  • components/schema/GroupIndividualPageStructuredData.tsx (1 hunks)
  • components/schema/ResourcePageStructuredData.tsx (1 hunks)
  • pages/[org]/[dataset]/r/[resourceId].tsx (2 hunks)
  • pages/groups/[groupName].tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • components/schema/DatasetPageStructuredData.tsx
🧰 Additional context used
🧬 Code Graph Analysis (4)
pages/[org]/[dataset]/r/[resourceId].tsx (1)
components/schema/ResourcePageStructuredData.tsx (1)
  • ResourcePageStructuredData (5-63)
pages/groups/[groupName].tsx (1)
components/schema/GroupIndividualPageStructuredData.tsx (1)
  • GroupIndividualPageStructuredData (4-47)
components/schema/GroupIndividualPageStructuredData.tsx (1)
next-seo.config.js (2)
  • title (3-3)
  • description (4-5)
components/schema/ResourcePageStructuredData.tsx (1)
next-seo.config.js (2)
  • title (3-3)
  • description (4-5)
🪛 Biome (1.9.4)
components/schema/ResourcePageStructuredData.tsx

[error] 59-59: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (10)
pages/[org]/[dataset]/r/[resourceId].tsx (2)

14-14: LGTM! Clean import structure.

The import of ResourcePageStructuredData is correctly added to support the SEO refactoring.


83-83: Excellent SEO enhancement!

The replacement of manual <Head> metadata with the structured data component centralizes SEO metadata management and adds rich JSON-LD schema markup for better search engine visibility.

pages/groups/[groupName].tsx (2)

14-14: LGTM! Proper import for structured data.

The import aligns with the SEO refactoring pattern across the application.


73-73: Great SEO improvement!

Replacing manual head metadata with the structured data component provides better SEO and rich results support.

components/schema/GroupIndividualPageStructuredData.tsx (2)

4-8: LGTM! Well-structured component design.

The component properly constructs URLs, titles, and descriptions from the group props and follows the established pattern for structured data components.


10-44: Excellent structured data implementation!

The component properly implements LogoJsonLd, NextSeo, BreadcrumbJsonLd, and WebPageJsonLd for comprehensive SEO support.

components/schema/ResourcePageStructuredData.tsx (4)

5-8: LGTM! Clean component structure.

The component properly constructs resource-specific URLs and descriptions from the props.


10-17: Excellent DataDownload schema implementation!

The JSON-LD structure correctly represents the resource as a DataDownload with appropriate Schema.org properties.


21-54: Comprehensive SEO implementation!

The component properly implements LogoJsonLd, NextSeo, and BreadcrumbJsonLd with correct URL structures and navigation hierarchy.


55-60: I’ll locate and inspect the actual page file that passes resource into this component to see how it’s fetched and whether any sanitization is applied:

#!/bin/bash
set -e

# Find the page importing ResourcePageStructuredData
PAGE=$(rg -l "ResourcePageStructuredData" -g "*.tsx" | grep "pages/" | head -n1)
echo "Inspecting page: $PAGE"

echo; echo "---- Top of File (1–200) ----"
sed -n '1,200p' "$PAGE"

echo; echo "---- Data-Fetching Functions ----"
rg -n "export async function get" -A5 "$PAGE"

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: 1

🧹 Nitpick comments (1)
components/schema/ResourcePageStructuredData.tsx (1)

55-60: Address the security concern with dangerouslySetInnerHTML.

While the static analysis tool flagged this as a security risk, the JSON.stringify usage with controlled data should be safe. However, consider using the DatasetJsonLd component from next-seo for consistency.

Since you're already importing DatasetJsonLd (line 2) but not using it, consider replacing the custom Script with the next-seo component:

-      <Script
-        id="datadownload-jsonld"
-        type="application/ld+json"
-        strategy="afterInteractive"
-        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
-      />
+      <DatasetJsonLd
+        name={resource.name}
+        description={description}
+        images={[]}
+      />

Alternatively, if you need the DataDownload schema specifically, add input sanitization:

-        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
+        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, '\\u003c') }}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 41f9399 and a49b231.

📒 Files selected for processing (6)
  • components/schema/DatasetPageStructuredData.tsx (1 hunks)
  • components/schema/GroupIndividualPageStructuredData.tsx (1 hunks)
  • components/schema/GroupPageStructuredData.tsx (1 hunks)
  • components/schema/OrganizationIndividualPageStructuredData.tsx (1 hunks)
  • components/schema/OrganizationPageStructuredData.tsx (1 hunks)
  • components/schema/ResourcePageStructuredData.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • components/schema/GroupPageStructuredData.tsx
  • components/schema/GroupIndividualPageStructuredData.tsx
  • components/schema/DatasetPageStructuredData.tsx
  • components/schema/OrganizationPageStructuredData.tsx
  • components/schema/OrganizationIndividualPageStructuredData.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
components/schema/ResourcePageStructuredData.tsx (1)
next-seo.config.js (2)
  • title (3-3)
  • description (4-5)
🪛 Biome (1.9.4)
components/schema/ResourcePageStructuredData.tsx

[error] 59-59: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (3)
components/schema/ResourcePageStructuredData.tsx (3)

1-3: LGTM! Clean and appropriate imports.

The imports are well-structured and include all necessary dependencies for the SEO and structured data functionality.


10-17: Well-structured JSON-LD schema implementation.

The DataDownload schema follows schema.org specifications correctly and includes appropriate properties for a resource download. The structure aligns well with SEO best practices.


19-54: Excellent use of next-seo components for structured data.

The implementation correctly uses LogoJsonLd, NextSeo, and BreadcrumbJsonLd components with proper hierarchical breadcrumb structure. The canonical URL and SEO metadata configuration is well-implemented.

Comment on lines +5 to +8
export function ResourcePageStructuredData({ resource, orgName, dataset }) {
const title = resource.name || "Resource"
const resourceUrl = `${url}/@${orgName}/${dataset}/r/${resource.id}`
const description = resource.description || "Resource page of " + title
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add TypeScript type definitions for better type safety.

The component props lack TypeScript type definitions, which could lead to runtime errors and reduces developer experience.

Consider adding interface definitions:

+interface ResourcePageStructuredDataProps {
+  resource: {
+    id: string;
+    name?: string;
+    description?: string;
+    format?: string;
+    url?: string;
+  };
+  orgName: string;
+  dataset: string;
+}
+
-export function ResourcePageStructuredData({ resource, orgName, dataset }) {
+export function ResourcePageStructuredData({ resource, orgName, dataset }: ResourcePageStructuredDataProps) {
📝 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
export function ResourcePageStructuredData({ resource, orgName, dataset }) {
const title = resource.name || "Resource"
const resourceUrl = `${url}/@${orgName}/${dataset}/r/${resource.id}`
const description = resource.description || "Resource page of " + title
interface ResourcePageStructuredDataProps {
resource: {
id: string;
name?: string;
description?: string;
format?: string;
url?: string;
};
orgName: string;
dataset: string;
}
export function ResourcePageStructuredData(
{ resource, orgName, dataset }: ResourcePageStructuredDataProps
) {
const title = resource.name || "Resource"
const resourceUrl = `${url}/@${orgName}/${dataset}/r/${resource.id}`
const description = resource.description || "Resource page of " + title
// …rest of the function
}
🤖 Prompt for AI Agents
In components/schema/ResourcePageStructuredData.tsx around lines 5 to 8, the
component props are missing TypeScript type definitions, which reduces type
safety. Define an interface for the props specifying the types for resource,
orgName, and dataset, then update the function signature to use this interface
for better type checking and developer experience.

@Datopian-Shreyas Datopian-Shreyas changed the title [WIP]: Improve PortalJS template's SEO features Improve PortalJS template's SEO features Jun 19, 2025
@anuveyatsu
Copy link
Member

@Datopian-Shreyas I'm not sure if this is working as expected. I have tested preview deployment using Google's rish results tester and on number of pages it doesn't show any structured data except the breadcrumb, for example, see resource page result:

https://search.google.com/test/rich-results/result?id=PB_Grxz1y6s7MCe5BLrv4g

Similarly, I tested using meta tags tool for dataset page this time and I would expect to see title and description of the dataset but it uses generic meta title and description:

https://metatags.io/?url=https%3A%2F%2Fportaljs-cloud-frontend-template-git-seo-impro-06c6c1-datopian1.vercel.app%2F%40datopian%2Ftiny_20resource

@Datopian-Shreyas
Copy link
Member Author

@Datopian-Shreyas I'm not sure if this is working as expected. I have tested preview deployment using Google's rish results tester and on number of pages it doesn't show any structured data except the breadcrumb, for example, see resource page result:

https://search.google.com/test/rich-results/result?id=PB_Grxz1y6s7MCe5BLrv4g

Similarly, I tested using meta tags tool for dataset page this time and I would expect to see title and description of the dataset but it uses generic meta title and description:

https://metatags.io/?url=https%3A%2F%2Fportaljs-cloud-frontend-template-git-seo-impro-06c6c1-datopian1.vercel.app%2F%40datopian%2Ftiny_20resource

Hey @anuveyatsu, Im not sure why this is happening..
I will check this out.

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