Skip to content

add SEO#29

Merged
naheel0 merged 5 commits intomainfrom
SEO
Feb 15, 2026
Merged

add SEO#29
naheel0 merged 5 commits intomainfrom
SEO

Conversation

@naheel0
Copy link
Copy Markdown
Member

@naheel0 naheel0 commented Feb 15, 2026

🚀 BΞYTΞFLʘW | Pull Request Protocol

PR Type: (Choose one: feat | fix | refactor | docs | perf)
Issue Link: Fixes #


📝 System Summary

Provide a concise brief of the changes introduced to the stream.

🛠️ Technical Changes

  • Logic change in ...
  • New UI component added: ...
  • Database schema updated: ...

🧪 Quality Assurance (QA)

  • Linting: Code style matches the BeyteFlow grid.
  • Build: npm run build executed without errors.
  • Testing: New logic has been verified and tested.
  • Dark Mode: UI is high-contrast and neon-optimized.

🖼️ Visual Evidence

If this PR affects the UI, drop a screenshot or GIF below:


📡 Developer Authorization

  • I have performed a self-review of my code.
  • My changes generate no new warnings in the console.
  • I have updated the documentation (if applicable).

Authorized by: @naheel0
Timestamp: {{ 15/2/2026}}


@naheel0 naheel0 requested a review from adithyanmkd as a code owner February 15, 2026 11:47
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Feb 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
readme-gen-ai Ready Ready Preview, Comment Feb 15, 2026 0:07am

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 15, 2026

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Dedicated repository generate pages with automatic metadata and titles
    • Interactive generation UI with markdown preview, loading indicator, and error alerts
  • Improvements

    • Pre-populated search field when accessing generate page from repository links
    • Enhanced SEO with Open Graph, Twitter card, robots, and JSON-LD structured data
  • Accessibility

    • Search input includes an accessible label for screen readers

Walkthrough

Adds a client-side GeneratePage component, a server route for dynamic [repo] pages that emits metadata, pre-fills the search input via a new prop, and enriches root layout with expanded SEO/OpenGraph/Twitter metadata and JSON‑LD.

Changes

Cohort / File(s) Summary
Generate page (client/server)
src/app/generate/GeneratePageClient.tsx, src/app/generate/page.tsx, src/app/generate/[repo]/page.tsx
Introduce GeneratePageClient (client component) that manages markdown state and POSTs to /api/generate. Replace previous inline page with a delegating default export. Add [repo]/page.tsx server component which resolves slug and returns dynamic metadata and renders the client with repoSlug.
Search input
src/components/Generator/SearchInput.tsx
Add initialValue?: string and ariaLabel?: string to SearchInputProps; initialize internal state from initialValue and apply aria-label to the input.
Root layout / SEO
src/app/layout.tsx
Replace simple title with metadataBase and a title object, expand description, add Open Graph and Twitter metadata, robots directives, and inject JSON‑LD SoftwareApplication script in head.
Manifest
package.json
Small dependency/manifest update recorded (lines changed).

Sequence Diagram(s)

sequenceDiagram
    participant Browser
    participant GenerateClient as GeneratePageClient
    participant ServerPage as [repo] Server Component
    participant API as /api/generate
    participant Markdown as MarkdownPreview

    Browser->>ServerPage: Request /generate/[repo]
    ServerPage-->>Browser: Render page + metadata (pre-filled repoSlug)
    Browser->>GenerateClient: Mount with repoSlug prop
    GenerateClient->>GenerateClient: set initial input from repoSlug
    Browser->>API: POST /api/generate { url }
    API-->>GenerateClient: 200 { markdown }
    GenerateClient->>Markdown: render markdown
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

area: frontend

Suggested reviewers

  • adithyanmkd

Poem

🐰 I hopped to split server and client with glee,
I seeded metadata, pre-filled a repo key,
I nudged the search input to remember and be,
Now markdown blooms fast — hooray for me! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is a template with placeholder checkboxes and does not provide concrete details about the actual code changes made in this pull request. Replace the template with a clear summary of the actual changes, including the new page structure, metadata additions, and component refactoring performed.
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'add SEO' is vague and does not clearly convey the specific changes made. While SEO improvements are part of the changeset, the title is too generic to meaningfully summarize the main changes. Use a more descriptive title that specifies the key changes, such as 'Add SEO metadata, refactor generate page structure, and improve accessibility' or break the work into focused PRs.
✅ Passed checks (1 passed)
Check name Status Explanation
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SEO

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/app/layout.tsx (2)

65-66: DRY: Extract the duplicated fallback URL into a shared constant.

The fallback "https://readmegen-ai.vercel.app" appears both in the metadataBase (Line 17) and in siteUrl (Line 66). If it ever needs to change, both must be updated in lockstep.

Proposed fix

Add a constant near the top of the file and reference it in both places:

+const SITE_URL =
+  process.env.NEXT_PUBLIC_SITE_URL || "https://readmegen-ai.vercel.app";
+
 export const metadata: Metadata = {
-  metadataBase: new URL(
-    process.env.NEXT_PUBLIC_SITE_URL || "https://readmegen-ai.vercel.app",
-  ),
+  metadataBase: new URL(SITE_URL),
   ...
 };

 export default function RootLayout(...) {
-  const siteUrl =
-    process.env.NEXT_PUBLIC_SITE_URL || "https://readmegen-ai.vercel.app";
+  const siteUrl = SITE_URL;

70-87: dangerouslySetInnerHTML static analysis warning is a false positive here — but consider placing JSON-LD in the body.

The XSS warning from Biome/ast-grep is not a real concern since the JSON-LD content is entirely developer-controlled with no user input. This is the standard Next.js pattern for injecting structured data.

That said, the Next.js App Router docs recommend rendering the JSON-LD <script> tag directly in the component body (inside <body>) rather than in a manual <head> element, as Next.js manages <head> content through the Metadata API.

Proposed fix — move JSON-LD to body
     <html lang="en">
-      <head>
-        {/* JSON-LD structured data */}
-        <script
-          type="application/ld+json"
-          dangerouslySetInnerHTML={{
-            __html: JSON.stringify({
-              "@context": "https://schema.org",
-              "@type": "SoftwareApplication",
-              name: "ReadmeGenAI",
-              applicationCategory: "DeveloperTool",
-              operatingSystem: "Web",
-              description:
-                "AI-powered GitHub README generator that creates markdown documentation automatically.",
-              url: siteUrl,
-            }),
-          }}
-        />
-      </head>
       <body
         className={`${geistSans.variable} ${geistMono.variable} antialiased`}
       >
+        {/* JSON-LD structured data */}
+        <script
+          type="application/ld+json"
+          dangerouslySetInnerHTML={{
+            __html: JSON.stringify({
+              "@context": "https://schema.org",
+              "@type": "SoftwareApplication",
+              name: "ReadmeGenAI",
+              applicationCategory: "DeveloperTool",
+              operatingSystem: "Web",
+              description:
+                "AI-powered GitHub README generator that creates markdown documentation automatically.",
+              url: siteUrl,
+            }),
+          }}
+        />
         {children}
       </body>

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.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/app/generate/`[repo]/page.tsx:
- Around line 4-8: The PageProps/route currently assumes a single path segment
for repo but must be a catch-all to accept owner/repo; rename the route folder
from [repo] to [...repo], change the params type in PageProps to repo: string[]
and in your page/component (and in GeneratePageServer) join params.repo with '/'
to produce the full "owner/repo" string before use; update any
destructuring/usages that expect a string to instead join the array first.
- Around line 4-8: The PageProps interface currently types params as a plain
object but Next.js 15+ provides params as a Promise; update the PageProps
declaration so params is Promise<{ repo: string }>, and also update any related
types for generateMetadata and the page component (e.g., generateMetadata,
default export Page or page function) to accept/await Promise<{ repo: string }>,
ensuring the places where you already await params (around the existing awaits
on lines 14 and 48) match the type signature.

In `@src/app/generate/GeneratePageClient.tsx`:
- Around line 72-77: The SearchInput component is not accepting or forwarding
aria attributes because SearchInputProps only declares onGenerate, isLoading and
initialValue; add an optional ariaLabel (or a generic props spread) to
SearchInputProps and accept it in the SearchInput component, then pass that
value to the underlying input element (e.g., use a prop name like ariaLabel and
apply it as aria-label on the <input> inside SearchInput) so the aria attribute
from GeneratePageClient's SearchInput usage is actually applied.

In `@src/app/layout.tsx`:
- Around line 30-45: Replace hardcoded site URLs so they follow metadataBase: in
src/app/layout.tsx remove or set openGraph.url to "/" (Next resolves it against
metadataBase) instead of "https://readmegen-ai.vercel.app", and update the
JSON-LD url value to use the same env-driven base (metadataBase or
process.env.NEXT_PUBLIC_SITE_URL) + path rather than the hardcoded domain;
ensure both openGraph.url and the JSON-LD `url` reference the single source
(metadataBase / NEXT_PUBLIC_SITE_URL) so custom domains pick up automatically.
🧹 Nitpick comments (4)
src/app/generate/GeneratePageClient.tsx (2)

17-25: document.title override conflicts with Next.js generateMetadata.

The [repo]/page.tsx server component already exports generateMetadata that sets the page title via Next.js's Metadata API. This useEffect will overwrite it on the client after hydration, potentially causing a visible title flicker and duplicating title logic in two places.

Consider removing this useEffect and relying solely on the server-side metadata for SEO titles. If you still need it as a fallback for the non-slug /generate route, limit it to only that case.

Suggested change
-  // Optional: Update document title for SPA navigation
-  useEffect(() => {
-    if (repoSlug) {
-      const repoName = repoSlug.split("/").pop();
-      document.title = `Generate README for ${repoName} | ReadmeGenAI`;
-    } else {
-      document.title = "ReadmeGenAI – AI GitHub README Generator";
-    }
-  }, [repoSlug]);

27-65: Error UX: alert() is jarring; consider inline error display instead.

Using alert() (Line 62) blocks the UI thread and is a poor UX pattern for a polished product. The SearchInput component already has inline error display capability. Consider surfacing generation errors through state that renders inline, similar to how validation errors are shown.

src/app/generate/[repo]/page.tsx (1)

14-24: User-controlled repo param is interpolated into metadata without sanitization.

The repo parameter comes directly from the URL and is interpolated into title, description, and Open Graph fields. While Next.js's Metadata API should escape these values when rendering HTML <meta> tags, consider adding basic validation (e.g., checking the format matches owner/repo with allowed characters) to avoid garbage or malicious values in your metadata.

Also applies to: 46-49

src/app/layout.tsx (1)

67-84: Remove manual <head> wrapper and update JSON-LD configuration per Next.js App Router best practices.

In Next.js App Router, place JSON-LD <script> elements directly in the component body (not wrapped in a manual <head> tag), as Next.js automatically manages the head. Also, update applicationCategory to "DeveloperApplication" (Google's rich results guidance recognizes this value, not "DeveloperTool"), and use the environment variable for consistency with the metadata object already defined in this file.

Suggested refactor
   return (
     <html lang="en">
-      <head>
-        {/* JSON-LD structured data */}
-        <script
-          type="application/ld+json"
-          dangerouslySetInnerHTML={{
-            __html: JSON.stringify({
-              "@context": "https://schema.org",
-              "@type": "SoftwareApplication",
-              name: "ReadmeGenAI",
-              applicationCategory: "DeveloperTool",
-              operatingSystem: "Web",
-              description:
-                "AI-powered GitHub README generator that creates markdown documentation automatically.",
-              url: "https://readmegen-ai.vercel.app",
-            }),
-          }}
-        />
-      </head>
       <body
         className={`${geistSans.variable} ${geistMono.variable} antialiased`}
       >
+        <script
+          type="application/ld+json"
+          dangerouslySetInnerHTML={{
+            __html: JSON.stringify({
+              "@context": "https://schema.org",
+              "@type": "SoftwareApplication",
+              name: "ReadmeGenAI",
+              applicationCategory: "DeveloperApplication",
+              operatingSystem: "Web",
+              description:
+                "AI-powered GitHub README generator that creates markdown documentation automatically.",
+              url: process.env.NEXT_PUBLIC_SITE_URL || "https://readmegen-ai.vercel.app",
+            }),
+          }}
+        />
         {children}
       </body>

@naheel0
Copy link
Copy Markdown
Member Author

naheel0 commented Feb 15, 2026

@copilot
In @src/app/generate/[repo]/page.tsx around lines 4 - 8, The PageProps interface
currently types params as a plain object but Next.js 15+ provides params as a
Promise; update the PageProps declaration so params is Promise<{ repo: string
}>, and also update any related types for generateMetadata and the page
component (e.g., generateMetadata, default export Page or page function) to
accept/await Promise<{ repo: string }>, ensuring the places where you already
await params (around the existing awaits on lines 14 and 48) match the type
signature.

In @src/app/generate/GeneratePageClient.tsx around lines 72 - 77, The
SearchInput component is not accepting or forwarding aria attributes because
SearchInputProps only declares onGenerate, isLoading and initialValue; add an
optional ariaLabel (or a generic props spread) to SearchInputProps and accept it
in the SearchInput component, then pass that value to the underlying input
element (e.g., use a prop name like ariaLabel and apply it as aria-label on the
inside SearchInput) so the aria attribute from GeneratePageClient's
SearchInput usage is actually applied.

In @src/app/layout.tsx around lines 30 - 45, Replace hardcoded site URLs so they
follow metadataBase: in src/app/layout.tsx remove or set openGraph.url to "/"
(Next resolves it against metadataBase) instead of
"https://readmegen-ai.vercel.app", and update the JSON-LD url value to use the
same env-driven base (metadataBase or process.env.NEXT_PUBLIC_SITE_URL) + path
rather than the hardcoded domain; ensure both openGraph.url and the JSON-LD
url reference the single source (metadataBase / NEXT_PUBLIC_SITE_URL) so
custom domains pick up automatically.
fix it

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 15, 2026

@naheel0 I've opened a new pull request, #30, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 2 commits February 15, 2026 12:02
Co-authored-by: naheel0 <191262736+naheel0@users.noreply.github.com>
Fix Next.js 15+ params handling and environment-driven metadata URLs
@naheel0 naheel0 merged commit ed23c96 into main Feb 15, 2026
5 checks passed
@naheel0 naheel0 deleted the SEO branch February 15, 2026 12:14
@coderabbitai coderabbitai bot mentioned this pull request Feb 21, 2026
10 tasks
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