Skip to content

Commit f29a693

Browse files
committed
fix: Add canonical metadata in each page
1 parent fdea615 commit f29a693

File tree

9 files changed

+159
-97
lines changed

9 files changed

+159
-97
lines changed

app/account/[ownerEthAddr]/page.tsx

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,22 @@ const getCachedNodeOperatorProfile = unstable_cache(
3030
{ revalidate: 60 },
3131
);
3232

33-
export async function generateMetadata({ params }) {
34-
const { ownerEthAddr } = await params;
35-
36-
if (!ownerEthAddr || !isAddress(ownerEthAddr) || isZeroAddress(ownerEthAddr)) {
37-
return {
38-
title: 'Error',
39-
openGraph: {
40-
title: 'Error',
41-
},
42-
};
43-
}
33+
export async function generateMetadata({ params }) {
34+
const { ownerEthAddr } = await params;
35+
const canonical = `/account/${encodeURIComponent(ownerEthAddr)}`;
36+
const errorMetadata = {
37+
title: 'Error',
38+
openGraph: {
39+
title: 'Error',
40+
},
41+
alternates: {
42+
canonical,
43+
},
44+
};
45+
46+
if (!ownerEthAddr || !isAddress(ownerEthAddr) || isZeroAddress(ownerEthAddr)) {
47+
return errorMetadata;
48+
}
4449

4550
try {
4651
const [ensName, publicProfile] = await Promise.all([
@@ -50,21 +55,19 @@ export async function generateMetadata({ params }) {
5055

5156
const primaryName = publicProfile?.name || ensName || getShortAddress(ownerEthAddr, 4, true);
5257

53-
return {
54-
title: `Node Operator • ${primaryName}`,
55-
openGraph: {
56-
title: `Node Operator • ${primaryName}`,
57-
},
58-
};
59-
} catch (error) {
60-
return {
61-
title: 'Error',
62-
openGraph: {
63-
title: 'Error',
64-
},
65-
};
66-
}
67-
}
58+
return {
59+
title: `Node Operator • ${primaryName}`,
60+
openGraph: {
61+
title: `Node Operator • ${primaryName}`,
62+
},
63+
alternates: {
64+
canonical,
65+
},
66+
};
67+
} catch (error) {
68+
return errorMetadata;
69+
}
70+
}
6871

6972
export default async function NodeOperatorPage({ params }) {
7073
const { ownerEthAddr } = await params;

app/cloud-service-providers/page.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,23 @@ import CSPsList from '../server-components/CPSs/CSPsList';
66
import { BorderedCard } from '../server-components/shared/cards/BorderedCard';
77
import { CardHorizontal } from '../server-components/shared/cards/CardHorizontal';
88

9-
export async function generateMetadata() {
10-
return {
11-
title: 'Cloud Service Providers',
12-
openGraph: {
13-
title: 'Cloud Service Providers',
14-
},
15-
};
16-
}
9+
export async function generateMetadata({ searchParams }: { searchParams?: { page?: string } }) {
10+
const pageParam = Number.parseInt(searchParams?.page ?? '', 10);
11+
const canonical =
12+
Number.isFinite(pageParam) && pageParam > 1
13+
? `/cloud-service-providers?page=${pageParam}`
14+
: '/cloud-service-providers';
15+
16+
return {
17+
title: 'Cloud Service Providers',
18+
openGraph: {
19+
title: 'Cloud Service Providers',
20+
},
21+
alternates: {
22+
canonical,
23+
},
24+
};
25+
}
1726

1827
export default async function CSPsPage(props: {
1928
searchParams?: Promise<{

app/license/[licenseType]/[licenseId]/page.tsx

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@ import * as types from '@/typedefs/blockchain';
1010
import { Skeleton } from '@heroui/skeleton';
1111
import { cache, Suspense } from 'react';
1212

13-
const errorMetadata = {
14-
title: 'Error',
15-
openGraph: {
16-
title: 'Error',
17-
},
18-
};
19-
20-
export async function generateMetadata({ params }) {
21-
const { licenseType, licenseId } = await params;
13+
export async function generateMetadata({ params }) {
14+
const { licenseType, licenseId } = await params;
15+
const canonical = `/license/${encodeURIComponent(licenseType)}/${encodeURIComponent(licenseId)}`;
16+
const errorMetadata = {
17+
title: 'Error',
18+
openGraph: {
19+
title: 'Error',
20+
},
21+
alternates: {
22+
canonical,
23+
},
24+
};
2225

2326
if (!licenseType || !['ND', 'MND', 'GND'].includes(licenseType)) {
2427
return errorMetadata;
@@ -36,13 +39,16 @@ export async function generateMetadata({ params }) {
3639
return errorMetadata;
3740
}
3841

39-
return {
40-
title: `License #${licenseId}`,
41-
openGraph: {
42-
title: `License #${licenseId}`,
43-
},
44-
};
45-
}
42+
return {
43+
title: `License #${licenseId}`,
44+
openGraph: {
45+
title: `License #${licenseId}`,
46+
},
47+
alternates: {
48+
canonical,
49+
},
50+
};
51+
}
4652

4753
const fetchLicense = async (
4854
licenseType: 'ND' | 'MND' | 'GND',

app/licenses/page.tsx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@ import List from '../server-components/Licenses/List';
55
import { BorderedCard } from '../server-components/shared/cards/BorderedCard';
66
import { CardHorizontal } from '../server-components/shared/cards/CardHorizontal';
77

8-
export async function generateMetadata() {
9-
return {
10-
title: 'Licenses',
11-
openGraph: {
12-
title: 'Licenses',
13-
},
14-
};
15-
}
8+
export async function generateMetadata({ searchParams }: { searchParams?: { page?: string } }) {
9+
const pageParam = Number.parseInt(searchParams?.page ?? '', 10);
10+
const canonical = Number.isFinite(pageParam) && pageParam > 1 ? `/licenses?page=${pageParam}` : '/licenses';
11+
12+
return {
13+
title: 'Licenses',
14+
openGraph: {
15+
title: 'Licenses',
16+
},
17+
alternates: {
18+
canonical,
19+
},
20+
};
21+
}
1622

1723
export default async function LicensesPage(props: {
1824
searchParams?: Promise<{

app/node-operators/page.tsx

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,21 @@ import List from '../server-components/NodeOperators/List';
77
import { BorderedCard } from '../server-components/shared/cards/BorderedCard';
88
import { CardHorizontal } from '../server-components/shared/cards/CardHorizontal';
99

10-
export async function generateMetadata() {
11-
return {
12-
title: 'Node Operators',
13-
openGraph: {
14-
title: 'Node Operators',
15-
},
16-
};
17-
}
10+
export async function generateMetadata({ searchParams }: { searchParams?: { page?: string } }) {
11+
const pageParam = Number.parseInt(searchParams?.page ?? '', 10);
12+
const canonical =
13+
Number.isFinite(pageParam) && pageParam > 1 ? `/node-operators?page=${pageParam}` : '/node-operators';
14+
15+
return {
16+
title: 'Node Operators',
17+
openGraph: {
18+
title: 'Node Operators',
19+
},
20+
alternates: {
21+
canonical,
22+
},
23+
};
24+
}
1825

1926
const fetchLicenseHolders = async (environment: 'mainnet' | 'testnet' | 'devnet') => {
2027
const url = await getSSURL(`license-holders?env=${environment}`);

app/node/[nodeAddr]/page.tsx

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,9 @@ import * as types from '@/typedefs/blockchain';
1111
import { RiCloseLine } from 'react-icons/ri';
1212
import { isAddress } from 'viem';
1313

14-
const errorMetadata = {
15-
title: 'Error',
16-
openGraph: {
17-
title: 'Error',
18-
},
19-
};
20-
21-
const resolveNodeEthAddress = (nodeAddress?: string): types.EthAddress | null => {
22-
if (!nodeAddress) {
23-
return null;
14+
const resolveNodeEthAddress = (nodeAddress?: string): types.EthAddress | null => {
15+
if (!nodeAddress) {
16+
return null;
2417
}
2518

2619
if (nodeAddress.startsWith('0xai_')) {
@@ -39,12 +32,22 @@ const resolveNodeEthAddress = (nodeAddress?: string): types.EthAddress | null =>
3932
return nodeAddress;
4033
};
4134

42-
export async function generateMetadata({ params }) {
43-
const { nodeAddr } = await params;
44-
const resolvedNodeEthAddr = resolveNodeEthAddress(nodeAddr);
45-
46-
if (!resolvedNodeEthAddr) {
47-
console.log(`[Node Page] Invalid node address: ${nodeAddr}`);
35+
export async function generateMetadata({ params }) {
36+
const { nodeAddr } = await params;
37+
const canonical = `/node/${encodeURIComponent(nodeAddr)}`;
38+
const errorMetadata = {
39+
title: 'Error',
40+
openGraph: {
41+
title: 'Error',
42+
},
43+
alternates: {
44+
canonical,
45+
},
46+
};
47+
const resolvedNodeEthAddr = resolveNodeEthAddress(nodeAddr);
48+
49+
if (!resolvedNodeEthAddr) {
50+
console.log(`[Node Page] Invalid node address: ${nodeAddr}`);
4851
return errorMetadata;
4952
}
5053

@@ -57,13 +60,16 @@ export async function generateMetadata({ params }) {
5760
return errorMetadata;
5861
}
5962

60-
return {
61-
title: `Node • ${nodeResponse.node_alias}`,
62-
openGraph: {
63-
title: `Node • ${nodeResponse.node_alias}`,
64-
},
65-
};
66-
}
63+
return {
64+
title: `Node • ${nodeResponse.node_alias}`,
65+
openGraph: {
66+
title: `Node • ${nodeResponse.node_alias}`,
67+
},
68+
alternates: {
69+
canonical,
70+
},
71+
};
72+
}
6773

6874
const fetchLicenseDetailsAndNodeAvailability = async (
6975
nodeEthAddr: types.EthAddress,

app/page.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@ import List from './server-components/Nodes/List';
77
import NodesListSkeleton from './server-components/Skeletons/NodesListSkeleton';
88
import { DetailedAlert } from './server-components/shared/DetailedAlert';
99

10+
export async function generateMetadata({ searchParams }: { searchParams?: { page?: string } }) {
11+
const pageParam = Number.parseInt(searchParams?.page ?? '', 10);
12+
const canonical = Number.isFinite(pageParam) && pageParam > 1 ? `/?page=${pageParam}` : '/';
13+
14+
return {
15+
alternates: {
16+
canonical,
17+
},
18+
};
19+
}
20+
1021
export default async function HomePage(props: {
1122
searchParams?: Promise<{
1223
page?: string;

app/search/page.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ import { isNonZeroInteger } from '@/lib/utils';
33
import SearchResultsList from '../server-components/SearchResultsList';
44
import { BorderedCard } from '../server-components/shared/cards/BorderedCard';
55

6+
export async function generateMetadata({ searchParams }: { searchParams?: { query?: string } }) {
7+
const rawQuery = searchParams?.query?.trim();
8+
const canonical = rawQuery ? `/search?query=${encodeURIComponent(rawQuery)}` : '/search';
9+
10+
return {
11+
alternates: {
12+
canonical,
13+
},
14+
};
15+
}
16+
617
export default async function SearchPage(props: {
718
searchParams?: Promise<{
819
query?: string;

app/stats/page.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@ const chartConfig = {
2828
},
2929
} satisfies ChartConfig;
3030

31-
export async function generateMetadata() {
32-
return {
33-
title: 'Stats',
34-
openGraph: {
35-
title: 'Stats',
36-
},
37-
};
38-
}
31+
export async function generateMetadata() {
32+
return {
33+
title: 'Stats',
34+
openGraph: {
35+
title: 'Stats',
36+
},
37+
alternates: {
38+
canonical: '/stats',
39+
},
40+
};
41+
}
3942

4043
export default async function StatsPage() {
4144
let tokenSupply: TokenSupplyResponse;

0 commit comments

Comments
 (0)