Skip to content

feat(seo): implement SEO-friendly report URLs, SSR, and dynamic sitemap#77

Merged
jkondrat merged 1 commit into
SolDevelo:mainfrom
igor-soldev:main
May 26, 2026
Merged

feat(seo): implement SEO-friendly report URLs, SSR, and dynamic sitemap#77
jkondrat merged 1 commit into
SolDevelo:mainfrom
igor-soldev:main

Conversation

@igor-soldev
Copy link
Copy Markdown
Member

This Pull Request introduces a comprehensive SEO overhaul for InfraScan reports. Previously, reports were served strictly as a Single Page Application (SPA) under query parameters (/?scan_id=<uuid>), which prevented search engines from properly crawling and indexing the valuable content within public scans.

This update transitions reports to dedicated, semantic URLs, implements Server-Side Rendering (SSR) specifically tailored for web crawlers, and introduces rich metadata without breaking any existing shared links.

Key Features & Changes

1. SEO-Friendly & Semantic URLs

  • Introduced a new dedicated endpoint @app.route('/report/<path:scan_id>').
  • URLs now dynamically include the sanitized repository name alongside the UUID (e.g., /report/github-soldevelo-infrascan-7a58c6a3...), which increases keyword saturation and organic discoverability.
  • Updated frontend (app.js) to generate these semantic URLs for the "Share Results" functionality and within the "Recent Scans" history list.

2. Bulletproof Backward Compatibility

  • Existing links using /?scan_id=<uuid> are fully supported. The index route acts as an interceptor that reads the scan metadata, resolves the repository name, and performs a native HTTP 301 Moved Permanently redirect to the new canonical URL. No user or existing external link is left behind.

3. Server-Side Rendering (SSR) for Crawlers

  • Created a new templates/report.html (inheriting UI from index).
  • Implemented a <noscript> block inside the #results-content container. This block natively renders the entire report schema (Repository Name, Overall Grades, Cost/Security Findings, and Recommendations) in pure HTML.
  • Googlebot and other crawlers can now extract the full value of the report immediately upon requesting the page, while normal users will seamlessly transition into the interactive JS-powered SPA view.

4. Rich Meta Tags & Structured Data

  • Dynamically injected <title>, <meta name="description">, OpenGraph (og:*), and Twitter Card meta tags into report.html using the report's metadata.
  • Implemented <link rel="canonical" href="..."> pointing directly to the SEO-friendly URL to prevent any duplicate content penalties.
  • Added application/ld+json Schema.org Structured Data (TechArticle and Review) to enable Google Rich Results.

5. Dynamic XML Sitemap

  • Removed the static sitemap.xml file.
  • Introduced a dynamic @app.route('/sitemap.xml') endpoint that yields canonical links to all stored public reports, allowing search engines to discover reports easily.

6. UX Improvements

  • Adjusted frontend logic to ensure UI elements (Tabs, Share Button) render correctly when visiting the new /report/ routes.
  • Clicking the "New Scan" button while viewing a dedicated report will now cleanly redirect the user back to the homepage (/) to begin a new scan flow.

🧪 Testing

  • Backward Compatibility: Visiting /?scan_id=<existing-uuid> properly redirects (301) to the new structure.
  • SSR Validation: Disabling JavaScript in the browser still displays the full textual report via the <noscript> tag.
  • Sitemap Generation: /sitemap.xml successfully lists all available non-private scans.
  • UI Interaction: Standalone report URLs natively display the results, and the "Share Results" feature copies the correct /report/repo-uuid path.

@igor-soldev igor-soldev requested a review from jkondrat May 26, 2026 09:15
@jkondrat jkondrat merged commit a2b6b9a into SolDevelo:main May 26, 2026
1 check passed
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