- /docs subpages canonicalized to /docs and had no descriptions; each now uses pageMetadata with its own path (was: Google could index at most one) - llms.txt claimed Team EUR 149, RBAC/SLA and BYO-cloud that do not exist; regenerated from lib/seo.ts truth + new llms-full.txt with docs content - sitemap stamped lastModified=now on every request; now real per-route dates from new lib/articles.ts registry (single source for guides index/sitemap/RSS) - new /feed.xml RSS 2.0 route + alternates link in root layout - articleJsonLd: image (per-guide opengraph-image via lib/og-article.tsx), Person author, wordCount; new breadcrumbJsonLd on guides + docs - GSC verification via NEXT_PUBLIC_GSC_VERIFICATION (documented in .env.example) - dropped fabricated Enterprise EUR 499 offer from SoftwareApplication JSON-LD - article-shell: OL/Table/Note primitives for upcoming articles Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SXUwmPVRTD8AKQtio6gCN5
59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
import { JsonLd } from '@/components/json-ld';
|
|
import { articlesNewestFirst } from '@/lib/articles';
|
|
import { breadcrumbJsonLd, pageMetadata } from '@/lib/seo';
|
|
import Link from 'next/link';
|
|
|
|
export const metadata = pageMetadata({
|
|
title: 'MCP guides',
|
|
description:
|
|
'Practical guides on hosting, securing and shipping Model Context Protocol (MCP) servers — OAuth 2.1, remote transport, platform comparisons.',
|
|
path: '/guides',
|
|
});
|
|
|
|
export default function GuidesIndex() {
|
|
const guides = articlesNewestFirst();
|
|
return (
|
|
<div className="mx-auto max-w-3xl px-6 py-14">
|
|
<JsonLd
|
|
data={breadcrumbJsonLd([
|
|
{ name: 'Home', path: '/' },
|
|
{ name: 'Guides', path: '/guides' },
|
|
])}
|
|
/>
|
|
<h1 className="text-[28px] font-semibold tracking-tight text-[--color-fg]">MCP guides</h1>
|
|
<p className="mt-2 text-[14.5px] leading-relaxed text-[--color-fg-muted]">
|
|
Hosting, auth and shipping for Model Context Protocol servers — written for people building
|
|
real tools, not demos.
|
|
</p>
|
|
<div className="mt-8 space-y-3">
|
|
{guides.map((g) => (
|
|
<Link
|
|
key={g.slug}
|
|
href={`/guides/${g.slug}`}
|
|
className="block rounded-lg border border-[--color-border] p-4 transition-colors hover:bg-[--color-bg-subtle]"
|
|
>
|
|
<div className="flex items-center gap-2.5">
|
|
<span className="mono text-[10.5px] uppercase tracking-wider text-[--color-fg-subtle]">
|
|
{g.tag}
|
|
</span>
|
|
<span className="text-[10.5px] text-[--color-fg-subtle]">
|
|
{new Date(g.dateModified ?? g.datePublished).toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'short',
|
|
day: 'numeric',
|
|
})}
|
|
</span>
|
|
</div>
|
|
<h2 className="mt-1 text-[16px] font-semibold tracking-tight text-[--color-fg]">
|
|
{g.title}
|
|
</h2>
|
|
<p className="mt-1.5 text-[13px] leading-relaxed text-[--color-fg-muted]">
|
|
{g.description}
|
|
</p>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|