refactor(web): restructure JSON-LD use

This commit is contained in:
Bjorn Lammers 2025-04-23 13:30:45 +02:00
parent cedbca1869
commit ce16ac85d4
5 changed files with 58 additions and 41 deletions

View File

@ -1,4 +1,5 @@
import { IconDetails } from "@/components/icon-details" import { IconDetails } from "@/components/icon-details"
import { StructuredData } from "@/components/structured-data"
import { BASE_URL, GITHUB_URL, ICON_DETAIL_KEYWORDS, SITE_NAME, SITE_TAGLINE, TITLE_SEPARATOR, WEB_URL, getIconDescription, getIconSchema } from "@/constants" import { BASE_URL, GITHUB_URL, ICON_DETAIL_KEYWORDS, SITE_NAME, SITE_TAGLINE, TITLE_SEPARATOR, WEB_URL, getIconDescription, getIconSchema } from "@/constants"
import { getAllIcons, getAuthorData } from "@/lib/api" import { getAllIcons, getAuthorData } from "@/lib/api"
import type { Metadata, ResolvingMetadata } from "next" import type { Metadata, ResolvingMetadata } from "next"
@ -118,9 +119,7 @@ export default async function IconPage({ params }: { params: Promise<{ icon: str
return ( return (
<> <>
<Script id="image-schema" type="application/ld+json"> <StructuredData data={imageSchema} id="image-schema" />
{JSON.stringify(imageSchema)}
</Script>
<IconDetails icon={icon} iconData={originalIconData} authorData={authorData} /> <IconDetails icon={icon} iconData={originalIconData} authorData={authorData} />
</> </>
) )

View File

@ -2,6 +2,7 @@ import { BASE_URL, BROWSE_KEYWORDS, DEFAULT_OG_IMAGE, GITHUB_URL, ORGANIZATION_N
import { getIconsArray } from "@/lib/api" import { getIconsArray } from "@/lib/api"
import type { Metadata } from "next" import type { Metadata } from "next"
import { IconSearch } from "./components/icon-search" import { IconSearch } from "./components/icon-search"
import { StructuredData } from "@/components/structured-data"
export async function generateMetadata(): Promise<Metadata> { export async function generateMetadata(): Promise<Metadata> {
const icons = await getIconsArray() const icons = await getIconsArray()
@ -41,12 +42,7 @@ export const dynamic = "force-static"
export default async function IconsPage() { export default async function IconsPage() {
const icons = await getIconsArray() const icons = await getIconsArray()
return ( const gallerySchema = {
<>
<script
id="gallery-schema"
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify({
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "ImageGallery", "@type": "ImageGallery",
"name": `${SITE_NAME} - Browse ${icons.length} Icons - ${SITE_TAGLINE}`, "name": `${SITE_NAME} - Browse ${icons.length} Icons - ${SITE_TAGLINE}`,
@ -58,13 +54,11 @@ export default async function IconsPage() {
"name": ORGANIZATION_NAME, "name": ORGANIZATION_NAME,
"url": GITHUB_URL "url": GITHUB_URL
} }
}) }} }
/>
<script return (
id="org-schema" <>
type="application/ld+json" <StructuredData data={gallerySchema} id="gallery-schema" />
dangerouslySetInnerHTML={{ __html: JSON.stringify(ORGANIZATION_SCHEMA) }}
/>
<div className="isolate overflow-hidden"> <div className="isolate overflow-hidden">
<div className="py-8"> <div className="py-8">
<div className="space-y-4 mb-8 mx-auto max-w-7xl px-4 sm:px-6 lg:px-8"> <div className="space-y-4 mb-8 mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">

View File

@ -2,6 +2,7 @@ import { PostHogProvider } from "@/components/PostHogProvider"
import { Footer } from "@/components/footer" import { Footer } from "@/components/footer"
import { HeaderWrapper } from "@/components/header-wrapper" import { HeaderWrapper } from "@/components/header-wrapper"
import { LicenseNotice } from "@/components/license-notice" import { LicenseNotice } from "@/components/license-notice"
import { WebsiteStructuredData } from "@/components/structured-data"
import { getTotalIcons } from "@/lib/api" import { getTotalIcons } from "@/lib/api"
import type { Metadata, Viewport } from "next" import type { Metadata, Viewport } from "next"
import { Inter } from "next/font/google" import { Inter } from "next/font/google"
@ -9,7 +10,6 @@ import { Toaster } from "sonner"
import "./globals.css" import "./globals.css"
import { DEFAULT_KEYWORDS, DEFAULT_OG_IMAGE, GITHUB_URL, ORGANIZATION_NAME, ORGANIZATION_SCHEMA, SITE_NAME, SITE_TAGLINE, WEB_URL, getDescription, getWebsiteSchema, websiteFullTitle, websiteTitle } from "@/constants" import { DEFAULT_KEYWORDS, DEFAULT_OG_IMAGE, GITHUB_URL, ORGANIZATION_NAME, ORGANIZATION_SCHEMA, SITE_NAME, SITE_TAGLINE, WEB_URL, getDescription, getWebsiteSchema, websiteFullTitle, websiteTitle } from "@/constants"
import { ThemeProvider } from "./theme-provider" import { ThemeProvider } from "./theme-provider"
import Script from "next/script"
const inter = Inter({ const inter = Inter({
variable: "--font-inter", variable: "--font-inter",
@ -98,16 +98,12 @@ export default async function RootLayout({ children }: Readonly<{ children: Reac
return ( return (
<html lang="en" suppressHydrationWarning> <html lang="en" suppressHydrationWarning>
<head>
<Script id="schema-org" type="application/ld+json">
{JSON.stringify(websiteSchema)}
</Script>
<Script id="org-schema" type="application/ld+json">
{JSON.stringify(ORGANIZATION_SCHEMA)}
</Script>
</head>
<body className={`${inter.variable} antialiased bg-background flex flex-col min-h-screen`}> <body className={`${inter.variable} antialiased bg-background flex flex-col min-h-screen`}>
<PostHogProvider> <PostHogProvider>
<WebsiteStructuredData
websiteSchema={websiteSchema}
organizationSchema={ORGANIZATION_SCHEMA}
/>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange> <ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
<HeaderWrapper /> <HeaderWrapper />
<main className="flex-grow">{children}</main> <main className="flex-grow">{children}</main>

View File

@ -1,9 +1,9 @@
import { HeroSection } from "@/components/hero" import { HeroSection } from "@/components/hero"
import { RecentlyAddedIcons } from "@/components/recently-added-icons" import { RecentlyAddedIcons } from "@/components/recently-added-icons"
import { StructuredData } from "@/components/structured-data"
import { BASE_URL, DEFAULT_KEYWORDS, DEFAULT_OG_IMAGE, GITHUB_URL, ORGANIZATION_NAME, ORGANIZATION_SCHEMA, SITE_NAME, SITE_TAGLINE, WEB_URL, REPO_NAME, getHomeDescription, websiteFullTitle, websiteTitle } from "@/constants" import { BASE_URL, DEFAULT_KEYWORDS, DEFAULT_OG_IMAGE, GITHUB_URL, ORGANIZATION_NAME, ORGANIZATION_SCHEMA, SITE_NAME, SITE_TAGLINE, WEB_URL, REPO_NAME, getHomeDescription, websiteFullTitle, websiteTitle } from "@/constants"
import { getRecentlyAddedIcons, getTotalIcons } from "@/lib/api" import { getRecentlyAddedIcons, getTotalIcons } from "@/lib/api"
import type { Metadata } from "next" import type { Metadata } from "next"
import Script from "next/script"
export async function generateMetadata(): Promise<Metadata> { export async function generateMetadata(): Promise<Metadata> {
const { totalIcons } = await getTotalIcons() const { totalIcons } = await getTotalIcons()
@ -70,12 +70,7 @@ export default async function Home() {
return ( return (
<> <>
<Script id="collection-schema" type="application/ld+json"> <StructuredData data={collectionSchema} id="collection-schema" />
{JSON.stringify(collectionSchema)}
</Script>
<Script id="org-schema" type="application/ld+json">
{JSON.stringify(ORGANIZATION_SCHEMA)}
</Script>
<div className="flex flex-col min-h-screen"> <div className="flex flex-col min-h-screen">
<HeroSection totalIcons={totalIcons} stars={stars} /> <HeroSection totalIcons={totalIcons} stars={stars} />
<RecentlyAddedIcons icons={recentIcons} /> <RecentlyAddedIcons icons={recentIcons} />

View File

@ -0,0 +1,33 @@
"use client"
type StructuredDataProps = {
data: any
id?: string
}
export const StructuredData = ({ data, id }: StructuredDataProps) => {
return (
<script
id={id}
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
/>
)
}
type WebsiteStructuredDataProps = {
websiteSchema: any
organizationSchema: any
}
export const WebsiteStructuredData = ({
websiteSchema,
organizationSchema
}: WebsiteStructuredDataProps) => {
return (
<>
<StructuredData data={websiteSchema} id="website-schema" />
<StructuredData data={organizationSchema} id="organization-schema" />
</>
)
}