Skip to content

Commit 3fb561b

Browse files
authored
Merge pull request #287 from CivicDataLab/284-seo-setup
Initial SEO Setup
2 parents 0496362 + 50bff86 commit 3fb561b

File tree

16 files changed

+547
-271
lines changed

16 files changed

+547
-271
lines changed

app/[locale]/(user)/about-us/page.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
11
import Image from 'next/image';
22
import { Text } from 'opub-ui';
33

4+
import { generatePageMetadata } from '@/lib/utils';
45
import BreadCrumbs from '@/components/BreadCrumbs';
56
import Team from './components/Team';
67

8+
export const generateMetadata = () =>
9+
generatePageMetadata({
10+
title: 'About Us',
11+
description:
12+
'Learn more about CivicDataSpace, our mission, and the people behind it.',
13+
keywords: ['CivicDataSpace', 'About Us', 'Open Data', 'CDL'],
14+
openGraph: {
15+
type: 'website',
16+
locale: 'en_US',
17+
url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/about`, // update if dynamic
18+
title: 'About CivicDataSpace',
19+
description:
20+
'Explore the mission, vision, and people powering CivicDataSpace – an open-source platform to enable data for public good.',
21+
siteName: 'CivicDataSpace',
22+
image: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/og.png`, // from /public/og.png
23+
},
24+
});
25+
726
const About = () => {
827
return (
928
<main>
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
'use client';
2+
3+
import { useEffect, useState } from 'react';
4+
import { graphql } from '@/gql';
5+
import { useQuery } from '@tanstack/react-query';
6+
import { Spinner } from 'opub-ui';
7+
8+
import { GraphQL } from '@/lib/api';
9+
import BreadCrumbs from '@/components/BreadCrumbs';
10+
import Details from './components/Details';
11+
import Metadata from './components/Metadata';
12+
import PrimaryData from './components/PrimaryData';
13+
import Resources from './components/Resources';
14+
import SimilarDatasets from './components/SimilarDatasets';
15+
16+
const datasetQuery: any = graphql(`
17+
query getDataset($datasetId: UUID!) {
18+
getDataset(datasetId: $datasetId) {
19+
tags {
20+
id
21+
value
22+
}
23+
id
24+
downloadCount
25+
title
26+
description
27+
created
28+
modified
29+
isIndividualDataset
30+
user {
31+
fullName
32+
id
33+
profilePicture {
34+
url
35+
}
36+
}
37+
metadata {
38+
metadataItem {
39+
id
40+
label
41+
dataType
42+
}
43+
value
44+
}
45+
license
46+
resources {
47+
id
48+
created
49+
modified
50+
type
51+
name
52+
description
53+
}
54+
organization {
55+
name
56+
logo {
57+
url
58+
}
59+
slug
60+
id
61+
}
62+
sectors {
63+
name
64+
}
65+
formats
66+
}
67+
}
68+
`);
69+
70+
export default function DatasetDetailsPage({
71+
datasetId,
72+
}: {
73+
datasetId: string;
74+
}) {
75+
const Datasetdetails: { data: any; isLoading: any } = useQuery(
76+
[`details_${datasetId}`],
77+
() =>
78+
GraphQL(
79+
datasetQuery,
80+
{},
81+
{ datasetId: datasetId }
82+
)
83+
);
84+
85+
return (
86+
<main className=" bg-surfaceDefault">
87+
<BreadCrumbs
88+
data={[
89+
{ href: '/', label: 'Home' },
90+
{ href: '/datasets', label: 'Dataset Listing' },
91+
{ href: '#', label: 'Dataset Details' },
92+
]}
93+
/>
94+
<div className="flex">
95+
<div className="w-full gap-10 border-r-2 border-solid border-greyExtralight p-6 lg:w-3/4 lg:p-10">
96+
{Datasetdetails.isLoading ? (
97+
<div className=" mt-8 flex justify-center">
98+
<Spinner />
99+
</div>
100+
) : (
101+
<PrimaryData
102+
data={Datasetdetails?.data?.getDataset}
103+
isLoading={Datasetdetails.isLoading}
104+
/>
105+
)}
106+
<Details />
107+
<Resources />
108+
<SimilarDatasets />
109+
</div>
110+
<div className=" hidden w-1/4 gap-10 px-7 py-10 lg:block">
111+
{Datasetdetails.isLoading ? (
112+
<div className=" mt-8 flex justify-center">
113+
<Spinner />
114+
</div>
115+
) : (
116+
<Metadata data={Datasetdetails?.data?.getDataset} />
117+
)}
118+
</div>
119+
</div>
120+
</main>
121+
);
122+
}
Lines changed: 45 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,56 @@
1-
'use client';
2-
3-
import { useRef, useState } from 'react';
4-
import { useParams } from 'next/navigation';
51
import { graphql } from '@/gql';
6-
import { useQuery } from '@tanstack/react-query';
7-
import { Spinner } from 'opub-ui';
82

93
import { GraphQL } from '@/lib/api';
10-
import BreadCrumbs from '@/components/BreadCrumbs';
11-
import Details from './components/Details';
12-
import Metadata from './components/Metadata';
13-
import PrimaryData from './components/PrimaryData';
14-
import Resources from './components/Resources';
15-
import SimilarDatasets from './components/SimilarDatasets';
4+
import { generatePageMetadata } from '@/lib/utils';
5+
import DatasetDetailsPage from './DatasetDetailsPage';
166

17-
const datasetQuery: any = graphql(`
18-
query getDataset($datasetId: UUID!) {
7+
const datasetMetaQuery: any = graphql(`
8+
query getDatasetInfo($datasetId: UUID!) {
199
getDataset(datasetId: $datasetId) {
20-
tags {
21-
id
22-
value
23-
}
24-
id
25-
downloadCount
2610
title
2711
description
28-
created
29-
modified
30-
isIndividualDataset
31-
user {
32-
fullName
33-
id
34-
profilePicture {
35-
url
36-
}
37-
}
38-
metadata {
39-
metadataItem {
40-
id
41-
label
42-
dataType
43-
}
44-
value
45-
}
46-
license
47-
resources {
48-
id
49-
created
50-
modified
51-
type
52-
name
53-
description
54-
}
55-
organization {
56-
name
57-
logo {
58-
url
59-
}
60-
slug
61-
id
62-
}
63-
sectors {
64-
name
65-
}
66-
formats
12+
id
6713
}
6814
}
6915
`);
7016

71-
const DatasetDetailsPage = () => {
72-
const params = useParams();
73-
74-
const Datasetdetails: { data: any; isLoading: any } = useQuery(
75-
[`${params.datasetIdentifier}`],
76-
() =>
77-
GraphQL(
78-
datasetQuery,
79-
{
80-
// Entity Headers if present
81-
},
82-
{ datasetId: params.datasetIdentifier }
83-
)
84-
);
85-
86-
return (
87-
<main className=" bg-surfaceDefault">
88-
<BreadCrumbs
89-
data={[
90-
{ href: '/', label: 'Home' },
91-
{ href: '/datasets', label: 'Dataset Listing' },
92-
{ href: '#', label: 'Dataset Details' },
93-
]}
94-
/>
95-
<div className="flex">
96-
<div className="w-full gap-10 border-r-2 border-solid border-greyExtralight p-6 lg:w-3/4 lg:p-10">
97-
{Datasetdetails.isLoading ? (
98-
<div className=" mt-8 flex justify-center">
99-
<Spinner />
100-
</div>
101-
) : (
102-
<PrimaryData
103-
data={Datasetdetails.data && Datasetdetails.data?.getDataset}
104-
isLoading={Datasetdetails.isLoading}
105-
/>
106-
)}
107-
<Details />
108-
<Resources />
109-
<SimilarDatasets />
110-
</div>
111-
<div className=" hidden w-1/4 gap-10 px-7 py-10 lg:block">
112-
{Datasetdetails.isLoading ? (
113-
<div className=" mt-8 flex justify-center">
114-
<Spinner />
115-
</div>
116-
) : (
117-
<div>
118-
<Metadata
119-
data={Datasetdetails.data && Datasetdetails.data?.getDataset}
120-
/>
121-
</div>
122-
)}
123-
</div>
124-
</div>
125-
126-
{/* <div className="w-full p-6 lg:p-10 lg:py-10">
127-
<SimilarDatasets />
128-
</div> */}
129-
</main>
130-
);
131-
};
132-
133-
export default DatasetDetailsPage;
17+
export async function generateMetadata({
18+
params,
19+
}: {
20+
params: { datasetIdentifier: string };
21+
}) {
22+
try {
23+
const res: any = await GraphQL(
24+
datasetMetaQuery,
25+
{},
26+
{ datasetId: params.datasetIdentifier }
27+
);
28+
29+
const dataset = res?.getDataset;
30+
31+
return generatePageMetadata({
32+
title: dataset?.title,
33+
description: dataset?.description,
34+
openGraph: {
35+
type: 'dataset',
36+
locale: 'en_US',
37+
url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/datasets/${params.datasetIdentifier}`,
38+
title: dataset?.title,
39+
description: dataset?.description,
40+
siteName: 'CivicDataSpace',
41+
image: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/og.png`,
42+
},
43+
});
44+
} catch (e) {
45+
console.error('Metadata fetch error', e);
46+
return generatePageMetadata({ title: 'Dataset Details' });
47+
}
48+
}
49+
50+
export default function Page({
51+
params,
52+
}: {
53+
params: { datasetIdentifier: string };
54+
}) {
55+
return <DatasetDetailsPage datasetId={params.datasetIdentifier} />;
56+
}

app/[locale]/(user)/page.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,35 @@
1+
import { generatePageMetadata } from '@/lib/utils';
12
import { Content } from './components/Content';
23
import Datasets from './components/Datasets';
34
import Sectors from './components/Sectors';
45
import UseCases from './components/UseCases';
56

7+
export const generateMetadata = () =>
8+
generatePageMetadata({
9+
title: 'CivicDataSpace – Empowering Public Good with Open Data',
10+
description:
11+
'CivicDataSpace is an open-source platform enabling inclusive and AI-ready data collaboratives. Explore datasets, use cases, and insights for public good.',
12+
keywords: [
13+
'CivicDataSpace',
14+
'Open Data',
15+
'Data Collaboratives',
16+
'Public Datasets',
17+
'AI-ready data',
18+
'CivicTech',
19+
'CivicDataLab',
20+
],
21+
openGraph: {
22+
type: 'website',
23+
locale: 'en_US',
24+
url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}`,
25+
title: 'CivicDataSpace – Empowering Public Good with Open Data',
26+
description:
27+
'Explore CivicDataSpace, an open-source platform to make data inclusive, interoperable, and impactful for researchers, policymakers, and civic actors.',
28+
siteName: 'CivicDataSpace',
29+
image: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/og.png`, // from /public/og.png
30+
},
31+
});
32+
633
export default async function Home() {
734
return (
835
<div className="bg-surfaceDefault">

0 commit comments

Comments
 (0)