Files
iptvnator/apps/website/src/components/Footer.astro
T
4grayandClaude Fable 5.1 baba0529ef feat(website): rebuild the hero, features, download and support sections (#1551)
* feat(website): rebuild the hero, features, download and support sections

Third landing redesign PR: the home page now speaks the app's own
language instead of a template's.

- Hero: left-aligned headline, a primary button that follows the
  visitor's OS (server-rendered fallback goes to /download/), an "All
  platforms" button and a text link for self-hosting. Project numbers
  (stars, downloads, languages, license) are set in the page's own
  typography from the GitHub API at build time (`lib/github-stats.ts`);
  anything the build cannot resolve is left out rather than faked. A
  small "Now playing" card with fictional demo content replaces the
  mascot, badges and social chips; the screenshot is lit by a blurred
  copy of itself, like the player's ambient mode.
- Features: a bento of interface fragments (EPG rows with progress,
  posters with a resume bar, a download queue with a REC dot, a remote
  D-pad) instead of numbered cards with icon watermarks and a marquee.
  The marquee CSS is gone.
- Download: one row per platform with the release's file names and a
  "Detected" badge for the visitor's OS (`lib/detect-platform.ts`),
  package-manager commands in the same panel.
- Support becomes a single row; the disclaimer moves into the footer,
  which also gets the mascot and a link list.
- Home sections drop the decorative eyebrows and the divider rules; the
  unused broadcast-wave, support-signal and watermark illustrations are
  removed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* test(website): cover the rebuilt home sections and the OS-aware download CTA

`website-home-sections.test.mjs` (in the website test target) reads the
built home page — generic hero CTA to /download/, project facts, no
badge images or dashed borders, every feature page linked from the
bento, one download row per platform with release file names and the
Detected badge hidden, the disclaimer and mascot in the footer — and
then drives it in Chromium under Windows, macOS, Linux and Android user
agents: the primary button and the Detected row follow the platform,
the phone keeps the generic markup, and the copy button writes the
command to the clipboard.

`detectPlatform()` now consults the user-agent string before the
client-hints platform and the deprecated `navigator.platform`, so the
source a visitor's tools actually change decides first; silent sources
fall through instead of vetoing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* fix(website): keep iPads on the generic download path

iPadOS asks for desktop sites with a Macintosh user agent and a
`MacIntel` platform, so the OS guess sent iPad visitors to the macOS
installers. A "mac" verdict is now trusted only on a device without
touch points: no Mac has a touch screen, every iPad reports several.
The browser test adds an iPad-in-desktop-mode row to the generic-device
matrix next to the Android phone.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 00:51:46 +02:00

97 lines
5.2 KiB
Plaintext

---
import { Image } from 'astro:assets';
import mascotImg from '../assets/illustrations/iptvnator-1-mascot.png';
const socialLinks = [
{
label: 'GitHub',
href: 'https://github.com/4gray/iptvnator',
icon: 'M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z',
},
{
label: 'Telegram',
href: 'https://t.me/iptvnator',
icon: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69.01-.03.01-.14-.07-.2-.08-.06-.19-.04-.27-.02-.12.03-1.99 1.27-5.62 3.72-.53.36-1.01.54-1.44.53-.47-.01-1.38-.27-2.06-.49-.83-.27-1.49-.42-1.43-.88.03-.24.37-.49 1.02-.74 3.99-1.74 6.65-2.89 7.99-3.44 3.81-1.58 4.6-1.86 5.12-1.87.11 0 .37.03.54.17.14.12.18.28.2.45-.01.06.01.24 0 .38z',
},
{
label: 'Bluesky',
href: 'https://bsky.app/profile/4gray.bsky.social',
icon: 'M13.202 10.857c2.752 2.066 5.711 6.254 6.798 8.502 1.087-2.248 4.046-6.436 6.798-8.502 1.985-1.49 5.202-2.644 5.202 1.026 0 .733-.42 6.157-.667 7.038-.857 3.061-3.978 3.842-6.755 3.37 4.854.826 6.089 3.562 3.422 6.299-5.065 5.197-7.279-1.304-7.847-2.97-.104-.305-.153-.448-.153-.327 0-.121-.049.021-.153.327-.567 1.666-2.782 8.166-7.847 2.97-2.667-2.736-1.432-5.473 3.422-6.299-2.777.473-5.899-.308-6.755-3.37-.246-.881-.667-6.305-.667-7.038 0-3.67 3.217-2.517 5.202-1.026Z',
},
{
label: 'Sponsor',
href: 'https://ko-fi.com/4gray',
icon: 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z',
},
];
const footerLinks = [
{ label: 'Features', href: '/iptvnator/features/' },
{ label: 'Compare', href: '/iptvnator/compare/' },
{ label: 'Download', href: '/iptvnator/download/' },
{ label: 'Blog', href: '/iptvnator/blog/' },
{ label: 'Unofficial sites', href: '/iptvnator/blog/beware-unofficial-iptvnator-websites/' },
];
---
<footer class="relative overflow-hidden border-t border-surface-800">
<!-- The mascot lives here now: a sign-off, not a hero competitor -->
<div class="pointer-events-none absolute -bottom-6 right-0 hidden w-64 opacity-70 md:block lg:w-72" aria-hidden="true">
<Image src={mascotImg} alt="" width={520} class="h-auto w-full object-contain" loading="lazy" />
</div>
<div class="relative z-10 mx-auto max-w-6xl px-6 py-16">
<div class="grid gap-10 md:grid-cols-[minmax(0,1.2fr)_minmax(0,0.8fr)] md:pr-72">
<div>
<div class="flex items-center gap-2.5">
<img src="/iptvnator/favicon-256x256.png" alt="IPTVnator logo" class="h-6 w-6" />
<span class="font-display text-lg font-semibold text-surface-100">IPTVnator</span>
</div>
<p class="mt-4 max-w-md text-sm leading-relaxed text-surface-400">
IPTVnator is a media player. It does not provide, host or sell any media, playlists, channels or EPG
data; channel names, logos and titles in screenshots are demo content. You are responsible for the
sources you use and for complying with local laws and rights.
</p>
<div class="mt-5 flex items-center gap-1">
{
socialLinks.map((link) => (
<a
href={link.href}
target="_blank"
rel="noopener noreferrer"
class="rounded-lg p-2.5 text-surface-500 transition-colors duration-200 hover:bg-surface-900 hover:text-surface-100"
aria-label={link.label}
>
<svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true">
<path d={link.icon} />
</svg>
</a>
))
}
</div>
</div>
<nav aria-label="Footer">
<ul class="grid gap-2 text-sm">
{
footerLinks.map((link) => (
<li>
<a href={link.href} class="text-surface-400 transition-colors duration-200 hover:text-surface-100">
{link.label}
</a>
</li>
))
}
</ul>
</nav>
</div>
<div class="mt-12 flex flex-col gap-2 border-t border-surface-800 pt-6 font-mono text-[11px] text-surface-500 sm:flex-row sm:justify-between md:pr-72">
<p>
MIT License · Built with <a href="https://astro.build" class="transition-colors hover:text-surface-200">Astro</a>.
</p>
<p>Hosted on GitHub Pages.</p>
</div>
</div>
</footer>