diff --git a/app/app/blog/[slug]/page.tsx b/app/app/blog/[slug]/page.tsx new file mode 100644 index 0000000..c7adfe8 --- /dev/null +++ b/app/app/blog/[slug]/page.tsx @@ -0,0 +1,148 @@ +import type { Metadata } from 'next' +import Link from 'next/link' +import { notFound } from 'next/navigation' +import { getAllPosts, getPost } from '@/lib/blog' +import { BLOG_CSS } from '../blog-styles' + +export function generateStaticParams() { + return getAllPosts().map((p) => ({ slug: p.slug })) +} + +export function generateMetadata({ params }: { params: { slug: string } }): Metadata { + const post = getPost(params.slug) + if (!post) return {} + const url = `https://knowcap.ai/blog/${post.slug}` + return { + title: `${post.title} — Knowcap Blog`, + description: post.description, + alternates: { canonical: url }, + openGraph: { + title: post.title, + description: post.description, + url, + type: 'article', + publishedTime: post.date, + authors: [post.author], + }, + } +} + +const RELATED_LABELS: Record = { + '/for/odoo-partners': 'For Odoo Partners', + '/compare/knowcap-vs-otter': 'Knowcap vs Otter', + '/compare/knowcap-vs-read-ai': 'Knowcap vs Read AI', + '/compare/knowcap-vs-fireflies': 'Knowcap vs Fireflies', + '/compare/knowcap-vs-fellow': 'Knowcap vs Fellow', + '/compare/knowcap-vs-granola': 'Knowcap vs Granola', +} + +export default function BlogPostPage({ params }: { params: { slug: string } }) { + const post = getPost(params.slug) + if (!post) notFound() + + const jsonLd: Record[] = [ + { + '@context': 'https://schema.org', + '@type': 'BlogPosting', + headline: post.title, + description: post.description, + datePublished: post.date, + author: { '@type': 'Person', name: post.author }, + publisher: { '@type': 'Organization', name: 'Knowcap', url: 'https://knowcap.ai' }, + mainEntityOfPage: `https://knowcap.ai/blog/${post.slug}`, + keywords: post.tags.join(', '), + }, + ] + if (post.faqs.length > 0) { + jsonLd.push({ + '@context': 'https://schema.org', + '@type': 'FAQPage', + mainEntity: post.faqs.map((f) => ({ + '@type': 'Question', + name: f.q, + acceptedAnswer: { '@type': 'Answer', text: f.a }, + })), + }) + } + + return ( +
+