diff --git a/apps/registry/app/layout.tsx b/apps/registry/app/layout.tsx
index 634b5176..0245f35c 100644
--- a/apps/registry/app/layout.tsx
+++ b/apps/registry/app/layout.tsx
@@ -5,6 +5,7 @@ import type { ReactNode } from 'react'
import type { Metadata } from 'next'
import { PostHogProvider } from './posthog-provider'
import { RegistryAskWidget } from '@/components/ask-widget'
+import { serializedRegistryStructuredData } from '@/lib/structured-data'
const inter = Inter({ subsets: ['latin'], variable: '--font-sans' })
const jetbrainsMono = JetBrains_Mono({ subsets: ['latin'], variable: '--font-mono' })
@@ -32,6 +33,10 @@ export default function RootLayout({ children }: { children: ReactNode }) {
+
diff --git a/apps/registry/lib/structured-data.test.ts b/apps/registry/lib/structured-data.test.ts
new file mode 100644
index 00000000..b631f15f
--- /dev/null
+++ b/apps/registry/lib/structured-data.test.ts
@@ -0,0 +1,24 @@
+import { describe, expect, it } from 'vitest'
+import { registryStructuredData, serializedRegistryStructuredData } from './structured-data'
+
+describe('registry structured data', () => {
+ it('publishes canonical website, collection, source, and organization identities', () => {
+ expect(JSON.parse(serializedRegistryStructuredData)).toEqual(registryStructuredData)
+ expect(registryStructuredData['@graph']).toContainEqual(expect.objectContaining({
+ '@type': 'WebSite',
+ '@id': 'https://registry.agentskit.io/#website',
+ url: 'https://registry.agentskit.io',
+ }))
+ expect(registryStructuredData['@graph']).toContainEqual(expect.objectContaining({
+ '@type': 'CollectionPage',
+ '@id': 'https://registry.agentskit.io/#collection',
+ isPartOf: { '@id': 'https://registry.agentskit.io/#website' },
+ }))
+ expect(registryStructuredData['@graph']).toContainEqual(expect.objectContaining({
+ '@type': 'SoftwareSourceCode',
+ codeRepository: 'https://github.com/AgentsKit-io/agentskit-registry',
+ license: 'https://github.com/AgentsKit-io/agentskit-registry/blob/main/LICENSE',
+ programmingLanguage: 'TypeScript',
+ }))
+ })
+})
diff --git a/apps/registry/lib/structured-data.ts b/apps/registry/lib/structured-data.ts
new file mode 100644
index 00000000..2bcf9458
--- /dev/null
+++ b/apps/registry/lib/structured-data.ts
@@ -0,0 +1,41 @@
+export const registryStructuredData = {
+ '@context': 'https://schema.org',
+ '@graph': [
+ {
+ '@type': 'Organization',
+ '@id': 'https://www.agentskit.io/#organization',
+ name: 'AgentsKit',
+ url: 'https://www.agentskit.io',
+ sameAs: ['https://github.com/AgentsKit-io'],
+ },
+ {
+ '@type': 'WebSite',
+ '@id': 'https://registry.agentskit.io/#website',
+ name: 'AgentsKit Registry',
+ description: 'A public catalog of validated, source-owned AI agents for AgentsKit.',
+ url: 'https://registry.agentskit.io',
+ publisher: { '@id': 'https://www.agentskit.io/#organization' },
+ inLanguage: 'en',
+ },
+ {
+ '@type': 'CollectionPage',
+ '@id': 'https://registry.agentskit.io/#collection',
+ name: 'AgentsKit Registry agent catalog',
+ description: 'Browse validated TypeScript agents, copy their source, and adapt them inside your project.',
+ url: 'https://registry.agentskit.io',
+ isPartOf: { '@id': 'https://registry.agentskit.io/#website' },
+ about: { '@id': 'https://registry.agentskit.io/#source' },
+ },
+ {
+ '@type': 'SoftwareSourceCode',
+ '@id': 'https://registry.agentskit.io/#source',
+ name: 'AgentsKit Registry',
+ codeRepository: 'https://github.com/AgentsKit-io/agentskit-registry',
+ license: 'https://github.com/AgentsKit-io/agentskit-registry/blob/main/LICENSE',
+ programmingLanguage: 'TypeScript',
+ author: { '@id': 'https://www.agentskit.io/#organization' },
+ },
+ ],
+} as const
+
+export const serializedRegistryStructuredData = JSON.stringify(registryStructuredData).replaceAll('<', '\\u003c')