Skip to content

Commit

Permalink
Add breadcrumbs and navigation structured data (#410)
Browse files Browse the repository at this point in the history
  • Loading branch information
ReeceHumphreys authored Dec 8, 2023
1 parent 048237c commit bf063e0
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 35 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ NEXT_PUBLIC_GA_MEASUREMENT_ID=G-2D9VN5WR6Z
NEXT_PUBLIC_ALGOLIA_APP_ID=CQS6UA9C70
NEXT_PUBLIC_ALGOLIA_SEARCH_KEY=ef679b476514ba6905fc1140c7781f48
NEXT_PUBLIC_API_HOST=https://docs.icerpc.dev
NEXT_PUBLIC_BASE_URL=https://docs.icerpc.dev
57 changes: 57 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Analytics } from '@/components/analytics';
import { Inter } from 'next/font/google';
import clsx from 'clsx';
import { Metadata } from 'next';
import Script from 'next/script';

const inter = Inter({ subsets: ['latin', 'latin-ext'] });

Expand Down Expand Up @@ -53,6 +54,57 @@ export const metadata: Metadata = {
metadataBase: new URL('https://docs.icerpc.dev')
};

const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;
const schema = {
'@context': 'http://schema.org',
'@type': 'ItemList',
itemListElement: [
{
'@type': 'SiteNavigationElement',
position: 1,
name: 'Home',
description: 'Welcome to the IceRPC Docs.',
url: new URL('/', baseUrl).href
},
{
'@type': 'SiteNavigationElement',
position: 2,
name: 'Getting Started',
description: 'Quickly get up and running with IceRPC.',
url: new URL('/getting-started', baseUrl).href
},
{
'@type': 'SiteNavigationElement',
position: 3,
name: 'IceRPC',
description: 'A modular RPC framework built for QUIC.',
url: new URL('/icerpc', baseUrl).href
},
{
'@type': 'SiteNavigationElement',
position: 4,
name: 'Slice',
description: 'A modern IDL and serialization format.',
url: new URL('/slice2', baseUrl).href
},
{
'@type': 'SiteNavigationElement',
position: 5,
name: 'Protobuf',
description: 'Using Protocol Buffers with IceRPC.',
url: new URL('/protobuf', baseUrl).href
},
{
'@type': 'SiteNavigationElement',
position: 6,
name: 'IceRPC for Ice users',
description:
'How IceRPC relates to Ice, and how to use IceRPC and Ice together.',
url: new URL('/icerpc-for-ice-users', baseUrl).href
}
]
};

export default function RootLayout(props: any) {
return (
<html lang="en" suppressHydrationWarning>
Expand All @@ -76,6 +128,11 @@ export default function RootLayout(props: any) {
<Analytics />
</PathProvider>
</ThemeProvider>
<Script
id="navigation-structured-data"
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
{/* Fix for issue #368 - see discussion at https://github.com/algolia/docsearch/issues/1260 */}
<div className="fixed">
<input type="text" />
Expand Down
90 changes: 55 additions & 35 deletions components/breadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,71 @@
import React from 'react';
import Link from 'next/link';
import clsx from 'clsx';
import Script from 'next/script';

export type Breadcrumb = {
name: string;
href: string;
};

type Props = { breadcrumbs: Breadcrumb[] };
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL;

export const Breadcrumbs = ({ breadcrumbs }: Props) => {
const schema = {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: breadcrumbs.map((crumb, index) => ({
'@type': 'ListItem',
position: index + 1, // Schema.org position is 1-based.
name: crumb.name,
item: new URL(crumb.href, baseUrl).href
}))
};

return (
<ol className="hidden justify-start p-0 text-sm md:flex">
{breadcrumbs.map((crumb, index) => {
const name = crumb.name;
const href = crumb.href;
const isLast = crumb === breadcrumbs[breadcrumbs.length - 1];
<>
<ol className="hidden justify-start p-0 text-sm md:flex">
{breadcrumbs.map((crumb, index) => {
const name = crumb.name;
const href = crumb.href;
const isLast = crumb === breadcrumbs[breadcrumbs.length - 1];

return (
<li
key={name}
className={clsx(
'mb-0 flex flex-row items-center gap-2',
index == 0 && 'pl-1'
)}
>
<Link href={href} className="dark:text-white/80">
{name}
</Link>
{!isLast ? (
<svg
fill="none"
height="22"
shapeRendering="geometricPrecision"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
viewBox="0 0 24 24"
className="-mx-2 text-[#64748b5b] dark:text-white/60"
>
<path d="M16.88 3.549L7.12 20.451"></path>
</svg>
) : null}
</li>
);
})}
</ol>
return (
<li
key={name}
className={clsx(
'mb-0 flex flex-row items-center gap-2',
index == 0 && 'pl-1'
)}
>
<Link href={href} className="dark:text-white/80">
{name}
</Link>
{!isLast ? (
<svg
fill="none"
height="22"
shapeRendering="geometricPrecision"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
viewBox="0 0 24 24"
className="-mx-2 text-[#64748b5b] dark:text-white/60"
>
<path d="M16.88 3.549L7.12 20.451"></path>
</svg>
) : null}
</li>
);
})}
</ol>
<Script
id="bread-crumb-structured-data"
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(schema) }}
/>
</>
);
};

0 comments on commit bf063e0

Please sign in to comment.