buildmymcpserver/apps/web/app/(marketing)/privacy/page.tsx
Marco Sadjadi b843394d0f
Some checks failed
Deploy to Production / deploy (push) Failing after 46s
feat(web): full SEO stack — metadata, JSON-LD, sitemap, robots, OG image
Ported and adapted from the BuildMyDiscord SEO setup:

- lib/seo.ts — single source for site constants, the FAQ data (shared by
  the rendered FAQ and the FAQPage schema so they never drift) and JSON-LD
  builders.
- Rich root metadata: title template, keywords, Open Graph, Twitter card,
  robots directives, canonical.
- JSON-LD: Organization + WebSite + SoftwareApplication sitewide, FAQPage
  on the landing page. No AggregateRating — there are no real reviews yet.
- app/robots.ts — allow all, explicit allow-list for AI answer-engine
  crawlers (GPTBot, ClaudeBot, PerplexityBot, …), disallow private routes.
- app/sitemap.ts — every public marketing + docs route.
- app/opengraph-image.tsx — monochrome on-brand 1200x630 share card.
- app/manifest.ts + public/llms.txt.
- Per-page metadata for pricing, changelog, security, privacy, terms,
  docs, templates and status.
- opengraph-image + apple-icon pinned to the edge runtime — next/og
  crashes during a Node-runtime prerender.

Verified: next build passes; /robots.txt, /sitemap.xml,
/manifest.webmanifest and /opengraph-image all generate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 19:16:40 +02:00

114 lines
4.2 KiB
TypeScript

import { pageMetadata } from '@/lib/seo';
export const metadata = pageMetadata({
title: 'Privacy',
description:
'BuildMyMCPServer privacy policy — what data we collect, how it is used, and the rights you have over it.',
path: '/privacy',
});
const SECTIONS = [
{
h: 'What we collect',
p: [
'Account: email, organization name, the IP address of your sign-in.',
'Workspace: the prompts you send to the generator, the generated server specifications, build logs, server names and slugs you choose.',
'Tool-call metrics: counts, latencies, status codes — never the request or response payloads. We only know that a tool was called, how long it took, and whether it succeeded.',
'Billing: Stripe customer id + subscription metadata for paid plans. Card details never touch our servers.',
],
},
{
h: 'What we do NOT collect',
p: [
'Plaintext credentials. Every secret you save is AES-256-GCM encrypted before it hits storage. We have no ability to read them; only your container at runtime can.',
'Tool-call payloads. The arguments your AI client sends and the responses our server returns are not stored or logged.',
'Browsing data, cross-site tracking, advertising identifiers.',
],
},
{
h: 'Where it lives',
p: [
'EU region by default (Hetzner Falkenstein, Germany).',
'Postgres + Redis + container hosts are all in the same region.',
'Backups encrypted at rest in Backblaze B2 EU.',
],
},
{
h: 'Subprocessors',
p: [
"Anthropic (generation) — only the prompt text you send. Anthropic's data-retention policy applies.",
'Hetzner (compute).',
'Backblaze (encrypted backups).',
'Stripe (billing).',
'Cloudflare (DNS + DDoS).',
],
},
{
h: 'Retention',
p: [
'Active account: all workspace data kept while subscribed.',
'Cancelled account: 30-day grace period, then full deletion (servers, builds, logs, audit).',
'Audit log: 1 year on Team+, 30 days on Pro/Hobby.',
'Tool-call metrics: 30 days, then aggregated to daily counts.',
],
},
{
h: 'Your rights (GDPR)',
p: [
'Access — export everything in JSON via the settings page (Sprint 4) or by email.',
'Deletion — delete your organization in settings; everything goes within 30 days.',
'Rectification — change name and email yourself; everything else is editable on request.',
'Portability — the generated TypeScript source of every server is yours, downloadable.',
],
},
];
export default function Privacy() {
return (
<div className="mx-auto max-w-3xl px-6 py-16">
<header className="mb-12">
<div className="text-[11px] uppercase tracking-[0.16em] text-[--color-fg-subtle]">
Privacy policy
</div>
<h1 className="mt-2 text-[32px] font-semibold tracking-tight">Privacy</h1>
<p className="mt-3 text-[14px] leading-relaxed text-[--color-fg-muted]">
Plain language. What we collect, where it lives, how to get it deleted. Last updated
2026-05-19.
</p>
</header>
<div className="space-y-9">
{SECTIONS.map((s) => (
<section key={s.h}>
<h2 className="text-[16px] font-semibold tracking-tight">{s.h}</h2>
<ul className="mt-3 space-y-1.5">
{s.p.map((p) => (
<li
key={p}
className="relative pl-4 text-[13.5px] leading-relaxed text-[--color-fg-muted] before:absolute before:left-0 before:top-2 before:size-1 before:rounded-full before:bg-[--color-fg-subtle]"
>
{p}
</li>
))}
</ul>
</section>
))}
<section>
<h2 className="text-[16px] font-semibold tracking-tight">Contact</h2>
<p className="mt-3 text-[13.5px] leading-relaxed text-[--color-fg-muted]">
Data controller: BuildMyMCPServer. Email{' '}
<a
className="text-[--color-accent] underline"
href="mailto:privacy@buildmymcpserver.com"
>
privacy@buildmymcpserver.com
</a>{' '}
for any of the above.
</p>
</section>
</div>
</div>
);
}