Files
opencode-mobile/website/app/privacy/page.tsx
Den e3fb8fa431 fix(site): use support@agentlabs.cc for opencode-mobile support contact (#84)
The website's Support, Privacy, and Terms pages still showed
support@vibebrowser.app — leftover boilerplate from the parent
VibeBrowser product. App store listings, the privacy policy source
(distribution/privacy-policy.html), F-Droid metadata, and the in-app
mailto already use support@agentlabs.cc, so this brings the website
in line with the canonical support address.

Changed:
- website/app/support/page.tsx: mailto link + two visible address strings
- website/app/privacy/page.tsx: fallback contact string shown only if
  distribution/privacy-policy.html fails to load
- website/app/terms/page.tsx: Section 7 (No Support Obligation) and
  Section 14 (Contact) mailto links

Left untouched: AGENTS.md's VIBEBROWSER_REMOTE_URL example (a real
VibeBrowser relay URL, unrelated product) and historical planning notes
(context.md, HANDOFF.md, .autopilot/state.md) documenting the prior
opencode.vibebrowser.app/privacy hosting decision — those are logs of
past decisions, not live support/contact surfaces.

Co-authored-by: engineer <engineer@gray-knight-m1.local>
2026-07-16 19:07:30 -07:00

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@agentlabs.cc" style="color:#3B82F6">support@agentlabs.cc</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>
)
}