Adds privacy-safe aggregate product intelligence, reviewed/versioned website assets, and a dispatch-only rollout until the dedicated Sentry token is verified. Independent review blockers were fixed in 8bc47e4; app checks, website production build, Android CI, and iOS CI are green. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
62 lines
2.7 KiB
TypeScript
62 lines
2.7 KiB
TypeScript
import type { Metadata } from 'next'
|
|
import { readFileSync } from 'fs'
|
|
import path from 'path'
|
|
|
|
export const metadata: Metadata = {
|
|
title: 'Privacy Policy',
|
|
description:
|
|
'OpenCode Mobile privacy policy. We do not collect your code, prompts, or AI responses. Crash diagnostics via Sentry are opt-in only.',
|
|
alternates: { canonical: 'https://opencode.agentlabs.cc/privacy' },
|
|
openGraph: {
|
|
title: 'Privacy Policy | OpenCode Mobile',
|
|
description: 'OpenCode Mobile privacy policy — minimal data collection, opt-in crash reporting.',
|
|
url: 'https://opencode.agentlabs.cc/privacy',
|
|
},
|
|
}
|
|
|
|
export default function PrivacyPage() {
|
|
// Read the canonical privacy policy HTML generated by the Android distribution workflow.
|
|
// This ensures the policy shown on the site is always in sync with app store submissions.
|
|
const policyPath = path.join(
|
|
process.cwd(),
|
|
'../../../opencode-mobile/distribution/privacy-policy.html',
|
|
)
|
|
|
|
let policyHtml = ''
|
|
try {
|
|
const raw = readFileSync(policyPath, 'utf8')
|
|
// Extract just the <body> content so we can render it inside our layout
|
|
const bodyMatch = raw.match(/<body[^>]*>([\s\S]*?)<\/body>/i)
|
|
policyHtml = bodyMatch ? bodyMatch[1] : raw
|
|
} catch {
|
|
policyHtml = `<p style="color:#94A3B8">Privacy policy document not found. Please contact
|
|
<a href="mailto:support@vibebrowser.app" style="color:#3B82F6">support@vibebrowser.app</a>.</p>`
|
|
}
|
|
|
|
return (
|
|
<div className="max-w-3xl mx-auto px-4 sm:px-6 py-16">
|
|
{/* Override the inline HTML colors from the standalone file with dark theme */}
|
|
<style>{`
|
|
.privacy-content body { color: inherit; background: transparent; }
|
|
.privacy-content header { border-bottom-color: #3B82F6; }
|
|
.privacy-content header h1 { color: #F1F5F9; }
|
|
.privacy-content .meta { color: #94A3B8; }
|
|
.privacy-content h2 { color: #F1F5F9; border-left-color: #3B82F6; }
|
|
.privacy-content p, .privacy-content li { color: #CBD5E1; }
|
|
.privacy-content a { color: #3B82F6; }
|
|
.privacy-content .highlight-box { background: rgba(59,130,246,0.1); border-color: rgba(59,130,246,0.4); }
|
|
.privacy-content .highlight-box strong { color: #93C5FD; }
|
|
.privacy-content th { background: #1E293B; border-color: #334155; color: #F1F5F9; }
|
|
.privacy-content td { border-color: #334155; color: #CBD5E1; }
|
|
.privacy-content tr:nth-child(even) td { background: rgba(30,41,59,0.5); }
|
|
.privacy-content footer { border-top-color: #334155; color: #64748B; }
|
|
.privacy-content code { color: #94A3B8; font-size: 0.85em; }
|
|
`}</style>
|
|
<div
|
|
className="privacy-content"
|
|
dangerouslySetInnerHTML={{ __html: policyHtml }}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|