feat(website): add og:title and og:description via pageMeta helper

Extract a DRY pageMeta(title, description) helper that returns both
standard and OpenGraph meta tags from a single source of truth.
This commit is contained in:
Mohamed Boudra
2026-03-15 14:28:10 +07:00
parent 21c585abec
commit cda08ec033
15 changed files with 78 additions and 105 deletions
+8
View File
@@ -0,0 +1,8 @@
export function pageMeta(title: string, description: string) {
return [
{ title },
{ name: 'description', content: description },
{ property: 'og:title', content: title },
{ property: 'og:description', content: description },
]
}
+5 -8
View File
@@ -1,18 +1,15 @@
import { Link, createFileRoute } from '@tanstack/react-router' import { Link, createFileRoute } from '@tanstack/react-router'
import ReactMarkdown from 'react-markdown' import ReactMarkdown from 'react-markdown'
import changelogMarkdown from '../../../../CHANGELOG.md?raw' import changelogMarkdown from '../../../../CHANGELOG.md?raw'
import { pageMeta } from '~/meta'
import '~/styles.css' import '~/styles.css'
export const Route = createFileRoute('/changelog')({ export const Route = createFileRoute('/changelog')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Changelog - Paseo' }, 'Changelog - Paseo',
{ 'Product updates, fixes, and improvements shipped in each Paseo release.',
name: 'description', ),
content:
'Product updates, fixes, and improvements shipped in each Paseo release.',
},
],
}), }),
component: Changelog, component: Changelog,
}) })
+5 -8
View File
@@ -1,16 +1,13 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { LandingPage } from '~/components/landing-page' import { LandingPage } from '~/components/landing-page'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/claude-code')({ export const Route = createFileRoute('/claude-code')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Claude Code Mobile App – Ship from your phone | Paseo' }, 'Claude Code Mobile App – Ship from your phone | Paseo',
{ 'Run Claude Code from your phone. Launch agents, check on progress, review diffs, and merge — all from your pocket. Self-hosted, your code stays on your machine.',
name: 'description', ),
content:
'Run Claude Code from your phone. Launch agents, check on progress, review diffs, and merge — all from your pocket. Self-hosted, your code stays on your machine.',
},
],
}), }),
component: ClaudeCodePage, component: ClaudeCodePage,
}) })
+5 -8
View File
@@ -1,16 +1,13 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { LandingPage } from '~/components/landing-page' import { LandingPage } from '~/components/landing-page'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/codex')({ export const Route = createFileRoute('/codex')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Codex Mobile App – Run Codex from anywhere | Paseo' }, 'Codex Mobile App – Run Codex from anywhere | Paseo',
{ 'Run OpenAI Codex from your phone. Kick off agents, monitor progress, and ship code without being at your desk. Self-hosted, your code never leaves your machine.',
name: 'description', ),
content:
'Run OpenAI Codex from your phone. Kick off agents, monitor progress, and ship code without being at your desk. Self-hosted, your code never leaves your machine.',
},
],
}), }),
component: CodexPage, component: CodexPage,
}) })
@@ -1,14 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/docs/best-practices')({ export const Route = createFileRoute('/docs/best-practices')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Best Practices - Paseo Docs' }, 'Best Practices - Paseo Docs',
{ 'Tips for getting the most out of Paseo and mobile-first agent workflows.',
name: 'description', ),
content: 'Tips for getting the most out of Paseo and mobile-first agent workflows.',
},
],
}), }),
component: BestPractices, component: BestPractices,
}) })
+5 -7
View File
@@ -1,14 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/docs/cli')({ export const Route = createFileRoute('/docs/cli')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'CLI - Paseo Docs' }, 'CLI - Paseo Docs',
{ 'Paseo CLI reference: manage agents, daemons, permissions, and worktrees from your terminal.',
name: 'description', ),
content: 'Paseo CLI reference: manage agents, daemons, permissions, and worktrees from your terminal.',
},
],
}), }),
component: CLI, component: CLI,
}) })
@@ -1,14 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/docs/configuration')({ export const Route = createFileRoute('/docs/configuration')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Configuration - Paseo Docs' }, 'Configuration - Paseo Docs',
{ 'Configure Paseo via config.json, environment variables, and CLI overrides.',
name: 'description', ),
content: 'Configure Paseo via config.json, environment variables, and CLI overrides.',
},
],
}), }),
component: Configuration, component: Configuration,
}) })
+5 -7
View File
@@ -1,14 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/docs/')({ export const Route = createFileRoute('/docs/')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Getting Started - Paseo Docs' }, 'Getting Started - Paseo Docs',
{ 'Learn how to set up and use Paseo to manage your coding agents from anywhere.',
name: 'description', ),
content: 'Learn how to set up and use Paseo to manage your coding agents from anywhere.',
},
],
}), }),
component: GettingStarted, component: GettingStarted,
}) })
@@ -1,15 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/docs/security')({ export const Route = createFileRoute('/docs/security')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Security - Paseo Docs' }, 'Security - Paseo Docs',
{ 'Security model for Paseo: architecture overview, connection methods, relay encryption, and best practices.',
name: 'description', ),
content:
'Security model for Paseo: architecture overview, connection methods, relay encryption, and best practices.',
},
],
}), }),
component: Security, component: Security,
}) })
+5 -7
View File
@@ -1,14 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/docs/updates')({ export const Route = createFileRoute('/docs/updates')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Updates - Paseo Docs' }, 'Updates - Paseo Docs',
{ 'How to update Paseo daemon and apps across web, desktop, and mobile.',
name: 'description', ),
content: 'How to update Paseo daemon and apps across web, desktop, and mobile.',
},
],
}), }),
component: UpdatesDocs, component: UpdatesDocs,
}) })
+5 -7
View File
@@ -1,14 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/docs/voice')({ export const Route = createFileRoute('/docs/voice')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Voice - Paseo Docs' }, 'Voice - Paseo Docs',
{ 'Paseo voice architecture, local-first model execution, and provider configuration.',
name: 'description', ),
content: 'Paseo voice architecture, local-first model execution, and provider configuration.',
},
],
}), }),
component: VoiceDocs, component: VoiceDocs,
}) })
@@ -1,14 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/docs/worktrees')({ export const Route = createFileRoute('/docs/worktrees')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Git Worktrees - Paseo Docs' }, 'Git Worktrees - Paseo Docs',
{ 'Run agents in isolated git worktrees for parallel feature development.',
name: 'description', ),
content: 'Run agents in isolated git worktrees for parallel feature development.',
},
],
}), }),
component: Worktrees, component: Worktrees,
}) })
+5 -8
View File
@@ -1,16 +1,13 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { LandingPage } from '~/components/landing-page' import { LandingPage } from '~/components/landing-page'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/')({ export const Route = createFileRoute('/')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Paseo – Run Claude Code, Codex, and OpenCode from everywhere' }, 'Paseo – Run Claude Code, Codex, and OpenCode from everywhere',
{ 'A self-hosted daemon for Claude Code, Codex, and OpenCode. Agents run on your machine with your full dev environment. Connect from phone, desktop, or web.',
name: 'description', ),
content:
'A self-hosted daemon for Claude Code, Codex, and OpenCode. Agents run on your machine with your full dev environment. Connect from phone, desktop, or web.',
},
],
}), }),
component: Home, component: Home,
}) })
+5 -8
View File
@@ -1,16 +1,13 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { LandingPage } from '~/components/landing-page' import { LandingPage } from '~/components/landing-page'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/opencode')({ export const Route = createFileRoute('/opencode')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'OpenCode Mobile App – Code from anywhere | Paseo' }, 'OpenCode Mobile App – Code from anywhere | Paseo',
{ 'Run OpenCode from your phone. Launch agents, watch them work, and ship code from wherever you are. Self-hosted, open source, your code stays local.',
name: 'description', ),
content:
'Run OpenCode from your phone. Launch agents, watch them work, and ship code from wherever you are. Self-hosted, open source, your code stays local.',
},
],
}), }),
component: OpenCodePage, component: OpenCodePage,
}) })
+5 -8
View File
@@ -1,15 +1,12 @@
import { createFileRoute } from '@tanstack/react-router' import { createFileRoute } from '@tanstack/react-router'
import { pageMeta } from '~/meta'
export const Route = createFileRoute('/privacy')({ export const Route = createFileRoute('/privacy')({
head: () => ({ head: () => ({
meta: [ meta: pageMeta(
{ title: 'Privacy Policy - Paseo' }, 'Privacy Policy - Paseo',
{ 'Privacy policy for Paseo - a self-hosted agent manager with no tracking or analytics.',
name: 'description', ),
content:
'Privacy policy for Paseo - a self-hosted agent manager with no tracking or analytics.',
},
],
}), }),
component: Privacy, component: Privacy,
}) })