From 01e5b5ed1dc68f340ac6ccf3c2284810146ac52c Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 4 Aug 2026 20:38:18 +0000 Subject: [PATCH] Give /file its own OG card and page metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Relayfile landing page fell back to the site-wide default card and carried only a title and description, so shares showed a generic "Headless Slack for Agents" image with no canonical, no social tags, and no entry in the sitemap — while its own docs pages already had Relayfile-branded cards. - Add a RelayfileVariant to the shared OG template: the /file hero's badge, headline, and subtitle beside the "relayfile workspace" tree, with the provider paths and WATCH/WRITE/READ labels from the hero animation. Same composition as the landing and Pear cards. - Serve it from app/file/og.png, prerendered at build like the other cards. - Build the page metadata in lib/relayfile-meta.ts: canonical, keywords, and full openGraph/twitter tags whose copy mirrors the live hero. The page-level openGraph replaces the layout's, so siteName and locale are restated. - Add SoftwareApplication structured data, matching the enterprise page. - Add /file to the sitemap, which was missing it entirely. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01S9ZyG8tEAxsQvUMFPWLF4D --- web/app/file/og.png/route.tsx | 23 +++ web/app/file/page.tsx | 31 +++- web/app/sitemap.ts | 6 + web/lib/og/template.tsx | 266 ++++++++++++++++++++++++++++++++++ web/lib/relayfile-meta.ts | 77 ++++++++++ 5 files changed, 397 insertions(+), 6 deletions(-) create mode 100644 web/app/file/og.png/route.tsx create mode 100644 web/lib/relayfile-meta.ts diff --git a/web/app/file/og.png/route.tsx b/web/app/file/og.png/route.tsx new file mode 100644 index 0000000..df08490 --- /dev/null +++ b/web/app/file/og.png/route.tsx @@ -0,0 +1,23 @@ +import { ImageResponse } from 'next/og'; + +import { loadBrandFonts, OG_SIZE, RelayfileVariant } from '../../../lib/og/template'; + +export const runtime = 'nodejs'; +// Prerender at build time — the Relayfile card never changes between deploys. +export const dynamic = 'force-static'; + +/** + * The Relayfile landing page's Open Graph card: the same composition as the + * homepage and Pear cards (left copy column, a panel bled into the bottom-right) + * with the page's own badge, headline, and subtitle beside the "relayfile + * workspace" tree from its hero. Served as a `.png` route handler so the URL + * ends in a real image extension. + */ +export async function GET() { + const { fonts, headingFamily, bodyFamily } = await loadBrandFonts(); + + return new ImageResponse(, { + ...OG_SIZE, + ...(fonts.length > 0 ? { fonts } : {}), + }); +} diff --git a/web/app/file/page.tsx b/web/app/file/page.tsx index 5f4a801..983be61 100644 --- a/web/app/file/page.tsx +++ b/web/app/file/page.tsx @@ -1,15 +1,34 @@ import type { Metadata } from 'next'; import { GitHubStarsBadge } from '../../components/GitHubStars'; +import { relayfileMetadata, RELAYFILE_PATH } from '../../lib/relayfile-meta'; +import { absoluteUrl } from '../../lib/site'; import { RelayfileContent } from './RelayfileContent'; -export const metadata: Metadata = { - title: 'Relayfile | Integration filesystem for AI agents', - description: - 'Mount SaaS integrations as files so agents can read, write, watch, and coordinate through one realtime workspace.', -}; +export const metadata: Metadata = relayfileMetadata(RELAYFILE_PATH); export default function FilePage() { - return } />; + const structuredData = { + '@context': 'https://schema.org', + '@type': 'SoftwareApplication', + name: 'Relayfile', + applicationCategory: 'DeveloperApplication', + description: + 'An integration filesystem for AI agents. Mount Linear, GitHub, Notion, Slack, and other SaaS systems as a realtime filesystem that agents read with bash and write back to by saving files.', + url: absoluteUrl(RELAYFILE_PATH), + operatingSystem: 'macOS, Linux', + provider: { + '@type': 'Organization', + name: 'Agent Relay', + url: absoluteUrl('/'), + }, + }; + + return ( + <> +