Skip to content

bug: Landing page (app/page.tsx) is entirely a client component — prevents SSR, page-level metadata, and hurts SEO #2140

@nyxsky404

Description

@nyxsky404

Description

The landing page (app/page.tsx) is marked with 'use client' at the very top, making the entire page a client component. In Next.js App Router, this has significant consequences:

  1. No page-specific metadata export — Next.js only allows export const metadata (or generateMetadata) in Server Components. The landing page cannot define its own title, description, or Open Graph tags. It relies entirely on the generic root layout.tsx metadata.

  2. No server-side rendering of page content — The hero text, feature cards, step guides, and all static content are rendered client-side. Search engine crawlers see an empty shell until JavaScript executes.

  3. Larger JavaScript bundle — All static text content (headings, descriptions, step guides) is shipped as JavaScript rather than pre-rendered HTML.

  4. Worse Core Web Vitals — LCP (Largest Contentful Paint) is delayed because the main heading text isn't in the initial HTML response.

// app/page.tsx line 1:
'use client';  // ← Makes the ENTIRE landing page a client component

// This means you CANNOT do:
// export const metadata = { title: "CommitPulse | ...", ... }

File: app/page.tsx

The root layout.tsx does define metadata, but it's generic and shared across all pages. The landing page should be able to define its own specific metadata for optimal SEO.

Steps to Reproduce

  1. View the page source of the deployed landing page (View Source or curl https://commitpulse.vercel.app)
  2. Observe that the <body> contains minimal HTML — the hero heading, feature cards, and all content are missing from the initial HTML
  3. Check that there is no page-specific <title> or <meta> tags beyond what layout.tsx provides
  4. Run Lighthouse on the landing page — observe suboptimal LCP score

Expected Behavior

  • The landing page's static content (hero heading, feature descriptions, step guides) should be server-rendered as HTML
  • The page should export its own metadata object with landing-page-specific title, description, and Open Graph tags
  • Only the interactive parts (username input, badge preview, recent searches state) should be client components
  • Search engines should see the full page content without executing JavaScript

Screenshots / Logs

N/A — this is an architectural issue visible via View Source or Lighthouse audit.

Suggested Fix

Refactor app/page.tsx into a Server Component that imports a client component for the interactive parts:

// app/page.tsx (Server Component — NO "use client")
import { Metadata } from "next";
import LandingPageClient from "./components/LandingPageClient";

export const metadata: Metadata = {
  title: "CommitPulse | 3D Isometric GitHub Contribution Graph",
  description: "Transform your GitHub contribution history into a cinematic 3D animated badge...",
  // page-specific OG tags, etc.
};

export default function LandingPage() {
  return <LandingPageClient />;
}

Or better yet, keep the static content (hero, features, footer) in the server component and only wrap the interactive form in a client component:

// app/page.tsx (Server Component)
import UsernameForm from "./components/UsernameForm"; // "use client"
import { FeatureCardsSection } from "@/components/FeatureCards";

export const metadata: Metadata = { ... };

export default function LandingPage() {
  return (
    <main>
      <h1>Elevate Your Contribution Story.</h1>
      <UsernameForm />  {/* Only this is client-rendered */}
      <FeatureCardsSection />  {/* Server-rendered static content */}
    </main>
  );
}

Impact

  • SEO: Landing page content is invisible to crawlers that don't execute JS
  • Performance: Higher LCP, larger JS bundle, slower Time to Interactive
  • Social sharing: Cannot define page-specific Open Graph metadata for the homepage
  • Best practices: Violates Next.js App Router recommendation to keep pages as Server Components where possible

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions