Skip to content

Commit

Permalink
fix: breadcrumb bad path
Browse files Browse the repository at this point in the history
  • Loading branch information
thedaviddias committed Feb 11, 2025
1 parent b467505 commit 3e0aeb1
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 43 deletions.
91 changes: 50 additions & 41 deletions app/[lang]/[[...mdxPath]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable react-hooks/rules-of-hooks -- false positive, useMDXComponents are not react hooks */

import { BASE_URL } from '@/app/_constants/project'
import { JsonLd, generateArticleSchema } from '@app/_components/json-ld'
import { generateBreadcrumbSchema } from '@app/_utils/generate-breadcrumb-schema'
import { Metadata } from 'next'
Expand All @@ -9,38 +8,49 @@ import { useMDXComponents } from '../../../mdx-components'

export const generateStaticParams = generateStaticParamsFor('mdxPath')

export async function generateMetadata(props: PageProps): Promise<Metadata | null> {
try {
const params = await props.params
const { metadata } = await importPage(params.mdxPath || [], params.lang)
const isHomepage = !params.mdxPath || params.mdxPath.length === 0
export async function generateMetadata({ params }): Promise<Metadata> {
const { frontMatter, metadata } = await importPage(params.mdxPath || [], params.lang)
const isHomepage = !params.mdxPath || params.mdxPath.length === 0
const baseUrl = 'https://uxpatterns.dev'
const path = params.mdxPath?.join('/') || ''

// Include the language prefix in the canonical path
const canonicalPath = `/${params.lang}${params.mdxPath ? `/${params.mdxPath.join('/')}` : ''}`
// Shared metadata
const title = frontMatter?.title || metadata?.title || 'UX Patterns for Devs'
const description = frontMatter?.description || metadata?.description || ''
const summary = frontMatter?.summary || ''

const ogImage = {
url: isHomepage
? '/og/opengraph-image.png'
: `/api/og?title=${encodeURIComponent(metadata.title || '')}`,
width: 1200,
height: 630,
type: 'image/png',
}
// OG image handling
const isPatternPage = params.mdxPath?.[0] === 'patterns'
const patternName = isPatternPage ? params.mdxPath?.[params.mdxPath.length - 1] : null
const ogImageUrl = isHomepage
? '/og/opengraph-image.png'
: `/api/og?title=${encodeURIComponent(title)}`

return {
...metadata,
openGraph: {
...metadata.openGraph,
images: [ogImage],
url: `${BASE_URL}${canonicalPath}`
},
alternates: {
canonical: `${BASE_URL}${canonicalPath}`
}
}
} catch (e) {
console.error('Error generating metadata:', e)
return null
return {
title,
description,
openGraph: {
title,
description,
type: 'article',
images: [
...(isPatternPage && patternName ? [{
url: `/covers/patterns/${patternName}.png`,
width: 800,
height: 400,
alt: `${summary} - UX Pattern`,
}] : []),
{
url: ogImageUrl,
width: 1200,
height: 630,
alt: description || title,
},
],
},
alternates: {
canonical: `${baseUrl}/${params.lang}${path ? `/${path}` : ''}`,
},
}
}

Expand All @@ -55,26 +65,25 @@ const Wrapper = useMDXComponents().wrapper

export default async function Page(props: PageProps) {
const params = await props.params
const result = await importPage(params.mdxPath, params.lang)
const { default: MDXContent, toc, metadata } = result
const { default: MDXContent, toc, metadata } = await importPage(params.mdxPath, params.lang)

// Get the OG image URL from metadata
// Use the same logic for OG image as in generateMetadata
const isHomepage = !params.mdxPath || params.mdxPath.length === 0
const title = metadata?.title || 'UX Patterns for Devs'
const description = metadata?.description || ''
const ogImageUrl = isHomepage
? '/og/opengraph-image.png'
: `/api/og?title=${encodeURIComponent(metadata.title || '')}`
: `/api/og?title=${encodeURIComponent(title)}`

const schemaData = generateArticleSchema(
metadata.title || '',
metadata.description || '',
title,
description,
`/${params.lang}/${params.mdxPath?.join('/') || ''}`,
ogImageUrl
)

// Generate breadcrumb items
const breadcrumbs = [
{ title: 'Home', url: `/${params.lang}` }
]
// Generate breadcrumb items for patterns only
const breadcrumbs: Array<{ title: string; url: string }> = []

if (params.mdxPath) {
let currentPath = ''
Expand All @@ -93,7 +102,7 @@ export default async function Page(props: PageProps) {
return (
<>
<JsonLd data={schemaData} />
<JsonLd data={breadcrumbSchema} />
{breadcrumbs.length > 0 && <JsonLd data={breadcrumbSchema} />}
<div className="nextra-content">
<Wrapper key={pageKey} toc={toc} metadata={metadata}>
<MDXContent {...props} params={params} />
Expand Down
1 change: 1 addition & 0 deletions app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export default async function RootLayout({ children, params }: {
<html lang={lang} suppressHydrationWarning>
<head>
<PlausibleProvider domain="uxpatterns.dev" trackOutboundLinks={true} taggedEvents={true} />
<script src="https://analytics.ahrefs.com/analytics.js" data-key="kp+2z+UG2C+LV5KT2+/B+w" async></script>
</head>
<body className={`${fontSans.variable} ${fontMono.variable} bg-background font-sans antialiased`}>
<Layout
Expand Down
47 changes: 45 additions & 2 deletions app/_utils/generate-breadcrumb-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,54 @@ interface BreadcrumbItem {
}

export function generateBreadcrumbSchema(breadcrumbs: BreadcrumbItem[]) {
// Extract language code from the first breadcrumb that has a URL with language
const langMatch = breadcrumbs.find(crumb => crumb.url)?.url?.match(/^\/([a-z]{2})\//)
const lang = langMatch ? langMatch[1] : 'en' // Default to 'en' if no language found

// Ensure home page is always first in the breadcrumb with correct language
const homePage: BreadcrumbItem = {
title: 'Home',
url: `/${lang}`
}

// Filter breadcrumbs based on the section
const filteredBreadcrumbs = breadcrumbs.reduce((acc: BreadcrumbItem[], crumb, index) => {
// Always keep the main section (patterns, pattern-guide, etc.)
if (crumb.url?.match(/^\/[a-z]{2}\/[^/]+$/)) {
acc.push(crumb)
return acc
}

// For the patterns section, skip category level
if (crumb.url?.includes('/patterns/')) {
// If it's the last item, keep it
if (index === breadcrumbs.length - 1) {
acc.push(crumb)
}
return acc
}

// For all other sections, keep everything
acc.push(crumb)
return acc
}, [])

// Combine home page with filtered breadcrumbs
const fullBreadcrumbs = [homePage, ...filteredBreadcrumbs]

if (fullBreadcrumbs.length === 0) {
return {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": []
}
}

return {
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": breadcrumbs.map((crumb, index) => {
const isLastItem = index === breadcrumbs.length - 1
"itemListElement": fullBreadcrumbs.map((crumb, index) => {
const isLastItem = index === fullBreadcrumbs.length - 1
const baseItem = {
"@type": "ListItem",
"position": index + 1,
Expand Down

0 comments on commit 3e0aeb1

Please sign in to comment.