mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 18:15:56 -04:00
docs: add privacy policy page and footer link
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"configVersion": 0,
|
||||
"apple": {
|
||||
"info": {
|
||||
"en-US": {
|
||||
"title": "Sofa - Movie & TV Tracker",
|
||||
"subtitle": "Companion app for Sofa servers",
|
||||
"promoText": "Sofa connects to your self-hosted server to track movies and TV shows. Log what you watch, manage your watchlist, and auto-track from Plex, Jellyfin, and Emby.",
|
||||
"description": "Sofa Mobile is the companion app for your self-hosted Sofa server. Track movies and TV shows, manage your watchlist, and pick up where you left off — all from your phone.\n\nA running Sofa server is required. Set one up at https://sofa.watch\n\nTRACK EVERYTHING YOU WATCH\nAdd movies and shows to your watchlist, mark them as watching or completed, and rate them on a 5-star scale. For TV shows, track progress down to individual episodes — mark a single episode, an entire season, or jump straight to where you left off.\n\nDISCOVER WHAT'S NEXT\nBrowse trending and popular titles, filter by genre, and get recommendations based on what's already in your library. Search across movies, TV shows, and people. Tap into any actor's filmography to find your next watch.\n\nSEE WHERE TO WATCH\nView streaming availability for any title so you know where to find it before you sit down.\n\nAUTO-TRACK FROM YOUR MEDIA SERVER\nConnect Plex, Jellyfin, or Emby to automatically log what you watch — no manual entry needed. Set up Sonarr and Radarr to sync your watchlist for automatic downloads.\n\nYOUR DATA, YOUR SERVER\nSofa is fully self-hosted. Your watch history, ratings, and library stay on your own server. No accounts with third parties, no data leaving your network unless you want it to.\n\nADMIN ON THE GO\nServer admins can check server health, manage registration settings, and see update notifications right from the app.\n\n• Watchlist, watching, and completed status tracking\n• Per-episode and per-season progress tracking\n• Continue Watching with next-episode info\n• Trending, popular, and personalized recommendations\n• Genre filtering\n• Full cast and filmography browsing\n• Streaming availability\n• Plex, Jellyfin, and Emby webhook integration\n• Sonarr and Radarr watchlist sync\n• Multi-user support with admin controls\n• Email/password and OIDC/SSO authentication",
|
||||
"keywords": [
|
||||
"sofa",
|
||||
"self-hosted",
|
||||
"movie",
|
||||
"tv",
|
||||
"tracker",
|
||||
"watchlist",
|
||||
"plex",
|
||||
"jellyfin",
|
||||
"emby",
|
||||
"sonarr",
|
||||
"radarr",
|
||||
"tmdb",
|
||||
"tracking"
|
||||
],
|
||||
"marketingUrl": "https://sofa.watch",
|
||||
"supportUrl": "https://sofa.watch/support",
|
||||
"privacyPolicyUrl": "https://sofa.watch/privacy"
|
||||
}
|
||||
},
|
||||
"categories": ["ENTERTAINMENT"],
|
||||
"copyright": "2026 Jake Jarvis",
|
||||
"review": {
|
||||
"demoUsername": "apple-reviewer@sofa.watch",
|
||||
"demoPassword": "cupertino",
|
||||
"demoRequired": true,
|
||||
"notes": "Use https://app-store-demo.sofa.watch to login to the demo account."
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
"!dist",
|
||||
"!build",
|
||||
"!.source",
|
||||
"!openapi.json"
|
||||
"!public/openapi.json"
|
||||
]
|
||||
},
|
||||
"css": {
|
||||
|
||||
@@ -17,6 +17,11 @@ const config = {
|
||||
destination: "/docs/api/account/account.removeAvatar",
|
||||
permanent: false,
|
||||
},
|
||||
{
|
||||
source: "/support",
|
||||
destination: "https://github.com/jakejarvis/sofa/discussions",
|
||||
permanent: false,
|
||||
},
|
||||
];
|
||||
},
|
||||
async rewrites() {
|
||||
|
||||
@@ -1,6 +1,48 @@
|
||||
import { HomeLayout } from "fumadocs-ui/layouts/home";
|
||||
import Link from "next/link";
|
||||
import { TmdbLogo } from "@/components/tmdb-logo";
|
||||
import { baseOptions } from "@/lib/layout.shared";
|
||||
|
||||
export default function Layout({ children }: LayoutProps<"/">) {
|
||||
return <HomeLayout {...baseOptions()}>{children}</HomeLayout>;
|
||||
return (
|
||||
<HomeLayout {...baseOptions()}>
|
||||
{children}
|
||||
<footer className="border-t border-fd-border px-6 py-8">
|
||||
<div className="mx-auto flex max-w-5xl flex-col items-center gap-4 text-center text-xs text-fd-muted-foreground">
|
||||
<div className="flex flex-wrap items-center justify-center gap-x-2 gap-y-1">
|
||||
<a
|
||||
href="https://github.com/jakejarvis/sofa"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-fd-foreground"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<span className="hidden sm:inline">·</span>
|
||||
<Link href="/docs" className="hover:text-fd-foreground">
|
||||
Docs
|
||||
</Link>
|
||||
<span className="hidden sm:inline">·</span>
|
||||
<Link href="/privacy" className="hover:text-fd-foreground">
|
||||
Privacy
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<a
|
||||
href="https://www.themoviedb.org/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="opacity-85 transition-opacity hover:opacity-100"
|
||||
>
|
||||
<TmdbLogo className="h-3" />
|
||||
</a>
|
||||
<p className="max-w-md text-fd-muted-foreground/80">
|
||||
This product uses the TMDB API but is not endorsed or certified by
|
||||
TMDB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</HomeLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
import Link from "next/link";
|
||||
import { ScrollIndicator } from "@/components/scroll-indicator";
|
||||
import { SofaLogo } from "@/components/sofa-logo";
|
||||
import { TmdbLogo } from "@/components/tmdb-logo";
|
||||
|
||||
const features = [
|
||||
{
|
||||
@@ -217,42 +216,6 @@ export default function HomePage() {
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Footer ── */}
|
||||
<footer className="border-t border-fd-border px-6 py-8">
|
||||
<div className="mx-auto flex max-w-5xl flex-col items-center gap-4 text-center text-xs text-fd-muted-foreground">
|
||||
<div className="flex flex-wrap items-center justify-center gap-x-4 gap-y-1">
|
||||
<span>MIT License</span>
|
||||
<span className="hidden sm:inline">·</span>
|
||||
<a
|
||||
href="https://github.com/jakejarvis/sofa"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-fd-foreground"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<span className="hidden sm:inline">·</span>
|
||||
<Link href="/docs" className="hover:text-fd-foreground">
|
||||
Docs
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<a
|
||||
href="https://www.themoviedb.org/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="opacity-85 transition-opacity hover:opacity-100"
|
||||
>
|
||||
<TmdbLogo className="h-3" />
|
||||
</a>
|
||||
<p className="max-w-md text-fd-muted-foreground/80">
|
||||
This product uses the TMDB API but is not endorsed or certified by
|
||||
TMDB.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Privacy Policy",
|
||||
description: "How Sofa handles your data.",
|
||||
};
|
||||
|
||||
export default function PrivacyPolicyPage() {
|
||||
return (
|
||||
<article className="prose prose-sm prose-invert mx-auto max-w-3xl px-6 py-16 [&_a]:text-fd-primary [&_a]:underline [&_a]:underline-offset-4 hover:[&_a]:text-fd-primary/80 [&_h2]:font-display [&_h2]:text-2xl [&_h2]:mt-10 [&_h2]:mb-4 [&_h2]:border-b [&_h2]:pb-2 [&_h3]:font-display [&_h3]:text-xl [&_h3]:mt-8 [&_h3]:mb-3 [&_p]:text-fd-muted-foreground [&_p]:text-[15px] [&_p]:leading-relaxed [&_li]:text-fd-muted-foreground [&_li]:text-[15px] [&_li]:leading-relaxed [&_ul]:space-y-1 [&_strong]:text-fd-foreground [&_strong]:font-medium">
|
||||
<h1 className="font-display text-3xl tracking-tight mb-2">
|
||||
Privacy Policy
|
||||
</h1>
|
||||
<p className="text-sm text-fd-muted-foreground/60 !mt-0 mb-8">
|
||||
Last updated: March 16, 2026
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Sofa is a self-hosted application. When you run Sofa, your data lives on
|
||||
your own server and is under your control. This policy describes what
|
||||
data Sofa stores, what it sends externally, and how you can control it.
|
||||
</p>
|
||||
|
||||
<h2>Data Stored on Your Server</h2>
|
||||
|
||||
<p>
|
||||
All of the following data is stored locally in a single SQLite database
|
||||
file on the machine running Sofa.
|
||||
</p>
|
||||
|
||||
<h3>Account Information</h3>
|
||||
<ul>
|
||||
<li>Email address, display name, and hashed password</li>
|
||||
<li>
|
||||
Session tokens, IP address, and user agent string of active sessions
|
||||
</li>
|
||||
<li>
|
||||
If using OIDC/SSO: provider account IDs and OAuth tokens from your
|
||||
identity provider
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Viewing Activity</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Watchlist status (e.g. “watching”,
|
||||
“completed”) for movies and TV shows
|
||||
</li>
|
||||
<li>Individual movie and episode watch timestamps</li>
|
||||
<li>Personal ratings</li>
|
||||
<li>
|
||||
Source of each watch event (manual entry, or imported from Plex,
|
||||
Jellyfin, or Emby)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Media Metadata</h3>
|
||||
<p>
|
||||
Movie, TV show, season, episode, and cast/crew metadata is fetched from{" "}
|
||||
<a
|
||||
href="https://www.themoviedb.org/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
The Movie Database (TMDB)
|
||||
</a>{" "}
|
||||
and cached locally. This includes titles, descriptions, images, genres,
|
||||
streaming availability, and related recommendations. No personal data is
|
||||
included in this metadata.
|
||||
</p>
|
||||
|
||||
<h3>Backups</h3>
|
||||
<p>
|
||||
Manual and scheduled backups are full copies of the database stored on
|
||||
your server. They contain all of the data described above. Backup
|
||||
management (creation, download, deletion) requires admin authentication.
|
||||
</p>
|
||||
|
||||
<h2>External Services</h2>
|
||||
|
||||
<p>
|
||||
Sofa communicates with the following external services during normal
|
||||
operation.
|
||||
</p>
|
||||
|
||||
<h3>The Movie Database (TMDB)</h3>
|
||||
<p>
|
||||
Your server makes API requests to TMDB to fetch and refresh movie and TV
|
||||
metadata. These requests include your TMDB API key and the IDs or search
|
||||
queries for titles being looked up. A single API key is used for the
|
||||
entire instance — TMDB cannot identify individual users. No
|
||||
personal data (watch history, ratings, etc.) is ever sent to TMDB.
|
||||
</p>
|
||||
<p>
|
||||
When the local image cache is enabled (the default), poster and backdrop
|
||||
images are downloaded from the TMDB CDN and served from your server.
|
||||
When disabled, images are loaded directly from TMDB’s CDN by the
|
||||
client.
|
||||
</p>
|
||||
|
||||
<h3>Sofa Public API</h3>
|
||||
<p>Your server may contact the Sofa public API for two purposes:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Update checks</strong> — a periodic request to{" "}
|
||||
<code>public-api.sofa.watch</code> to check for new releases. Only a
|
||||
user agent string is sent; no instance or user data is included. Can
|
||||
be disabled in admin settings.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Telemetry</strong> — an optional, anonymous report sent
|
||||
at most once every 24 hours. It includes a random instance ID, the
|
||||
Sofa version, CPU architecture, bucketed user and title counts (e.g.
|
||||
“2-5”), and which optional features are enabled. No
|
||||
personal data, watch history, or exact counts are included. Telemetry
|
||||
is <strong>disabled by default</strong> and must be explicitly enabled
|
||||
by an admin. See the{" "}
|
||||
<Link href="/docs/telemetry">telemetry documentation</Link> for full
|
||||
details.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>PostHog (Mobile App Only)</h3>
|
||||
<p>
|
||||
The native iOS and Android app includes optional, anonymous analytics
|
||||
powered by PostHog. This tracks screen views and app lifecycle events
|
||||
— no personal data, search queries, or watch history is collected.
|
||||
Analytics is <strong>disabled by default</strong> and requires explicit
|
||||
opt-in. On iOS, Apple’s App Tracking Transparency prompt is shown
|
||||
first. You can change your preference at any time in the app’s
|
||||
settings.
|
||||
</p>
|
||||
|
||||
<h3>Media Server Integrations</h3>
|
||||
<p>
|
||||
If you connect Plex, Jellyfin, or Emby, those services send webhook
|
||||
events <em>to</em> your Sofa server when you finish watching something.
|
||||
This data is processed and stored locally. Sofa does not send data back
|
||||
to your media servers.
|
||||
</p>
|
||||
|
||||
<h3>Sonarr & Radarr</h3>
|
||||
<p>
|
||||
If you use Sonarr or Radarr integration, those services pull your
|
||||
watchlist from Sofa via authenticated API requests. Sofa does not push
|
||||
data to them.
|
||||
</p>
|
||||
|
||||
<h2>Cookies</h2>
|
||||
<p>
|
||||
Sofa uses a session cookie to keep you logged in. This cookie is
|
||||
HTTP-only, same-site, and contains only a session token. No third-party
|
||||
cookies are set by the web app.
|
||||
</p>
|
||||
|
||||
<h2>Data Sharing</h2>
|
||||
<p>
|
||||
Because Sofa is self-hosted, there is no central service that has access
|
||||
to your data. The project maintainers have no access to your database,
|
||||
your watch history, or your account information. The only data that
|
||||
leaves your server is described in the{" "}
|
||||
<a href="#external-services">External Services</a> section above.
|
||||
</p>
|
||||
|
||||
<h2>Data Retention & Deletion</h2>
|
||||
<p>
|
||||
All data is stored in a single SQLite file on your server. You have full
|
||||
control over it:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Admin users can delete other user accounts, which cascades to all
|
||||
associated viewing history and ratings
|
||||
</li>
|
||||
<li>
|
||||
Scheduled backups are automatically pruned after a configurable
|
||||
retention limit (default: 7)
|
||||
</li>
|
||||
<li>Sessions and verification tokens expire automatically</li>
|
||||
<li>Deleting the database file removes all data entirely</li>
|
||||
</ul>
|
||||
|
||||
<h2>Children</h2>
|
||||
<p>
|
||||
Sofa is not directed at children under 13. Since the application is
|
||||
self-hosted, account creation is controlled entirely by the server
|
||||
administrator.
|
||||
</p>
|
||||
|
||||
<h2>Open Source</h2>
|
||||
<p>
|
||||
Sofa is open source under the MIT License. You can audit exactly what
|
||||
data is collected and how it is handled by reviewing the{" "}
|
||||
<a
|
||||
href="https://github.com/jakejarvis/sofa"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
source code
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
|
||||
<h2>Changes</h2>
|
||||
<p>
|
||||
This policy may be updated as new features are added. Changes will be
|
||||
reflected in the “Last updated” date above and committed to
|
||||
the repository.
|
||||
</p>
|
||||
|
||||
<h2>Contact</h2>
|
||||
<p>
|
||||
Questions or concerns about privacy can be raised via{" "}
|
||||
<a
|
||||
href="https://github.com/jakejarvis/sofa/issues"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
GitHub Issues
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user