/** * Lineage per-subdomain downloads page — `lineage.freno.me/downloads` * (see `./deletion-content.ts`). * * Served at the public browser path `/downloads` (vercel.json host rewrites * `lineage.freno.me/*` → the internal `/lineage/*` route prefix, leaving the * browser URL clean. The nav-config "Downloads" * entry and the landing page's Google Play badge both point at this path. * * Download surface (mirrors the Lineage section of the unified * `freno.me/downloads` page, byte-identical asset source): * - Android APK via tRPC `downloads.getDownloadUrl({ asset_name: "lineage" })` * → S3 signed URL for `Life and Lineage.apk`. Reuses the shared * `downloadAsset` helper so the click → redirect → S3 flow is a * single code path shared with the Gaze landing page. * - iOS App Store link (`LINEAGE_APP_STORE_URL`) — absolute external URL, * identical to the link surfaced on the landing page + unified downloads. * * Site-awareness: * - `` reads `useSite()` → the lineage `titleSuffix` * (` | Life and Lineage`) + canonical `https://lineage.freno.me/downloads` * are derived automatically; we pass only the base title here. * - No auth — Lineage's mobile JWT (`LINEAGE_JWT_SECRET`) is for the mobile * app's API calls, not the web downloads page. * * Acceptance: `lineage.localhost:3000/downloads` renders APK + App Store; * clicking APK redirects to an S3 signed URL; the unified downloads page is * unchanged (regression check). */ import { A } from "@solidjs/router"; import { createSignal, onMount, onCleanup } from "solid-js"; import { PageHead } from "~/components/PageHead"; import { EdgeCacheHeaders } from "~/components/EdgeCacheHeaders"; import SubdomainHeader from "~/components/SubdomainHeader"; import DownloadOnAppStore from "~/components/icons/DownloadOnAppStore"; import Button from "~/components/ui/Button"; import { glitchText } from "~/lib/client-utils"; import { downloadAsset } from "~/lib/download-asset"; import { LINEAGE_DOWNLOAD_ASSET, LINEAGE_APK_BUTTON_LABEL, LINEAGE_APP_STORE_URL, LINEAGE_HOME_HREF, PAGE_META } from "~/routes/lineage/downloads-content"; export default function LineageDownloadsPage() { const [title, setTitle] = createSignal("Life and Lineage"); const [loading, setLoading] = createSignal(false); const handleDownload = () => { if (loading()) return; setLoading(true); import("~/lib/api") .then(({ api }) => downloadAsset({ api, assetName: LINEAGE_DOWNLOAD_ASSET, onError: (error) => { console.error("Lineage download error:", error); alert("Failed to initiate download. Please try again."); } }) ) .finally(() => setLoading(false)); }; onMount(() => { const interval = glitchText(title(), setTitle); onCleanup(() => clearInterval(interval)); }); return ( <>
{/* Subtle scanline effect — consistent with the unified downloads page. */}

{">"} {title()}

{/* Android APK via tRPC → S3 signed URL */}
platform: android # android build not optimized
{/* iOS App Store */}
platform: ios
{/* Secondary CTA → landing page */}

← back to Life and Lineage

); }