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
21 changes: 21 additions & 0 deletions app/app/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,31 @@ export const metadata: Metadata = {
export default function BlogIndexPage() {
const posts = getAllPosts()

const blogJsonLd = {
'@context': 'https://schema.org',
'@type': 'Blog',
name: 'Knowcap Blog',
url: 'https://knowcap.ai/blog',
description:
'Case studies, comparisons, and field notes from the trust layer for AI agents.',
publisher: { '@type': 'Organization', name: 'Knowcap', url: 'https://knowcap.ai' },
blogPost: posts.map((post) => ({
'@type': 'BlogPosting',
headline: post.title,
description: post.description,
datePublished: post.date,
url: `https://knowcap.ai/blog/${post.slug}`,
})),
}

return (
<EditorialShell>
<div className="kb-root">
<style dangerouslySetInnerHTML={{ __html: BLOG_CSS }} />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(blogJsonLd) }}
/>

<header className="kb-index-head">
<div className="kb-index-head-inner">
Expand Down
12 changes: 12 additions & 0 deletions app/app/book/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Book a Knowcap Demo — 20 Minutes',
description:
'See Knowcap turn a real meeting into verified evidence and agent actions — Odoo tickets, GitHub PRs, follow-ups. Book a 20-minute walkthrough.',
alternates: { canonical: 'https://knowcap.ai/book' },
}

export default function BookLayout({ children }: { children: React.ReactNode }) {
return children
}
12 changes: 12 additions & 0 deletions app/app/careers/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Careers at Knowcap — Join the Team',
description:
'Build the trust layer for AI agents. Open roles at Knowcap across engineering, product, and go-to-market — remote-friendly, MENA-rooted.',
alternates: { canonical: 'https://knowcap.ai/careers' },
}

export default function CareersLayout({ children }: { children: React.ReactNode }) {
return children
}
7 changes: 7 additions & 0 deletions app/app/compare/knowcap-vs-fellow/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { compareMetadata } from '@/lib/compare-seo'

export const metadata = compareMetadata('fellow')

export default function CompareFellowLayout({ children }: { children: React.ReactNode }) {
return children
}
2 changes: 2 additions & 0 deletions app/app/compare/knowcap-vs-fellow/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Link from 'next/link'
import EditorialShell, { PageHero } from '@/components/editorial/shell'
import { COMPARE_CSS } from '../compare-styles'
import CompareJsonLd from '@/components/compare/compare-json-ld'

const COMPETITOR = 'Fellow.app'
const COMPETITOR_SLUG = 'fellow'
Expand Down Expand Up @@ -63,6 +64,7 @@ export default function ComparePage() {
return (
<>
<style dangerouslySetInnerHTML={{ __html: COMPARE_CSS }} />
<CompareJsonLd slug="fellow" competitor={COMPETITOR} faqs={FAQS} />
<EditorialShell>
<PageHero
kicker={`Comparison · Knowcap vs ${COMPETITOR}`}
Expand Down
7 changes: 7 additions & 0 deletions app/app/compare/knowcap-vs-fireflies/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { compareMetadata } from '@/lib/compare-seo'

export const metadata = compareMetadata('fireflies')

export default function CompareFirefliesLayout({ children }: { children: React.ReactNode }) {
return children
}
2 changes: 2 additions & 0 deletions app/app/compare/knowcap-vs-fireflies/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import Link from 'next/link'
import EditorialShell, { PageHero } from '@/components/editorial/shell'
import { COMPARE_CSS } from '../compare-styles'
import CompareJsonLd from '@/components/compare/compare-json-ld'

const COMPETITOR = 'Fireflies.ai'
const COMPETITOR_SLUG = 'fireflies'
Expand Down Expand Up @@ -61,6 +62,7 @@ export default function ComparePage() {
return (
<>
<style dangerouslySetInnerHTML={{ __html: COMPARE_CSS }} />
<CompareJsonLd slug="fireflies" competitor={COMPETITOR} faqs={FAQS} />
<EditorialShell>
<PageHero
kicker={`Comparison · Knowcap vs ${COMPETITOR}`}
Expand Down
7 changes: 7 additions & 0 deletions app/app/compare/knowcap-vs-granola/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { compareMetadata } from '@/lib/compare-seo'

export const metadata = compareMetadata('granola')

export default function CompareGranolaLayout({ children }: { children: React.ReactNode }) {
return children
}
2 changes: 2 additions & 0 deletions app/app/compare/knowcap-vs-granola/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Link from 'next/link'
import EditorialShell, { PageHero } from '@/components/editorial/shell'
import { COMPARE_CSS } from '../compare-styles'
import CompareJsonLd from '@/components/compare/compare-json-ld'

const COMPETITOR = 'Granola.ai'
const COMPETITOR_SLUG = 'granola'
Expand Down Expand Up @@ -60,6 +61,7 @@ export default function ComparePage() {
return (
<>
<style dangerouslySetInnerHTML={{ __html: COMPARE_CSS }} />
<CompareJsonLd slug="granola" competitor={COMPETITOR} faqs={FAQS} />
<EditorialShell>
<PageHero
kicker={`Comparison · Knowcap vs ${COMPETITOR}`}
Expand Down
7 changes: 7 additions & 0 deletions app/app/compare/knowcap-vs-otter/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { compareMetadata } from '@/lib/compare-seo'

export const metadata = compareMetadata('otter')

export default function CompareOtterLayout({ children }: { children: React.ReactNode }) {
return children
}
2 changes: 2 additions & 0 deletions app/app/compare/knowcap-vs-otter/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Link from 'next/link'
import EditorialShell, { PageHero } from '@/components/editorial/shell'
import { COMPARE_CSS } from '../compare-styles'
import CompareJsonLd from '@/components/compare/compare-json-ld'

const COMPETITOR = 'Otter.ai'
const COMPETITOR_SLUG = 'otter'
Expand Down Expand Up @@ -60,6 +61,7 @@ export default function ComparePage() {
return (
<>
<style dangerouslySetInnerHTML={{ __html: COMPARE_CSS }} />
<CompareJsonLd slug="otter" competitor={COMPETITOR} faqs={FAQS} />
<EditorialShell>
<PageHero
kicker={`Comparison · Knowcap vs ${COMPETITOR}`}
Expand Down
7 changes: 7 additions & 0 deletions app/app/compare/knowcap-vs-read-ai/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { compareMetadata } from '@/lib/compare-seo'

export const metadata = compareMetadata('read-ai')

export default function CompareReadAiLayout({ children }: { children: React.ReactNode }) {
return children
}
2 changes: 2 additions & 0 deletions app/app/compare/knowcap-vs-read-ai/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Link from 'next/link'
import EditorialShell, { PageHero } from '@/components/editorial/shell'
import { COMPARE_CSS } from '../compare-styles'
import CompareJsonLd from '@/components/compare/compare-json-ld'

const COMPETITOR = 'Read.ai'
const COMPETITOR_SLUG = 'read-ai'
Expand Down Expand Up @@ -61,6 +62,7 @@ export default function ComparePage() {
return (
<>
<style dangerouslySetInnerHTML={{ __html: COMPARE_CSS }} />
<CompareJsonLd slug="read-ai" competitor={COMPETITOR} faqs={FAQS} />
<EditorialShell>
<PageHero
kicker={`Comparison · Knowcap vs ${COMPETITOR}`}
Expand Down
12 changes: 12 additions & 0 deletions app/app/contact-us/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Contact Knowcap — Talk to the Team',
description:
'Questions about Knowcap, partnerships, or a demo for your Odoo practice, agency, or audit firm? Reach the team and we will get back to you.',
alternates: { canonical: 'https://knowcap.ai/contact-us' },
}

export default function ContactLayout({ children }: { children: React.ReactNode }) {
return children
}
1 change: 1 addition & 0 deletions app/app/for/odoo-partners/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const metadata = {
title: 'Knowcap for Odoo implementation partners — From client meeting to Odoo SH PR before the meeting ends',
description:
'Your client mentions a bug or asks for a feature mid-meeting. Knowcap captures it, classifies it, and waits for one tap. Then an Odoo SH ticket opens, a GitHub PR appears, and your tracker advances — before the call wraps.',
alternates: { canonical: 'https://knowcap.ai/for/odoo-partners' },
}

export default function PageForOdooPartners() {
Expand Down
5 changes: 5 additions & 0 deletions app/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,16 @@ const jetbrainsMono = JetBrains_Mono({ subsets: ['latin'], variable: '--font-mon
const ebGaramond = EB_Garamond({ subsets: ['latin'], variable: '--font-serif' })

export const metadata: Metadata = {
metadataBase: new URL('https://knowcap.ai'),
title: 'Knowcap — The Trust Layer for AI Agents',
description: 'Turn human claims into evidence your AI agents can learn from. Capture meetings, messages, and recordings. Promote the durable parts to evidence. Let agents act on what\'s verified.',
icons: {
icon: '/favicon.ico',
},
openGraph: {
siteName: 'Knowcap',
type: 'website',
},
}

export default function RootLayout({
Expand Down
51 changes: 50 additions & 1 deletion app/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,50 @@
import HomeCommitment from '@/components/home-commitment'
import { getAllPosts } from '@/lib/blog'
import type { Metadata } from 'next'

// Homepage — Commitment Ledger edition (full replacement, 2026-06-10).
// The B-vs-D middleware rotation is retired; /a /b /c /d remain reachable
// for reference. Copy: docs/content-pipeline/drafts/homepage-commitment-copy.md
export const metadata: Metadata = {
alternates: { canonical: 'https://knowcap.ai/' },
openGraph: {
title: 'Knowcap — The Trust Layer for AI Agents',
description:
'Turn human claims into evidence your AI agents can act on. Capture meetings, messages, and recordings — promote the verified parts to evidence agents can use.',
url: 'https://knowcap.ai',
type: 'website',
},
}

// Organization + WebSite + SoftwareApplication schema for the homepage —
// gives crawlers and AI search the brand entity, site identity, and product
// facts that were missing before the 2026-06-14 SEO audit.
const HOME_JSON_LD = [
{
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Knowcap',
url: 'https://knowcap.ai',
logo: 'https://knowcap.ai/knowcap-logo.png',
description: 'The trust layer for AI agents — human-verified meeting and message intelligence.',
},
{
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'Knowcap',
url: 'https://knowcap.ai',
},
{
'@context': 'https://schema.org',
'@type': 'SoftwareApplication',
name: 'Knowcap',
applicationCategory: 'BusinessApplication',
operatingSystem: 'Web',
url: 'https://knowcap.ai',
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
},
]

export default function Home() {
const recentPosts = getAllPosts()
.slice(0, 3)
Expand All @@ -14,5 +55,13 @@ export default function Home() {
description: p.description,
readMinutes: p.readMinutes,
}))
return <HomeCommitment recentPosts={recentPosts} />
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(HOME_JSON_LD) }}
/>
<HomeCommitment recentPosts={recentPosts} />
</>
)
}
12 changes: 12 additions & 0 deletions app/app/policy/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Privacy Policy — Knowcap',
description:
'How Knowcap collects, uses, stores, and protects your data — and the controls you have over meeting recordings, transcripts, and verified evidence.',
alternates: { canonical: 'https://knowcap.ai/policy' },
}

export default function PolicyLayout({ children }: { children: React.ReactNode }) {
return children
}
12 changes: 12 additions & 0 deletions app/app/terms/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Terms of Service — Knowcap',
description:
'The terms that govern your use of Knowcap — accounts, acceptable use, billing, and the responsibilities of the trust layer for your AI agents.',
alternates: { canonical: 'https://knowcap.ai/terms' },
}

export default function TermsLayout({ children }: { children: React.ReactNode }) {
return children
}
61 changes: 61 additions & 0 deletions app/components/compare/compare-json-ld.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { compareUrl, type CompareSlug } from '@/lib/compare-seo'

/**
* Emits FAQPage + SoftwareApplication + BreadcrumbList JSON-LD for a
* /compare/* page. Rendered inside the (client) compare page body — client
* components still server-render on first paint, so the script lands in the
* initial HTML where crawlers read it.
*
* Closes the "no schema on compare pages" gap from the 2026-06-14 SEO audit.
*/
export default function CompareJsonLd({
slug,
competitor,
faqs,
}: {
slug: CompareSlug
competitor: string
faqs: { q: string; a: string }[]
}) {
const url = compareUrl(slug)

const jsonLd: Record<string, unknown>[] = [
{
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: [
{ '@type': 'ListItem', position: 1, name: 'Knowcap', item: 'https://knowcap.ai' },
{ '@type': 'ListItem', position: 2, name: 'Compare', item: 'https://knowcap.ai/compare' },
{ '@type': 'ListItem', position: 3, name: `Knowcap vs ${competitor}`, item: url },
],
},
{
'@context': 'https://schema.org',
'@type': 'SoftwareApplication',
name: 'Knowcap',
applicationCategory: 'BusinessApplication',
operatingSystem: 'Web',
url: 'https://knowcap.ai',
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
},
]

if (faqs.length > 0) {
jsonLd.push({
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: faqs.map((f) => ({
'@type': 'Question',
name: f.q,
acceptedAnswer: { '@type': 'Answer', text: f.a },
})),
})
}

return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
)
}
Loading