Skip to content

Commit aaffd3b

Browse files
committed
feat: more SEO optimization
1 parent 946cb0b commit aaffd3b

File tree

7 files changed

+238
-15
lines changed

7 files changed

+238
-15
lines changed

app/category/[cid]/page.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,29 @@ export async function generateMetadata({
2828
}
2929

3030
return {
31-
title: `${categoryData.cat_title} Projects`,
31+
title: `${categoryData.cat_title} Projects in NEAR Catalog`,
3232
description:
3333
categoryData.cat_desc ||
34-
`Discover ${categoryData.cat_title} projects`,
34+
`Explore ${categoryData.cat_title} projects in the NEAR ecosystem. Discover innovative blockchain applications and tools built on NEAR Protocol.`,
35+
keywords: [cid, "NEAR", "NEAR Projects", categoryData.cat_title],
36+
openGraph: {
37+
title: `${categoryData.cat_title} Projects - NEAR Catalog`,
38+
description:
39+
categoryData.cat_desc ||
40+
`Explore ${categoryData.cat_title} projects in the NEAR ecosystem.`,
41+
type: "website",
42+
url: `https://nearcatalog.xyz/category/${cid}`,
43+
},
44+
twitter: {
45+
card: "summary",
46+
title: `${categoryData.cat_title} Projects - NEAR Catalog`,
47+
description:
48+
categoryData.cat_desc ||
49+
`Explore ${categoryData.cat_title} projects in the NEAR ecosystem.`,
50+
},
51+
alternates: {
52+
canonical: `/category/${cid}`,
53+
},
3554
};
3655
}
3756

app/layout.tsx

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const metadata: Metadata = {
2020
template: "%s - NEAR Catalog",
2121
},
2222
description:
23-
"NEAR Catalog is an ecosystem directory for NEAR Protocol, showcasing NEAR projects, teams, people and contributors.",
23+
"NEAR Catalog is #1 ecosystem directory for NEAR Protocol, showcasing NEAR projects, teams, people and contributors.",
2424
metadataBase: new URL(BASE_URL),
2525
alternates: {
2626
canonical: './'
@@ -31,6 +31,14 @@ export const metadata: Metadata = {
3131
"NEAR Catalog",
3232
"NEAR Projects",
3333
"NEAR Ecosystem",
34+
"NEAR dApps",
35+
"NEAR DeFi",
36+
"NEAR AI",
37+
"NEAR Intents"
38+
"NEAR Chain Abstraction",
39+
"blockchain directory",
40+
"crypto projects",
41+
"Web3 applications",
3442
"NEAR Community",
3543
"NEAR People",
3644
],
@@ -40,17 +48,73 @@ export const metadata: Metadata = {
4048
url: BASE_URL,
4149
},
4250
],
43-
creator: "@near",
44-
manifest: "/manifest.webmanifest"
51+
creator: "@nearcatalog",
52+
manifest: "/manifest.webmanifest",
53+
twitter: {
54+
card: "summary_large_image",
55+
site: "@nearcatalog",
56+
creator: "@nearcatalog",
57+
title: "NEAR Catalog - Explore NEAR Projects, People and mores",
58+
description: "NEAR Catalog is #1 ecosystem directory for NEAR Protocol, showcasing NEAR projects, teams, people and contributors.",
59+
images: [
60+
{
61+
url: `${BASE_URL}/og-image.webp`,
62+
width: 1200,
63+
height: 630,
64+
alt: "NEAR Catalog - NEAR Ecosystem Directory"
65+
}
66+
]
67+
},
68+
openGraph: {
69+
type: "website",
70+
locale: "en_US",
71+
url: BASE_URL,
72+
title: "NEAR Catalog - Discover NEAR Projects, People and mores",
73+
description: "NEAR Catalog is #1 ecosystem directory for NEAR Protocol, showcasing NEAR projects, teams, people and contributors.",
74+
siteName: "NEAR Catalog",
75+
images: [
76+
{
77+
url: `${BASE_URL}/og-image.webp`,
78+
width: 1200,
79+
height: 630,
80+
alt: "NEAR Catalog - NEAR Ecosystem Directory"
81+
}
82+
]
83+
}
4584
};
4685

4786
interface RootLayoutProps {
4887
children: React.ReactNode;
4988
}
5089

5190
export default function RootLayout({ children }: RootLayoutProps) {
91+
const organizationSchema = {
92+
"@context": "https://schema.org",
93+
"@type": "Organization",
94+
"name": "NEAR Catalog",
95+
"url": BASE_URL,
96+
"logo": `${BASE_URL}/favicon.ico`,
97+
"sameAs": [
98+
"https://x.com/nearcatalog",
99+
"https://github.com/nearcatalog",
100+
"https://t.me/nearcatalogchat"
101+
],
102+
"description": "NEAR Catalog is #1 ecosystem directory for NEAR Protocol, showcasing NEAR projects, teams, people and contributors.",
103+
"contact": {
104+
"@type": "ContactPoint",
105+
"url": BASE_URL,
106+
"contactType": "Customer Service"
107+
}
108+
};
109+
52110
return (
53111
<html lang="en">
112+
<head>
113+
<script
114+
type="application/ld+json"
115+
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema) }}
116+
/>
117+
</head>
54118
<body className={` min-h-screen bg-black font-sans antialiased`}
55119
>
56120
<div className="bg-background relative flex min-h-screen flex-col">

app/project/[pid]/layout.tsx

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,37 @@ export async function generateMetadata({
4646
if (!project) {
4747
return {
4848
title: "Project Not Found",
49-
description: "The requested project could not be found."
49+
description: "The requested project could not be found in NEAR Catalog."
5050
};
5151
}
5252

53+
const projectTags = Object.keys(project.profile.tags || {});
54+
const imageUrl = project.profile.image?.url || "https://nearcatalog.xyz/favicon.ico";
55+
5356
return {
54-
title: `${project.profile.name}`,
55-
description: project.profile.name + " - " + project.profile.tagline,
56-
keywords: Object.values(project.profile.tags),
57+
title: `${project.profile.name} - NEAR Project`,
58+
description: `${project.profile.tagline} - Discover ${project.profile.name} on NEAR Catalog, the #1 NEAR ecosystem directory.`,
59+
keywords: [project.profile.name, ...projectTags, "NEAR", "NEAR Project"],
5760
openGraph: {
61+
type: "website",
62+
title: `${project.profile.name} - NEAR Catalog`,
63+
description: `${project.profile.tagline} - Discover ${project.profile.name} on NEAR Catalog, the #1 NEAR ecosystem directory.`,
64+
url: `https://nearcatalog.xyz/project/${pid}`,
65+
images: [
66+
{
67+
url: imageUrl,
68+
width: 1200,
69+
height: 630,
70+
alt: project.profile.name
71+
}
72+
]
73+
},
74+
twitter: {
75+
card: "summary_large_image",
5876
title: `${project.profile.name} - NEAR Catalog`,
59-
description: project.profile.name + " - " + project.profile.tagline,
77+
description: `${project.profile.tagline}`,
78+
images: [imageUrl],
79+
creator: "@nearcatalog"
6080
},
6181
alternates: {
6282
canonical: `/project/${pid}`,

app/project/[pid]/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import SocialsEmbed from "./_components/socials-embed";
99
import Markdown from "react-markdown";
1010
import ErrorImage from "@/public/assets/images/error.webp";
1111
import remarkGfm from "remark-gfm";
12+
import { ProjectSchema } from "@/components/seo/json-ld";
1213

1314
interface ProjectPageProps {
1415
params: {
@@ -59,6 +60,7 @@ export default async function ProjectPage({ params }: ProjectPageProps) {
5960

6061
return (
6162
<main id="project-detail" className="container mx-auto my-4 flex flex-col gap-4 px-4 lg:my-12">
63+
<ProjectSchema project={projectData} />
6264
<div className="flex flex-col justify-between gap-4 lg:flex-row">
6365
<ProjectHeader projectData={projectData} />
6466
<LinkTree project={projectData} />

components/home/hero.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,9 @@ export default function HomeHero() {
99
<>
1010
<section id="home-hero" className="container relative z-[5] mx-auto mt-16 mb-0 flex flex-col items-center justify-center gap-6 sm:my-8">
1111
<HomeImages />
12-
<h1 className="z-[5] hidden text-balance text-center text-7xl font-bold leading-tight text-white sm:block">
13-
Discover NEAR Ecosystem
12+
<h1 className="z-[5] text-balance text-center text-[2.5rem] font-bold leading-tight text-white sm:text-7xl">
13+
Discover NEAR <br/> Ecosystem
1414
</h1>
15-
<h2 className="z-[5] text-balance text-center text-[2.5rem] font-bold leading-tight text-white sm:hidden">
16-
Discover NEAR <br /> Ecosystem
17-
</h2>
1815
{/* <HomeStats /> */}
1916
<GradientButton
2017
target="_blank"

components/seo/json-ld.tsx

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
export function OrganizationSchema() {
2+
const schema = {
3+
"@context": "https://schema.org",
4+
"@type": "Organization",
5+
name: "NEAR Catalog",
6+
url: "https://nearcatalog.xyz",
7+
logo: "https://nearcatalog.xyz/favicon.ico",
8+
sameAs: [
9+
"https://x.com/nearcatalog",
10+
"https://github.com/nearcatalog",
11+
"https://t.me/nearcatalogchat"
12+
],
13+
description: "NEAR Catalog is #1 ecosystem directory for NEAR Protocol, showcasing NEAR projects, teams, people and contributors.",
14+
contact: {
15+
"@type": "ContactPoint",
16+
url: "https://nearcatalog.xyz",
17+
contactType: "Customer Service"
18+
}
19+
};
20+
21+
return (
22+
<script
23+
type="application/ld+json"
24+
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
25+
/>
26+
);
27+
}
28+
29+
export function ProjectSchema({
30+
project
31+
}: {
32+
project: {
33+
profile: {
34+
name: string;
35+
tagline: string;
36+
image?: { url: string };
37+
tags?: Record<string, string>;
38+
};
39+
slug: string;
40+
}
41+
}) {
42+
const tags = project.profile.tags ? Object.keys(project.profile.tags) : [];
43+
const schema = {
44+
"@context": "https://schema.org",
45+
"@type": "SoftwareApplication",
46+
name: project.profile.name,
47+
description: project.profile.tagline,
48+
image: project.profile.image?.url || "https://nearcatalog.xyz/favicon.ico",
49+
url: `https://nearcatalog.xyz/project/${project.slug}`,
50+
applicationCategory: "BlockchainApplication",
51+
operatingSystem: "Web",
52+
keywords: tags.join(", "),
53+
offers: {
54+
"@type": "Offer",
55+
price: "0",
56+
priceCurrency: "USD"
57+
},
58+
publisher: {
59+
"@type": "Organization",
60+
name: "NEAR Catalog",
61+
url: "https://nearcatalog.xyz"
62+
}
63+
};
64+
65+
return (
66+
<script
67+
type="application/ld+json"
68+
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
69+
/>
70+
);
71+
}
72+
73+
export function BreadcrumbSchema({ items }: { items: { name: string; url: string }[] }) {
74+
const schema = {
75+
"@context": "https://schema.org",
76+
"@type": "BreadcrumbList",
77+
itemListElement: items.map((item, index) => ({
78+
"@type": "ListItem",
79+
position: index + 1,
80+
name: item.name,
81+
item: item.url
82+
}))
83+
};
84+
85+
return (
86+
<script
87+
type="application/ld+json"
88+
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
89+
/>
90+
);
91+
}
92+
93+
export function WebPageSchema({
94+
title,
95+
description,
96+
url
97+
}: {
98+
title: string;
99+
description: string;
100+
url: string;
101+
}) {
102+
const schema = {
103+
"@context": "https://schema.org",
104+
"@type": "WebPage",
105+
name: title,
106+
description: description,
107+
url: url,
108+
publisher: {
109+
"@type": "Organization",
110+
name: "NEAR Catalog",
111+
url: "https://nearcatalog.xyz"
112+
}
113+
};
114+
115+
return (
116+
<script
117+
type="application/ld+json"
118+
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
119+
/>
120+
);
121+
}

public/og-image.webp

1.22 MB
Loading

0 commit comments

Comments
 (0)