website: add privacy policy page and footer link
Add a minimal privacy policy at /privacy that explains: - Paseo is self-hosted, no data collection - The relay uses end-to-end encryption and cannot read messages - No analytics, tracking, or ads - Third-party agent providers handle their own auth Add footer link on home page styled as muted/subtle.
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
||||
|
||||
import { Route as rootRouteImport } from './routes/__root'
|
||||
import { Route as PrivacyRouteImport } from './routes/privacy'
|
||||
import { Route as DocsRouteImport } from './routes/docs'
|
||||
import { Route as IndexRouteImport } from './routes/index'
|
||||
import { Route as DocsIndexRouteImport } from './routes/docs/index'
|
||||
@@ -19,6 +20,11 @@ import { Route as DocsConfigurationRouteImport } from './routes/docs/configurati
|
||||
import { Route as DocsCliRouteImport } from './routes/docs/cli'
|
||||
import { Route as DocsBestPracticesRouteImport } from './routes/docs/best-practices'
|
||||
|
||||
const PrivacyRoute = PrivacyRouteImport.update({
|
||||
id: '/privacy',
|
||||
path: '/privacy',
|
||||
getParentRoute: () => rootRouteImport,
|
||||
} as any)
|
||||
const DocsRoute = DocsRouteImport.update({
|
||||
id: '/docs',
|
||||
path: '/docs',
|
||||
@@ -68,6 +74,7 @@ const DocsBestPracticesRoute = DocsBestPracticesRouteImport.update({
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
'/docs': typeof DocsRouteWithChildren
|
||||
'/privacy': typeof PrivacyRoute
|
||||
'/docs/best-practices': typeof DocsBestPracticesRoute
|
||||
'/docs/cli': typeof DocsCliRoute
|
||||
'/docs/configuration': typeof DocsConfigurationRoute
|
||||
@@ -78,6 +85,7 @@ export interface FileRoutesByFullPath {
|
||||
}
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexRoute
|
||||
'/privacy': typeof PrivacyRoute
|
||||
'/docs/best-practices': typeof DocsBestPracticesRoute
|
||||
'/docs/cli': typeof DocsCliRoute
|
||||
'/docs/configuration': typeof DocsConfigurationRoute
|
||||
@@ -90,6 +98,7 @@ export interface FileRoutesById {
|
||||
__root__: typeof rootRouteImport
|
||||
'/': typeof IndexRoute
|
||||
'/docs': typeof DocsRouteWithChildren
|
||||
'/privacy': typeof PrivacyRoute
|
||||
'/docs/best-practices': typeof DocsBestPracticesRoute
|
||||
'/docs/cli': typeof DocsCliRoute
|
||||
'/docs/configuration': typeof DocsConfigurationRoute
|
||||
@@ -103,6 +112,7 @@ export interface FileRouteTypes {
|
||||
fullPaths:
|
||||
| '/'
|
||||
| '/docs'
|
||||
| '/privacy'
|
||||
| '/docs/best-practices'
|
||||
| '/docs/cli'
|
||||
| '/docs/configuration'
|
||||
@@ -113,6 +123,7 @@ export interface FileRouteTypes {
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to:
|
||||
| '/'
|
||||
| '/privacy'
|
||||
| '/docs/best-practices'
|
||||
| '/docs/cli'
|
||||
| '/docs/configuration'
|
||||
@@ -124,6 +135,7 @@ export interface FileRouteTypes {
|
||||
| '__root__'
|
||||
| '/'
|
||||
| '/docs'
|
||||
| '/privacy'
|
||||
| '/docs/best-practices'
|
||||
| '/docs/cli'
|
||||
| '/docs/configuration'
|
||||
@@ -136,10 +148,18 @@ export interface FileRouteTypes {
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute
|
||||
DocsRoute: typeof DocsRouteWithChildren
|
||||
PrivacyRoute: typeof PrivacyRoute
|
||||
}
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
interface FileRoutesByPath {
|
||||
'/privacy': {
|
||||
id: '/privacy'
|
||||
path: '/privacy'
|
||||
fullPath: '/privacy'
|
||||
preLoaderRoute: typeof PrivacyRouteImport
|
||||
parentRoute: typeof rootRouteImport
|
||||
}
|
||||
'/docs': {
|
||||
id: '/docs'
|
||||
path: '/docs'
|
||||
@@ -231,6 +251,7 @@ const DocsRouteWithChildren = DocsRoute._addFileChildren(DocsRouteChildren)
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
DocsRoute: DocsRouteWithChildren,
|
||||
PrivacyRoute: PrivacyRoute,
|
||||
}
|
||||
export const routeTree = rootRouteImport
|
||||
._addFileChildren(rootRouteChildren)
|
||||
|
||||
@@ -53,6 +53,16 @@ function Home() {
|
||||
<Story />
|
||||
<FAQ />
|
||||
</main>
|
||||
<footer className="p-6 md:p-20 md:pt-0 max-w-3xl mx-auto">
|
||||
<div className="border-t border-white/10 pt-6">
|
||||
<a
|
||||
href="/privacy"
|
||||
className="text-xs text-white/40 hover:text-white/60 transition-colors"
|
||||
>
|
||||
Privacy
|
||||
</a>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</CursorFieldProvider>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/privacy')({
|
||||
head: () => ({
|
||||
meta: [
|
||||
{ title: 'Privacy Policy - Paseo' },
|
||||
{
|
||||
name: 'description',
|
||||
content:
|
||||
'Privacy policy for Paseo - a self-hosted agent manager with no tracking or analytics.',
|
||||
},
|
||||
],
|
||||
}),
|
||||
component: Privacy,
|
||||
})
|
||||
|
||||
function Privacy() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background">
|
||||
<div className="max-w-3xl mx-auto p-6 md:p-12">
|
||||
<h1 className="text-3xl font-medium mb-8">Privacy Policy</h1>
|
||||
|
||||
<div className="space-y-6 text-white/70 leading-relaxed">
|
||||
<p>
|
||||
Paseo is a self-hosted tool for managing coding agents. Your code and
|
||||
data stay on your machine.
|
||||
</p>
|
||||
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-xl font-medium text-white">What we collect</h2>
|
||||
<p>Nothing. Paseo runs on your machine and doesn't send us any data.</p>
|
||||
</section>
|
||||
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-xl font-medium text-white">The relay server</h2>
|
||||
<p>
|
||||
If you use the optional encrypted relay to connect your phone to your
|
||||
daemon, the relay sees:
|
||||
</p>
|
||||
<ul className="list-disc list-inside space-y-1 ml-4">
|
||||
<li>IP addresses and connection timing</li>
|
||||
<li>Message sizes</li>
|
||||
<li>Session IDs</li>
|
||||
</ul>
|
||||
<p>
|
||||
All messages between your phone and daemon are end-to-end encrypted
|
||||
with AES-256-GCM. The relay cannot read your messages, see your code,
|
||||
or decrypt your traffic.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-xl font-medium text-white">Analytics and tracking</h2>
|
||||
<p>
|
||||
We don't use analytics, tracking pixels, cookies, or ads. The app
|
||||
doesn't phone home.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-xl font-medium text-white">Third-party services</h2>
|
||||
<p>
|
||||
Paseo wraps agent providers like Claude Code, Codex, and OpenCode.
|
||||
Those tools communicate with their own APIs (Anthropic, OpenAI, etc.)
|
||||
using your credentials. Paseo doesn't manage or intercept those API
|
||||
calls.
|
||||
</p>
|
||||
<p>
|
||||
If you use voice features with cloud providers (OpenAI speech), your
|
||||
voice data is sent to those services according to their privacy
|
||||
policies.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-xl font-medium text-white">
|
||||
We don't sell your data
|
||||
</h2>
|
||||
<p>
|
||||
We don't have your data to sell. Paseo is self-hosted and
|
||||
local-first.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-xl font-medium text-white">Questions</h2>
|
||||
<p>
|
||||
If you have questions about privacy, open an issue on{' '}
|
||||
<a
|
||||
href="https://github.com/getpaseo/paseo"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="underline hover:text-white/90"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<p className="text-sm text-white/50 pt-6">Last updated: February 2025</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user