feat(tv-anarchy): ✨ add landing page design
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
a22340b002
commit
d79e99c21c
5 changed files with 248 additions and 0 deletions
248
site/index.html
Normal file
248
site/index.html
Normal 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 & 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 & 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>
|
||||
BIN
site/screenshots/library-show.png
Normal file
BIN
site/screenshots/library-show.png
Normal file
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 |
Loading…
Add table
Reference in a new issue