Skip to content

Commit 779b070

Browse files
feat: improve SEO by adding canonical URLs, structured data, and breadcrumbs, and remove redundant robots.ts.
1 parent cbb4a66 commit 779b070

12 files changed

Lines changed: 170 additions & 87 deletions

File tree

‎src/app/clinical-trials/page.js‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ import ClinicalTrialsSkeleton from './ClinicalTrialsSkeleton.js';
66
export const metadata = {
77
title: 'Find Clinical Trials to Participate In | Yourself to Science',
88
description: 'A curated catalogue of international registries and platforms to find and participate in clinical trials. Search for studies by disease, location, or as a healthy volunteer.',
9+
alternates: {
10+
canonical: 'https://yourselftoscience.org/clinical-trials',
11+
},
12+
openGraph: {
13+
title: 'Find Clinical Trials to Participate In | Yourself to Science',
14+
description: 'A curated catalogue of international registries and platforms to find and participate in clinical trials.',
15+
url: 'https://yourselftoscience.org/clinical-trials',
16+
type: 'website',
17+
},
918
};
1019

1120
export default function ClinicalTrialsPage() {

‎src/app/data-types/[slug]/page.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export async function generateMetadata({ params }) {
2424
return {
2525
title: `${dataType.title} | Data Dictionary | Yourself to Science`,
2626
description: dataType.description,
27+
alternates: {
28+
canonical: `https://yourselftoscience.org/data-types/${dataType.slug}`,
29+
},
2730
};
2831
}
2932

‎src/app/data-types/page.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import CopyButton from '@/components/CopyButton';
66
export const metadata = {
77
title: 'Data Dictionary | Yourself to Science',
88
description: 'Ontology definitions for the various biological, digital, and clinical data types tracked in the Yourself to Science catalogue.',
9+
alternates: {
10+
canonical: 'https://yourselftoscience.org/data-types',
11+
},
912
};
1013

1114
export default function DataTypesPage() {

‎src/app/data/layout.js‎

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import lastUpdatedMeta from '@/data/lastUpdated.json';
2+
import { permanentDoi } from '@/data/config';
3+
14
const title = "Open Science Data & API Hub | Programmatic Research Infrastructure";
25
const description = "Programmatic access to the Yourself to Science dataset. Relational data packages, AI/LLM feeds, quantitative JSON endpoints, and semantic RDF mapping. Standardized research infrastructure for open science.";
36
const url = "https://yourselftoscience.org/data";
@@ -48,5 +51,74 @@ export const metadata = {
4851
};
4952

5053
export default function DataLayout({ children }) {
51-
return <>{children}</>;
54+
// Dataset JSON-LD is rendered server-side here for reliable Google indexing,
55+
// rather than in the 'use client' page component.
56+
const jsonLd = {
57+
"@context": "https://schema.org/",
58+
"@type": "Dataset",
59+
"name": "Yourself to Science Open Dataset",
60+
"description": "A curated, open-access catalog of services, platforms, and programs that allow individuals to securely contribute to scientific research with their biological and digital selves.",
61+
"url": "https://yourselftoscience.org/data",
62+
"sameAs": "https://yourselftoscience.org/resources.ttl#dataset",
63+
"identifier": [
64+
"https://yourselftoscience.org/resources.ttl#dataset",
65+
`https://doi.org/${permanentDoi}`
66+
],
67+
"keywords": [
68+
"open dataset",
69+
"CC0 dataset",
70+
"public domain data",
71+
"science data",
72+
"clinical trials data",
73+
"citizen science dataset",
74+
"JSON API",
75+
"CSV download",
76+
"linked data",
77+
"research opportunities"
78+
],
79+
"alternateName": [
80+
"Yourself to Science Catalogue",
81+
"Yourself to Science Database"
82+
],
83+
"creator": {
84+
"@type": "Organization",
85+
"name": "Yourself to Science",
86+
"url": "https://yourselftoscience.org",
87+
"contactPoint": {
88+
"@type": "ContactPoint",
89+
"contactType": "public engagement",
90+
"email": "hello@yourselftoscience.org"
91+
}
92+
},
93+
"license": "https://creativecommons.org/publicdomain/zero/1.0/",
94+
"isAccessibleForFree": true,
95+
"dateModified": lastUpdatedMeta.dateModified,
96+
"distribution": [
97+
{
98+
"@type": "DataDownload",
99+
"encodingFormat": "text/csv",
100+
"contentUrl": "https://yourselftoscience.org/resources.csv"
101+
},
102+
{
103+
"@type": "DataDownload",
104+
"encodingFormat": "application/json",
105+
"contentUrl": "https://yourselftoscience.org/resources.json"
106+
},
107+
{
108+
"@type": "DataDownload",
109+
"encodingFormat": "text/turtle",
110+
"contentUrl": "https://yourselftoscience.org/resources.ttl"
111+
}
112+
]
113+
};
114+
115+
return (
116+
<>
117+
<script
118+
type="application/ld+json"
119+
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
120+
/>
121+
{children}
122+
</>
123+
);
52124
}

‎src/app/data/page.js‎

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
import { resources } from '@/data/resources';
55
import wikidataStats from '@/data/wikidataStats.json';
6-
import lastUpdatedMeta from '@/data/lastUpdated.json';
7-
import { permanentDoi } from '@/data/config';
86
import WikidataIcon from '@/components/WikidataIcon';
97

108
import { FaDownload, FaCode, FaCopy, FaCheck, FaChartBar, FaTable, FaDatabase, FaRobot, FaNetworkWired, FaBook } from 'react-icons/fa';
@@ -36,62 +34,8 @@ export default function DataPage() {
3634
setTimeout(() => setCopiedUrl(null), 2500);
3735
};
3836

39-
const jsonLd = {
40-
"@context": "https://schema.org/",
41-
"@type": "Dataset",
42-
"name": "Yourself to Science Open Dataset",
43-
"description": "A curated, open-access catalog of services, platforms, and programs that allow individuals to securely contribute to scientific research with their biological and digital selves.",
44-
"url": "https://yourselftoscience.org/data",
45-
"sameAs": "https://yourselftoscience.org/resources.ttl#dataset",
46-
"identifier": [
47-
"https://yourselftoscience.org/resources.ttl#dataset",
48-
`https://doi.org/${permanentDoi}`
49-
],
50-
"keywords": [
51-
"open dataset",
52-
"CC0 dataset",
53-
"public domain data",
54-
"science data",
55-
"clinical trials data",
56-
"citizen science dataset",
57-
"JSON API",
58-
"CSV download",
59-
"linked data",
60-
"research opportunities"
61-
],
62-
"creator": {
63-
"@type": "Organization",
64-
"name": "Yourself to Science",
65-
"url": "https://yourselftoscience.org"
66-
},
67-
"license": "https://creativecommons.org/publicdomain/zero/1.0/",
68-
"isAccessibleForFree": true,
69-
"dateModified": lastUpdatedMeta.dateModified,
70-
"distribution": [
71-
{
72-
"@type": "DataDownload",
73-
"encodingFormat": "text/csv",
74-
"contentUrl": "https://yourselftoscience.org/resources.csv"
75-
},
76-
{
77-
"@type": "DataDownload",
78-
"encodingFormat": "application/json",
79-
"contentUrl": "https://yourselftoscience.org/resources.json"
80-
},
81-
{
82-
"@type": "DataDownload",
83-
"encodingFormat": "text/turtle",
84-
"contentUrl": "https://yourselftoscience.org/resources.ttl"
85-
}
86-
]
87-
};
88-
8937
return (
9038
<main className="flex-grow w-full max-w-screen-xl mx-auto px-4 py-12 md:py-16">
91-
<script
92-
type="application/ld+json"
93-
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
94-
/>
9539
<motion.div
9640
initial={{ opacity: 0, y: -20 }}
9741
animate={{ opacity: 1, y: 0 }}

‎src/app/get-involved/page.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import GetInvolvedClientPage from './GetInvolvedClientPage';
44
export const metadata = {
55
title: 'Get Involved | Yourself to Science',
66
description: 'Help build the future of citizen science. Suggest a new service, contact us, join the community discussion, or contribute to the code.',
7+
alternates: {
8+
canonical: 'https://yourselftoscience.org/get-involved',
9+
},
710
};
811

912
export default function GetInvolvedPage() {

‎src/app/layout.tsx‎

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,24 +115,45 @@ export default function RootLayout({
115115
}: Readonly<{
116116
children: React.ReactNode;
117117
}>) {
118-
const jsonLd = {
119-
"@context": "https://schema.org",
120-
"@type": "WebSite",
121-
"name": "Yourself to Science",
122-
"url": "https://yourselftoscience.org",
123-
"potentialAction": {
124-
"@type": "SearchAction",
125-
"target": "https://yourselftoscience.org/?q={search_term_string}",
126-
"query-input": "required name=search_term_string"
118+
const jsonLd = [
119+
{
120+
"@context": "https://schema.org",
121+
"@type": "WebSite",
122+
"name": "Yourself to Science",
123+
"url": "https://yourselftoscience.org",
124+
"potentialAction": {
125+
"@type": "SearchAction",
126+
"target": "https://yourselftoscience.org/?q={search_term_string}",
127+
"query-input": "required name=search_term_string"
128+
},
129+
"sameAs": [
130+
"https://github.com/yourselftoscience/yourselftoscience.org/",
131+
"https://www.reddit.com/r/YourselfToScience/",
132+
"https://x.com/YouToScience",
133+
"https://www.linkedin.com/company/yourselftoscience/",
134+
"https://www.facebook.com/61584505973946/"
135+
]
127136
},
128-
"sameAs": [
129-
"https://github.com/yourselftoscience/yourselftoscience.org/",
130-
"https://www.reddit.com/r/YourselfToScience/",
131-
"https://x.com/YouToScience",
132-
"https://www.linkedin.com/company/yourselftoscience/",
133-
"https://www.facebook.com/61584505973946/"
134-
]
135-
};
137+
{
138+
"@context": "https://schema.org",
139+
"@type": "Organization",
140+
"name": "Yourself to Science",
141+
"url": "https://yourselftoscience.org",
142+
"logo": "https://yourselftoscience.org/logo-tm.svg",
143+
"sameAs": [
144+
"https://github.com/yourselftoscience/yourselftoscience.org/",
145+
"https://www.reddit.com/r/YourselfToScience/",
146+
"https://x.com/YouToScience",
147+
"https://www.linkedin.com/company/yourselftoscience/",
148+
"https://www.facebook.com/61584505973946/"
149+
],
150+
"contactPoint": {
151+
"@type": "ContactPoint",
152+
"contactType": "public engagement",
153+
"email": "hello@yourselftoscience.org"
154+
}
155+
}
156+
];
136157

137158
return (
138159
// Keep suppressHydrationWarning on html for good measure

‎src/app/organ-body-tissue-donation/page.js‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ import OrganBodyTissueDonationSkeleton from './OrganBodyTissueDonationSkeleton.j
66
export const metadata = {
77
title: 'Find Organ, Body, and Tissue Donation Programs | Yourself to Science',
88
description: 'A curated catalogue of programs for organ, body, and tissue donation for scientific research. Find opportunities to contribute by location.',
9+
alternates: {
10+
canonical: 'https://yourselftoscience.org/organ-body-tissue-donation',
11+
},
12+
openGraph: {
13+
title: 'Find Organ, Body, and Tissue Donation Programs | Yourself to Science',
14+
description: 'A curated catalogue of programs for organ, body, and tissue donation for scientific research.',
15+
url: 'https://yourselftoscience.org/organ-body-tissue-donation',
16+
type: 'website',
17+
},
918
};
1019

1120
export default function OrganBodyTissueDonationPage() {

‎src/app/resource/[slug]/page.js‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,18 @@ export default function ResourcePage({ params }) {
118118
]
119119
})) : undefined,
120120
'isAccessibleForFree': true,
121-
...(resource.resourceWikidataId && { 'sameAs': `https://www.wikidata.org/wiki/${resource.resourceWikidataId}` }),
121+
'sameAs': [
122+
resource.link,
123+
...(resource.resourceWikidataId ? [`https://www.wikidata.org/wiki/${resource.resourceWikidataId}`] : [])
124+
],
125+
...(resource.wikidataLabel && resource.wikidataLabel !== resource.title && { 'alternateName': [resource.title] }),
122126
...(resource.dataTypes && resource.dataTypes.length > 0 && { 'keywords': resource.dataTypes }),
127+
...(resource.countries && resource.countries.length > 0 && resource.countries[0] !== 'Worldwide' && {
128+
'spatialCoverage': resource.countries.map(c => ({
129+
'@type': 'Place',
130+
'name': c
131+
}))
132+
}),
123133
...(resource.citations && resource.citations.length > 0 && { 'citation': resource.citations.map(c => c.link || c.title) })
124134
};
125135

@@ -154,12 +164,26 @@ export default function ResourcePage({ params }) {
154164
}
155165
};
156166

167+
const breadcrumbLd = {
168+
'@context': 'https://schema.org',
169+
'@type': 'BreadcrumbList',
170+
'itemListElement': [
171+
{ '@type': 'ListItem', 'position': 1, 'name': 'Home', 'item': 'https://yourselftoscience.org' },
172+
{ '@type': 'ListItem', 'position': 2, 'name': 'Catalogue', 'item': 'https://yourselftoscience.org/resources' },
173+
{ '@type': 'ListItem', 'position': 3, 'name': displayTitle }
174+
]
175+
};
176+
157177
return (
158178
<main className="max-w-4xl mx-auto py-12 px-4 sm:px-6 lg:px-8">
159179
<script
160180
type="application/ld+json"
161181
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
162182
/>
183+
<script
184+
type="application/ld+json"
185+
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbLd) }}
186+
/>
163187
{/* Breadcrumb Navigation */}
164188
<nav aria-label="breadcrumb" className="mb-8 text-sm">
165189
<ol className="flex items-center space-x-2 text-gray-600 flex-wrap">
@@ -539,7 +563,7 @@ export default function ResourcePage({ params }) {
539563
</div>
540564

541565
<div className="mt-6 text-sm">
542-
<a href={`mailto:science@yourselftoscience.org?subject=Claim%20Record%3A%20${encodeURIComponent(resource.title)}`} className="text-indigo-700 hover:text-indigo-900 hover:underline font-semibold inline-flex items-center">
566+
<a href={`mailto:hello@yourselftoscience.org?subject=Claim%20Record%3A%20${encodeURIComponent(resource.title)}`} className="text-indigo-700 hover:text-indigo-900 hover:underline font-semibold inline-flex items-center">
543567
Are you affiliated with this project? Claim or update this record <FaArrowRight className="ml-2 w-3 h-3" />
544568
</a>
545569
</div>

‎src/app/robots.ts‎

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)