Skip to content
Merged
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
1 change: 1 addition & 0 deletions docs/toolhive/guides-cli/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: 'Quickstart: ToolHive CLI'
sidebar_label: Quickstart
description: Install the ToolHive CLI and run your first MCP server in minutes.
schema_type: tutorial
---

In this tutorial, you'll install the ToolHive command-line application and run
Expand Down
1 change: 1 addition & 0 deletions docs/toolhive/guides-k8s/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sidebar_label: Quickstart
description:
Deploy the ToolHive Kubernetes Operator and run your first MCP server in a
cluster.
schema_type: tutorial
---

import useBaseUrl from '@docusaurus/useBaseUrl';
Expand Down
1 change: 1 addition & 0 deletions docs/toolhive/guides-ui/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: 'Quickstart: ToolHive UI'
sidebar_label: Quickstart
description:
Install the ToolHive desktop app and run your first MCP server in minutes.
schema_type: tutorial
---

In this tutorial, you'll install the ToolHive desktop application and run your
Expand Down
1 change: 1 addition & 0 deletions docs/toolhive/tutorials/custom-registry.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Create a custom MCP registry
description:
Create a custom MCP server registry with curated servers for your team or
organization.
schema_type: tutorial
---

## Overview
Expand Down
1 change: 1 addition & 0 deletions docs/toolhive/tutorials/mcp-optimizer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: Reduce token usage with MCP Optimizer
description:
Enable the MCP Optimizer to enhance tool selection and reduce token usage.
schema_type: tutorial
---

## Overview
Expand Down
3 changes: 3 additions & 0 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ const config: Config = {
sidebarPath: './sidebars.ts',
// Remove this to remove the "edit this page" links.
editUrl: 'https://github.com/stacklok/docs-website/tree/main/',
// Populate lastUpdatedAt metadata for JSON-LD structured data.
// The rendered timestamp is hidden via CSS (.theme-last-updated).
showLastUpdateTime: true,
},
blog: {
blogTitle: 'ToolHive Updates and Announcements',
Expand Down
7 changes: 7 additions & 0 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ html[data-theme='dark'] {
--docusaurus-highlighted-code-line-bg: rgba(66, 66, 66, 0.35);
}

/* Hide "Last updated" text rendered by DocItem/Footer.
The underlying lastUpdatedAt metadata is still populated
and used by the DocItem/Layout wrapper for JSON-LD. */
.theme-last-updated {
display: none;
}

thead th {
font-size: 0.875rem;
}
Expand Down
57 changes: 57 additions & 0 deletions src/theme/DocItem/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { type ReactNode } from 'react';
import Layout from '@theme-original/DocItem/Layout';
import type LayoutType from '@theme/DocItem/Layout';
import type { WrapperProps } from '@docusaurus/types';
import Head from '@docusaurus/Head';
import { useDoc } from '@docusaurus/plugin-content-docs/client';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';

type Props = WrapperProps<typeof LayoutType>;

function useStructuredData() {
const { metadata, frontMatter } = useDoc();
const { siteConfig } = useDocusaurusContext();

const schema: Record<string, unknown> = {
'@context': 'https://schema.org',
'@type': 'TechArticle',
headline: metadata.title,
description: metadata.description,
url: new URL(metadata.permalink, siteConfig.url).toString(),
inLanguage: 'en',
publisher: {
'@type': 'Organization',
'@id': 'https://stacklok.com/#organization',
},
isPartOf: {
'@type': 'WebSite',
'@id': 'https://stacklok.com/#website',
},
};

if (metadata.lastUpdatedAt) {
schema.dateModified = new Date(metadata.lastUpdatedAt).toISOString();
}

// Allow frontmatter to signal tutorial content
if ((frontMatter as Record<string, unknown>).schema_type === 'tutorial') {
schema.learningResourceType = 'tutorial';
}

return schema;
}

export default function LayoutWrapper(props: Props): ReactNode {
const schema = useStructuredData();

return (
<>
<Head>
<script type='application/ld+json' id='techarticle-schema'>
{JSON.stringify(schema)}
</script>
</Head>
<Layout {...props} />
</>
);
}