feat(tv-anarchy): add landing page design

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-06-09 21:50:39 -07:00
parent a22340b002
commit d79e99c21c
5 changed files with 248 additions and 0 deletions

248
site/index.html Normal file
View file

@ -0,0 +1,248 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TVAnarchy — your media stack, one native app</title>
<style>
:root {
--bg: #0c0c0f;
--panel: #16161c;
--line: #26262e;
--text: #e8e8ee;
--dim: #9a9aa8;
--accent: #4c8dff;
--green: #3ddc84;
--mono: "SF Mono", ui-monospace, Menlo, monospace;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg);
color: var(--text);
font: 16px/1.65 -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.wrap { max-width: 1060px; margin: 0 auto; padding: 0 24px; }
header { padding: 96px 0 64px; text-align: center; }
.badge {
display: inline-block; font: 12px var(--mono); color: var(--green);
border: 1px solid #234534; background: #11231a; border-radius: 999px;
padding: 4px 14px; margin-bottom: 24px; letter-spacing: .08em;
}
h1 { font-size: 52px; line-height: 1.1; letter-spacing: -.02em; }
h1 .tv { color: var(--accent); }
header p.tag {
color: var(--dim); font-size: 20px; max-width: 640px; margin: 20px auto 0;
}
.pills { margin-top: 28px; display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.pill {
font: 13px var(--mono); color: var(--dim);
border: 1px solid var(--line); border-radius: 999px; padding: 5px 14px;
}
section { padding: 56px 0; border-top: 1px solid var(--line); }
section.flip .row { flex-direction: row-reverse; }
.row { display: flex; gap: 48px; align-items: center; }
.copy { flex: 0 0 320px; }
.copy h2 { font-size: 26px; letter-spacing: -.01em; margin-bottom: 12px; }
.copy h2 .num { color: var(--accent); font: 700 15px var(--mono); display: block; margin-bottom: 8px; }
.copy p { color: var(--dim); font-size: 15px; }
.copy ul { margin-top: 14px; list-style: none; }
.copy li { color: var(--dim); font-size: 14px; padding: 3px 0 3px 22px; position: relative; }
.copy li::before { content: "→"; color: var(--accent); position: absolute; left: 0; }
.shot { flex: 1; min-width: 0; }
.shot img {
width: 100%; display: block; border-radius: 10px;
border: 1px solid var(--line);
box-shadow: 0 24px 60px -24px rgba(0,0,0,.8);
}
.arch { background: var(--panel); }
.arch h2 { text-align: center; font-size: 26px; margin-bottom: 8px; }
.arch > .wrap > p { text-align: center; color: var(--dim); max-width: 640px; margin: 0 auto 40px; }
.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.card {
border: 1px solid var(--line); border-radius: 10px; padding: 22px; background: var(--bg);
}
.card h3 { font-size: 16px; margin-bottom: 8px; }
.card h3 code { font: 13px var(--mono); color: var(--accent); }
.card p { color: var(--dim); font-size: 14px; }
footer { padding: 48px 0 72px; text-align: center; color: var(--dim); font-size: 14px; }
footer code { font: 13px var(--mono); color: var(--text); background: var(--panel); padding: 2px 8px; border-radius: 6px; }
@media (max-width: 860px) {
.row, section.flip .row { flex-direction: column; }
.copy { flex: none; }
h1 { font-size: 38px; }
.cards { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<header>
<div class="wrap">
<div class="badge">NATIVE macOS · SWIFTUI</div>
<h1><span class="tv">TV</span>Anarchy</h1>
<p class="tag">One app for the whole home media stack: pick a playback device, browse the library, search and download, and watch — on the laptop or the living-room TV.</p>
<div class="pills">
<span class="pill">VLC · HTTP</span>
<span class="pill">mpv · JSON-IPC over SSH</span>
<span class="pill">QuickTime · AppleScript</span>
<span class="pill">Transmission</span>
<span class="pill">303 shows indexed</span>
</div>
</div>
</header>
<section>
<div class="wrap row">
<div class="copy">
<h2><span class="num">01</span>Home</h2>
<p>Land on what matters: Continue Watching, Recently Added, and per-category rails built from a locally cached library index. The scanner keeps it fresh in the background.</p>
<ul>
<li>Recently added across all folders</li>
<li>TV / Movies / Anime / Cartoons rails</li>
<li>Mini-transport always in reach</li>
</ul>
</div>
<div class="shot"><img src="screenshots/home.png" alt="Home tab with Recently Added and category rails"></div>
</div>
</section>
<section class="flip">
<div class="wrap row">
<div class="copy">
<h2><span class="num">02</span>Library</h2>
<p>The full collection, grouped by configurable folder types. Filter chips and live search narrow 300+ shows to the one you want in a keystroke.</p>
<ul>
<li>Type chips with live counts</li>
<li>Folder → type mapping is yours to edit</li>
<li>Episode-level browse per show</li>
</ul>
</div>
<div class="shot"><img src="screenshots/library.png" alt="Library grid with filter chips"></div>
</div>
</section>
<section>
<div class="wrap row">
<div class="copy">
<h2><span class="num">03</span>Show pages</h2>
<p>Every show gets a season-by-season episode list. Play one episode, or queue the whole run on whichever device is active — the queue follows the show order.</p>
<ul>
<li>Play / Queue all from the header</li>
<li>Per-episode play buttons</li>
<li>"Queued 19 on 'Black TV'" — one click</li>
</ul>
</div>
<div class="shot"><img src="screenshots/library-show.png" alt="Severance show page with two seasons of episodes"></div>
</div>
</section>
<section class="flip">
<div class="wrap row">
<div class="copy">
<h2><span class="num">04</span>Player &amp; devices</h2>
<p>The control plane is native Swift: VLC over HTTP on the laptop, mpv over SSH on the TV box, QuickTime via AppleScript. Switch targets with one click in the toolbar.</p>
<ul>
<li>Transport, volume, subtitle/dub toggle</li>
<li>Sleep timer and host load readout</li>
<li>Device registry editable in-app</li>
</ul>
</div>
<div class="shot"><img src="screenshots/player.png" alt="Player tab with transport controls"></div>
</div>
</section>
<section>
<div class="wrap row">
<div class="copy">
<h2><span class="num">05</span>Search everywhere</h2>
<p>One search box covers the library you have and the torrents you don't. Results show seeders, size, and source — already in your library is flagged first.</p>
<ul>
<li>Library hits ranked above downloads</li>
<li>Seeders / size / tracker at a glance</li>
<li>Add to Transmission with one click</li>
</ul>
</div>
<div class="shot"><img src="screenshots/search.png" alt="Search results for severance: library hit plus 7 torrents"></div>
</div>
</section>
<section class="flip">
<div class="wrap row">
<div class="copy">
<h2><span class="num">06</span>Downloads</h2>
<p>Live Transmission view of everything moving on the storage box: throughput, per-torrent progress, ETA, and a "needs attention" triage for stuck or erroring transfers.</p>
<ul>
<li>44 active · 168 seeding, one screen</li>
<li>Stuck-at-0-peers flagged automatically</li>
<li>Notification when an episode is watchable</li>
</ul>
</div>
<div class="shot"><img src="screenshots/downloads.png" alt="Downloads tab with live progress bars"></div>
</div>
</section>
<section>
<div class="wrap row">
<div class="copy">
<h2><span class="num">07</span>Devices</h2>
<p>The device registry lives in <code style="font-family:var(--mono);font-size:13px">devices.json</code> and is editable in-app. Each entry shows connectivity, roles, and host load — LAN first, WireGuard fallback.</p>
<ul>
<li>Laptop VLC + TV box out of the box</li>
<li>Restart / deploy actions per device</li>
<li>Reload, reset, or reveal the config</li>
</ul>
</div>
<div class="shot"><img src="screenshots/devices.png" alt="Devices tab with Plum VLC and Black TV connected"></div>
</div>
</section>
<section class="flip">
<div class="wrap row">
<div class="copy">
<h2><span class="num">08</span>Logs &amp; settings</h2>
<p>Filterable structured logs for every subsystem, and settings that cover library types, media-key forwarding, download notifications, an offline episode cache, and an importable download VPN.</p>
<ul>
<li>INFO / WARN / ERROR filters</li>
<li>Offline cache: next episodes synced to disk</li>
<li>OpenVPN import for dark download traffic</li>
</ul>
</div>
<div class="shot"><img src="screenshots/settings.png" alt="Settings tab: playback, offline cache, download VPN"></div>
</div>
</section>
<section class="arch">
<div class="wrap">
<h2>How it works</h2>
<p>Hybrid architecture: a native Swift control plane with zero new runtime dependencies, delegating data-heavy work to vendored helper subsystems.</p>
<div class="cards">
<div class="card">
<h3>Control plane · <code>Swift</code></h3>
<p>VLC's Lua HTTP interface for local playback; mpv JSON-IPC tunneled over SSH for the TV attached to the storage box; AppleScript for QuickTime. All first-party frameworks.</p>
</div>
<div class="card">
<h3>Data plane · <code>helpers</code></h3>
<p>Library scanning, metadata enrichment, torrent search, and recommendations run as subprocesses from vendored helper projects — reused, not rewritten.</p>
</div>
<div class="card">
<h3>Fleet · <code>mesh</code></h3>
<p>Devices resolve over the LAN with a WireGuard overlay fallback, so the same app drives the living-room TV from home or from the road.</p>
</div>
</div>
</div>
</section>
<footer>
<div class="wrap">
<p>Build with <code>xcodegen generate && xcodebuild</code> · install with <code>./build-install.sh</code></p>
<p style="margin-top:8px">Screenshots are the real app (v1.1.0) running against the live home stack.</p>
</div>
</footer>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

After

Width:  |  Height:  |  Size: 233 KiB