From acef3d6fa1bfb0da09cbf59b9bd80a2632bcc61d Mon Sep 17 00:00:00 2001 From: JulioMCruz Date: Wed, 5 Aug 2026 22:34:47 +0200 Subject: [PATCH] feat(seo): canonical, social cards, robots and sitemap The site had a title and a description and nothing else. No canonical, no Open Graph, no Twitter card, and /robots.txt and /sitemap.xml both 404, so a shared link rendered as a bare URL and crawlers had no guidance. - layout metadata: metadataBase, canonical, Open Graph, Twitter summary card, explicit robots directives, and a title template for subpages. - app/robots.ts: allow the landing, keep crawlers out of the wallet-gated dashboard and admin views and the agent endpoints under /api, /knowledge and /skill. - app/sitemap.ts: the landing, which is the only public page. - public/og.png: a 1200x630 card in the site's own palette. - JSON-LD on the landing (WebSite, Organization, SoftwareApplication) so search engines and assistants describe the service accurately. Build verified: /robots.txt and /sitemap.xml are emitted as static routes. --- App/app/layout.tsx | 38 ++++++++++++++++++++++++++++++++++++-- App/app/page.tsx | 39 +++++++++++++++++++++++++++++++++++++++ App/app/robots.ts | 16 ++++++++++++++++ App/app/sitemap.ts | 14 ++++++++++++++ App/public/og.png | Bin 0 -> 232156 bytes 5 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 App/app/robots.ts create mode 100644 App/app/sitemap.ts create mode 100644 App/public/og.png diff --git a/App/app/layout.tsx b/App/app/layout.tsx index 15c09c8..9ed3c41 100644 --- a/App/app/layout.tsx +++ b/App/app/layout.tsx @@ -2,9 +2,43 @@ import type { Metadata } from 'next'; import Web3Providers from '../components/Web3Providers'; import './styles.css'; +const SITE_URL = 'https://knowledge.perkos.xyz'; +const TITLE = 'PerkOS Knowledge — a shared knowledge commons for people and their agents'; +const DESCRIPTION = + 'A shared knowledge commons. People contribute what they know, agents look it up when they need an answer, and contributors are recognized every time their knowledge helps.'; + export const metadata: Metadata = { - title: 'PerkOS Knowledge', - description: 'A shared knowledge commons. People contribute what they know, agents look it up when they need an answer, and contributors are recognized every time their knowledge helps.', + metadataBase: new URL(SITE_URL), + title: { + default: TITLE, + template: '%s · PerkOS Knowledge', + }, + description: DESCRIPTION, + applicationName: 'PerkOS Knowledge', + alternates: { + canonical: '/', + }, + openGraph: { + type: 'website', + url: SITE_URL, + siteName: 'PerkOS Knowledge', + title: TITLE, + description: DESCRIPTION, + locale: 'en_US', + images: [{ url: '/og.png', width: 1200, height: 630, alt: 'PerkOS Knowledge, a shared knowledge commons' }], + }, + twitter: { + card: 'summary_large_image', + title: TITLE, + description: DESCRIPTION, + site: '@perk_os', + images: ['/og.png'], + }, + robots: { + index: true, + follow: true, + googleBot: { index: true, follow: true, 'max-image-preview': 'large', 'max-snippet': -1 }, + }, other: { 'talentapp:project_verification': '6312cbdecd6b0d974fb841350d907866a1bc2ed3a10c7ac2057d9b747a3ef7ef662b202d1a8fcedc67ada1a5cc3d5cbddaf052fc7952b9a911c7c0fca1d4a572', diff --git a/App/app/page.tsx b/App/app/page.tsx index f94801d..a3ddb62 100644 --- a/App/app/page.tsx +++ b/App/app/page.tsx @@ -15,9 +15,48 @@ const apiCards = [ const rails = ['Open source', 'Self-hostable', 'MCP', 'Qdrant', 'Postgres', 'Firebase', 'Docker']; +// Structured data so search engines and assistants can describe the service +// without guessing. Keep it to what the page itself claims. +const structuredData = { + '@context': 'https://schema.org', + '@graph': [ + { + '@type': 'WebSite', + '@id': 'https://knowledge.perkos.xyz/#website', + url: 'https://knowledge.perkos.xyz', + name: 'PerkOS Knowledge', + description: + 'A shared knowledge commons. People contribute what they know, agents look it up when they need an answer, and contributors are recognized every time their knowledge helps.', + inLanguage: 'en', + publisher: { '@id': 'https://perkos.xyz/#organization' } + }, + { + '@type': 'Organization', + '@id': 'https://perkos.xyz/#organization', + name: 'PerkOS', + url: 'https://perkos.xyz' + }, + { + '@type': 'SoftwareApplication', + name: 'PerkOS Knowledge', + applicationCategory: 'DeveloperApplication', + operatingSystem: 'Any', + url: 'https://knowledge.perkos.xyz', + description: + 'A searchable knowledge commons that people and AI agents share. Answers come back with their sources, private notes stay private, and contributors are recognized when their knowledge helps.', + isAccessibleForFree: true + } + ] +}; + export default function Home() { return (
+