Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { LocaleParams } from '@/i18n/types'

import { setRequestLocale } from 'next-intl/server'

import { StructuredDataScript } from '@filecoin-foundation/ui/StructuredDataScript'
import { MarkdownContent as BaseMarkdownContent } from '@filecoin-foundation/ui-filecoin/Markdown/MarkdownContent'
import { PageSection } from '@filecoin-foundation/ui-filecoin/PageSection'
import { type SlugParams } from '@filecoin-foundation/utils/types/paramsTypes'
Expand All @@ -17,6 +18,7 @@ import { PageHeader } from '../components/PageHeader'
import { getCaseStudyData, getCaseStudiesData } from '../utils/getCaseStudyData'

import { TextCard } from './components/TextCard'
import { generateStructuredData } from './utils/generateStructuredData'

type CaseStudyArticleProps = {
params: Promise<SlugParams & LocaleParams>
Expand All @@ -27,6 +29,8 @@ export default async function CaseStudyArticle(props: CaseStudyArticleProps) {
setRequestLocale(locale)

// TODO: Add all case studies and make challenge, solution, and results required
const data = await getCaseStudyData(slug, locale)

const {
title,
pageDescription,
Expand All @@ -35,10 +39,11 @@ export default async function CaseStudyArticle(props: CaseStudyArticleProps) {
challenge,
solution,
results,
} = await getCaseStudyData(slug, locale)
} = data

return (
<>
<StructuredDataScript structuredData={generateStructuredData(data)} />
<Navigation backgroundVariant="dark" />
<PageSection backgroundVariant="dark">
<PageHeader
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PATHS } from '@/constants/paths'

import type { CaseStudy } from '../../types/caseStudyType'

import { generateCaseStudyArticleStructuredData } from '@/case-studies/utils/generateCaseStudyArticleStructuredData'

export function generateStructuredData(data: CaseStudy) {
const { title, pageDescription, image } = data
return generateCaseStudyArticleStructuredData({
path: `${PATHS.CASE_STUDIES.path}/${data.slug}`,
headline: title,
description: pageDescription,
image: image ? image.src : undefined,
})
}
8 changes: 8 additions & 0 deletions apps/filecoin-site/src/app/[locale]/case-studies/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { LocaleParams } from '@/i18n/types'

import { StructuredDataScript } from '@filecoin-foundation/ui/StructuredDataScript'
import { Button } from '@filecoin-foundation/ui-filecoin/Button'
import { CardGrid } from '@filecoin-foundation/ui-filecoin/CardGrid'
import { PageSection } from '@filecoin-foundation/ui-filecoin/PageSection'
Expand All @@ -16,6 +17,7 @@ import { SimpleCardWithLogo } from '@/components/SimpleCardWithLogo'

import { PageHeader } from './components/PageHeader'
import { CASE_STUDIES_SEO } from './constants/seo'
import { generateStructuredData } from './utils/generateStructuredData'
import { getCaseStudiesByFeaturedStatus } from './utils/getCaseStudyData'

type CaseStudiesProps = {
Expand All @@ -30,6 +32,12 @@ export default async function CaseStudies({ params }: CaseStudiesProps) {

return (
<>
<StructuredDataScript
structuredData={generateStructuredData(
CASE_STUDIES_SEO,
featuredCaseStudies,
)}
/>
<Navigation backgroundVariant="dark" />
<PageSection backgroundVariant="dark">
<PageHeader
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { getCaseStudyData } from '../utils/getCaseStudyData'

export type CaseStudy = Awaited<ReturnType<typeof getCaseStudyData>>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { Article } from 'schema-dts'

import type { ArticleGraph } from '@filecoin-foundation/ui/StructuredDataScript'
import { SCHEMA_CONTEXT_URL } from '@filecoin-foundation/utils/constants/structuredDataConstants'

import { PATHS, type NextRouteWithoutLocale } from '@/constants/paths'
import { BASE_URL } from '@/constants/siteMetadata'
import { STRUCTURED_DATA_IDS } from '@/constants/structuredDataConstants'

import { generateBreadcrumbList } from '@/utils/generateBreadcrumbsList'

type GenerateCaseStudyArticleStructuredDataProps = {
path: NextRouteWithoutLocale
headline: string
description: Article['description']
image?: Article['image']
}

export function generateCaseStudyArticleStructuredData({
path,
headline,
description,
image,
}: GenerateCaseStudyArticleStructuredDataProps): ArticleGraph {
const url = `${BASE_URL}${path}`

const caseStudyArticle: Article = {
'@type': 'Article',
headline,
description,
author: { '@id': STRUCTURED_DATA_IDS.ORGANIZATION },
publisher: { '@id': STRUCTURED_DATA_IDS.ORGANIZATION },
mainEntityOfPage: { '@id': url },
...(image && { image }),
}

return {
'@context': SCHEMA_CONTEXT_URL,
'@graph': [
caseStudyArticle,
generateBreadcrumbList({
path,
title: headline,
parentPaths: [
{ path: PATHS.CASE_STUDIES.path, title: PATHS.CASE_STUDIES.label },
],
}),
],
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import type { CollectionPage, ItemList, ListItem } from 'schema-dts'

import type { CollectionPageGraph } from '@filecoin-foundation/ui/StructuredDataScript'
import { SCHEMA_CONTEXT_URL } from '@filecoin-foundation/utils/constants/structuredDataConstants'

import { PATHS, type NextRouteWithoutLocale } from '@/constants/paths'
import { BASE_URL, ORGANIZATION_NAME } from '@/constants/siteMetadata'
import { STRUCTURED_DATA_IDS } from '@/constants/structuredDataConstants'

import { generateBreadcrumbList } from '@/utils/generateBreadcrumbsList'

type GenerateCaseStudyStructuredDataProps = {
name: string
description: string
items?: Array<{
path: NextRouteWithoutLocale
headline: string
description?: string
image?: string
}>
}

export function generateCaseStudyStructuredData({
name,
description,
items = [],
}: GenerateCaseStudyStructuredDataProps): CollectionPageGraph {
const mainEntity: ItemList | undefined =
items.length > 0
? {
'@type': 'ItemList',
name,
itemListElement: items.map<ListItem>((item, i) => ({
'@type': 'ListItem',
position: i + 1,
item: {
'@type': 'Article',
'@id': STRUCTURED_DATA_IDS.getCaseStudyId(item.path),
url: `${BASE_URL}${item.path}`,
headline: item.headline,
description: item.description,
image: item.image,
author: {
'@type': 'Organization',
name: ORGANIZATION_NAME,
url: BASE_URL,
},
publisher: {
'@type': 'Organization',
name: ORGANIZATION_NAME,
url: BASE_URL,
},
},
})),
}
: undefined

const caseStudy: CollectionPage = {
'@type': 'CollectionPage',
url: `${BASE_URL}${PATHS.CASE_STUDIES.path}`,
name,
description,
}

const graph: CollectionPageGraph['@graph'] = [
caseStudy,
...(mainEntity ? [mainEntity] : []),
generateBreadcrumbList({
path: PATHS.CASE_STUDIES.path,
title: PATHS.CASE_STUDIES.label,
}),
]

return {
'@context': SCHEMA_CONTEXT_URL,
'@graph': graph,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { CollectionPageGraph } from '@filecoin-foundation/ui/StructuredDataScript'
import type { StructuredDataParams } from '@filecoin-foundation/utils/types/structuredDataParams'

import { PATHS } from '@/constants/paths'

import type { CaseStudy } from '../types/caseStudyType'

import { generateCaseStudyStructuredData } from './generateCaseStudyStructuredData'

export function generateStructuredData(
seo: StructuredDataParams,
sortedPosts: Array<CaseStudy>,
): CollectionPageGraph {
return generateCaseStudyStructuredData({
name: seo.title,
description: seo.description,
items: sortedPosts.map((post) => ({
path: `${PATHS.CASE_STUDIES.path}/${post.slug}`,
headline: post.title,
description: post.pageDescription,
image: post.image?.src,
})),
})
}
4 changes: 4 additions & 0 deletions apps/filecoin-site/src/app/[locale]/community-hub/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Image from 'next/image'

import type { LocaleParams } from '@/i18n/types'

import { StructuredDataScript } from '@filecoin-foundation/ui/StructuredDataScript'
import { Button } from '@filecoin-foundation/ui-filecoin/Button'
import { CardGrid } from '@filecoin-foundation/ui-filecoin/CardGrid'
import { LinkCard } from '@filecoin-foundation/ui-filecoin/LinkCard'
Expand All @@ -13,6 +14,7 @@ import { getFeaturedBlogPosts } from '@filecoin-foundation/utils/getFeaturedBlog

import { PATHS } from '@/constants/paths'
import { FILECOIN_FOUNDATION_URLS } from '@/constants/siteMetadata'
import { ORGANIZATION_SCHEMA_BASE } from '@/constants/structuredDataConstants'

import { graphicsData } from '@/data/graphicsData'

Expand Down Expand Up @@ -49,6 +51,8 @@ export default async function CommunityHub({ params }: BlogProps) {

return (
<>
<StructuredDataScript structuredData={ORGANIZATION_SCHEMA_BASE} />

<div className="relative isolate">
<Navigation backgroundVariant="transparentDark" />
<PageSection backgroundVariant="transparentDark">
Expand Down
5 changes: 5 additions & 0 deletions apps/filecoin-site/src/app/[locale]/learn/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Image from 'next/image'

import { clsx } from 'clsx'

import { StructuredDataScript } from '@filecoin-foundation/ui/StructuredDataScript'
import { Button } from '@filecoin-foundation/ui-filecoin/Button'
import { Card } from '@filecoin-foundation/ui-filecoin/Card'
import { CardGrid } from '@filecoin-foundation/ui-filecoin/CardGrid'
Expand Down Expand Up @@ -29,10 +30,14 @@ import { howFilecoinWorks } from './data/howFilecoinWorks'
import { learnAboutFilecoinProtocol } from './data/learnAboutFilecoinProtocol'
import { resilientInternetCta } from './data/resilientInternetCta'
import { whatIsFilecoinUsedFor } from './data/whatIsFilecoinUsedFor'
import { generateStructuredData } from './utils/generateStructuredData'

export default function Learn() {
return (
<>
<StructuredDataScript
structuredData={generateStructuredData(LEARN_SEO)}
/>
<div className={clsx('relative isolate', backgroundVariants.dark)}>
<Navigation backgroundVariant="transparentDark" />
<PageSection backgroundVariant="transparentDark">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { WebPageGraph } from '@filecoin-foundation/ui/StructuredDataScript'
import type { StructuredDataParams } from '@filecoin-foundation/utils/types/structuredDataParams'

import { PATHS } from '@/constants/paths'

import { generatePageStructuredData } from '@/utils/generatePageStructuredData'

export function generateStructuredData(
seo: StructuredDataParams,
): WebPageGraph {
return generatePageStructuredData({
title: seo.title,
description: seo.description,
path: PATHS.LEARN.path,
pageType: 'WebPage',
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const STRUCTURED_DATA_IDS = {
BLOG: `${BASE_URL}${PATHS.BLOG.path}#blog`,
getServiceId: (path: NextRouteWithoutLocale) => `${BASE_URL}${path}#service`,
getBlogPostId: (path: string) => `${BASE_URL}${path}#post`,
getCaseStudyId: (path: string) => `${BASE_URL}${path}#case-study`,
getPageId: (path: NextRouteWithoutLocale, type: PageType) =>
`${BASE_URL}${path}#${type === 'CollectionPage' ? 'page' : 'webpage'}`,
} as const
Expand Down
34 changes: 24 additions & 10 deletions packages/ui/src/StructuredDataScript.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,15 @@ import type {
WithContext,
ItemList,
BlogPosting,
CollectionPage,
Article,
} from 'schema-dts'

import { SCHEMA_CONTEXT_URL } from '@filecoin-foundation/utils/constants/structuredDataConstants'

export type WebPageGraph = {
export type ArticleGraph = {
'@context': typeof SCHEMA_CONTEXT_URL
'@graph': Array<WebPage | BreadcrumbList>
}

export type ServicePageGraph = {
'@context': typeof SCHEMA_CONTEXT_URL
'@graph': Array<Service | BreadcrumbList>
'@graph': Array<Article | BreadcrumbList>
}

export type BlogPageGraph = {
Expand All @@ -33,19 +30,36 @@ export type BlogPostPageGraph = {
'@graph': Array<BlogPosting | BreadcrumbList>
}

export type CollectionPageGraph = {
'@context': typeof SCHEMA_CONTEXT_URL
'@graph': Array<CollectionPage | ItemList | BreadcrumbList>
}

export type OrganizationGraph = {
'@context': typeof SCHEMA_CONTEXT_URL
'@graph': readonly [Organization, WebSite]
}

export type ServicePageGraph = {
'@context': typeof SCHEMA_CONTEXT_URL
'@graph': Array<Service | BreadcrumbList>
}

export type WebPageGraph = {
'@context': typeof SCHEMA_CONTEXT_URL
'@graph': Array<WebPage | BreadcrumbList>
}

type StructuredDataScriptProps = {
structuredData:
| WithContext<Thing>
| WebPageGraph
| ServicePageGraph
| ArticleGraph
| BlogPageGraph
| BlogPostPageGraph
| CollectionPageGraph
| OrganizationGraph
| ServicePageGraph
| WebPageGraph
| WithContext<Thing>
}

export function StructuredDataScript({
Expand Down
Loading