Description
surfsense_web/app/(home)/announcements/page.tsx is a public, crawlable page but has no SEO metadata of its own. The entire file is marked "use client", which prevents exporting metadata or generateMetadata from the same module (those only work in Server Components).
Current file (lines 1–18):
"use client";
import { useEffect } from "react";
import { AnnouncementCard } from "@/components/announcements/AnnouncementCard";
import { AnnouncementsEmptyState } from "@/components/announcements/AnnouncementsEmptyState";
import { useAnnouncements } from "@/hooks/use-announcements";
export default function AnnouncementsPage() {
const { announcements, markAllRead } = useAnnouncements();
useEffect(() => {
markAllRead();
}, [markAllRead]);
// ...
}
So the route falls back to root app/layout.tsx metadata, giving generic titles/descriptions in search results and social previews.
Other marketing routes (e.g. /blog, /changelog, /contact, /privacy, /terms) already define metadata or generateMetadata; this is the gap.
What to do
Create a server layout at surfsense_web/app/(home)/announcements/layout.tsx that exports route-specific metadata and just renders its children:
import type { Metadata, ReactNode } from "next";
export const metadata: Metadata = {
title: "Announcements | SurfSense",
description: "Latest product updates, feature releases, and news from SurfSense.",
alternates: {
canonical: "https://www.surfsense.net/announcements",
},
openGraph: {
title: "Announcements | SurfSense",
description: "Latest product updates, feature releases, and news from SurfSense.",
url: "https://www.surfsense.net/announcements",
type: "website",
},
twitter: {
card: "summary_large_image",
title: "Announcements | SurfSense",
description: "Latest product updates, feature releases, and news from SurfSense.",
},
};
export default function AnnouncementsLayout({ children }: { children: ReactNode }) {
return <>{children}</>;
}
Important:
- Do NOT add
"use client" to this layout — it must stay a Server Component so metadata export works
- Do NOT change
page.tsx
- If the canonical domain differs (check
app/layout.tsx for the actual metadataBase), adjust it
Verify
- View the page source at
/announcements and confirm the new <title> and <meta> tags are present
next build succeeds
Acceptance criteria
- New
app/(home)/announcements/layout.tsx exists with route-specific metadata
- Existing page behavior is unchanged
Description
surfsense_web/app/(home)/announcements/page.tsxis a public, crawlable page but has no SEO metadata of its own. The entire file is marked"use client", which prevents exportingmetadataorgenerateMetadatafrom the same module (those only work in Server Components).Current file (lines 1–18):
So the route falls back to root
app/layout.tsxmetadata, giving generic titles/descriptions in search results and social previews.Other marketing routes (e.g.
/blog,/changelog,/contact,/privacy,/terms) already definemetadataorgenerateMetadata; this is the gap.What to do
Create a server layout at
surfsense_web/app/(home)/announcements/layout.tsxthat exports route-specific metadata and just renders its children:Important:
"use client"to this layout — it must stay a Server Component sometadataexport workspage.tsxapp/layout.tsxfor the actual metadataBase), adjust itVerify
/announcementsand confirm the new<title>and<meta>tags are presentnext buildsucceedsAcceptance criteria
app/(home)/announcements/layout.tsxexists with route-specific metadata