mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-11 19:46:16 -08:00
Publish /compare/ with three pages answering the choices the app asks users to make: M3U vs Xtream Codes vs Stalker portal, the built-in web players vs embedded MPV vs external MPV/VLC, and the desktop app vs the self-hosted browser version. Each opens with a one-paragraph verdict, carries a feature matrix whose cells are yes, no or a qualifier, and emits WebPage / FAQPage / BreadcrumbList JSON-LD — not SoftwareApplication, because guidance is not a product listing. These compare IPTVnator's own options against each other rather than naming other products, so every cell is checkable against this repository. Pages that name competitors remain phase 3's open half; the plan now records what has to be decided first. A registry in src/lib/comparisons.ts drives the hub, the switcher and the tests. The header gains a Compare entry and the features hub links across. tools/testing/website-compare-pages.test.mjs checks canonical URLs, the verdict block, the table, schema, cross-links and sitemap entries. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
118 lines
5.6 KiB
Markdown
118 lines
5.6 KiB
Markdown
# IPTVnator Website
|
|
|
|
The website is an Astro static site deployed to GitHub Pages at `https://4gray.github.io/iptvnator/`.
|
|
|
|
## Blog Comments
|
|
|
|
Blog posts render Giscus comments from `apps/website/src/components/GiscusComments.astro`.
|
|
Giscus stores comments in GitHub Discussions for `4gray/iptvnator` and maps each page to a discussion by `pathname`, including the GitHub Pages base path such as `/iptvnator/blog/why-external-players-help/`.
|
|
|
|
The embed is wired to the dedicated `Blog comments` discussion category:
|
|
|
|
- Repository id: `MDEwOlJlcG9zaXRvcnkyMTMxOTQ3Mzg=`
|
|
- Category id: `DIC_kwDODLUX8s4C9eBJ`
|
|
- Mapping: `pathname`
|
|
- Theme: `transparent_dark`
|
|
|
|
If the category is recreated, query the new category id:
|
|
|
|
```bash
|
|
gh api graphql \
|
|
-f owner=4gray \
|
|
-f name=iptvnator \
|
|
-f query='query($owner:String!, $name:String!) { repository(owner:$owner, name:$name) { discussionCategories(first:25) { nodes { id name slug isAnswerable } } } }'
|
|
```
|
|
|
|
Then update `data-category-id` in `GiscusComments.astro`.
|
|
|
|
Moderation happens in GitHub Discussions. Maintainers can hide, delete, lock, or move discussions and comments from the repository Discussions UI.
|
|
|
|
## Download Pages
|
|
|
|
`/download/` plus `/download/windows/`, `/download/macos/` and `/download/linux/`
|
|
are per-OS landing pages (`apps/website/src/pages/download/`). They exist for
|
|
search visibility on "IPTVnator <OS> download" style queries and to spare users
|
|
the 27-asset GitHub release page; each carries OS-specific install steps,
|
|
requirements, an FAQ and `SoftwareApplication` / `FAQPage` / `BreadcrumbList`
|
|
structured data. Shared pieces live in `src/components/download/` and reuse the
|
|
blog components (`StepRail`, `Alert`, `FaqAccordion`, `CopyCommand`).
|
|
|
|
### Latest-release resolution
|
|
|
|
Direct asset links need the release version, so `src/lib/downloads.ts`
|
|
resolves it at build time:
|
|
|
|
1. `GET https://api.github.com/repos/4gray/iptvnator/releases/latest` (8 s
|
|
timeout). The asset list from the *published* release is authoritative:
|
|
options whose file is missing are dropped, sizes and the publish date come
|
|
from the API. `deploy-website.yml` passes `GITHUB_TOKEN` to the build so
|
|
the call is authenticated.
|
|
2. Fallback: the root `package.json` version with the asset naming pattern
|
|
from `electron-builder.json`. This is deterministic but cannot prove the
|
|
files exist yet (a version bump lands on `master` before the release is
|
|
published), so a warning is printed. Set `WEBSITE_SKIP_RELEASE_FETCH=1` to
|
|
force it for offline or reproducible builds.
|
|
|
|
Both paths produce the same page structure. Adding an artifact means adding a
|
|
`DownloadOption` (matcher + fallback name) in `downloads.ts`; the pages and the
|
|
hub pick it up. The homepage `SoftwareApplication` schema reads the same
|
|
resolved version.
|
|
|
|
`pnpm nx test website` builds the site and runs
|
|
`tools/testing/website-download-pages.test.mjs`, which checks titles,
|
|
canonicals, direct asset links, JSON-LD, cross-links and sitemap entries
|
|
without depending on a specific version.
|
|
|
|
## Guides
|
|
|
|
Evergreen how-to posts live in the blog collection next to release notes
|
|
(`xtream-codes-setup-guide.mdx`, `stalker-portal-setup-guide.mdx` and
|
|
`m3u-playlist-epg-setup-guide.mdx` in `apps/website/src/content/blog/`).
|
|
Two conventions set them apart:
|
|
|
|
- **`faq` frontmatter.** An optional list of `{ q, a }` entries. `BlogPost.astro`
|
|
renders it as an accordion after the body and emits a `FAQPage` JSON-LD block
|
|
next to the `BlogPosting` one, so the answers can surface as rich results.
|
|
- **Screenshots from the capture script.** Guide frames are captured by
|
|
`pnpm release:screenshots --group guides` into
|
|
`apps/website/public/blog/guides/screenshots/<slug>-<theme>.png`; the shots are
|
|
declared in `tools/release/screenshots.manifest.json` with `"group": "guides"`
|
|
and never appear in a release run.
|
|
|
|
`tools/testing/website-guides.test.mjs` (part of `pnpm nx test website`) checks
|
|
each guide for the FAQPage schema, a link to the download hub and the presence
|
|
of every referenced screenshot in the build output.
|
|
|
|
## Feature Pages
|
|
|
|
`/features/` plus one page per feature (`m3u-player`, `xtream-codes-player`,
|
|
`stalker-portal-player`, `epg`, `remote-control`) live in
|
|
`apps/website/src/pages/features/`. They target "<feature> player" style
|
|
searches, reuse the download-page sections, and each carries
|
|
`SoftwareApplication` (with `featureList`) / `FAQPage` / `BreadcrumbList`
|
|
structured data. The registry in `src/lib/features.ts` drives the hub, the
|
|
per-page switcher, the homepage feature cards and
|
|
`tools/testing/website-feature-pages.test.mjs`; adding a page means adding one
|
|
registry entry and one `.astro` file. Screenshots come only from the
|
|
mock-backed guide and release captures, never from the older homepage
|
|
screenshots that show real channel names.
|
|
|
|
## Comparison Pages
|
|
|
|
`/compare/` plus one page per decision the app asks users to make
|
|
(`m3u-vs-xtream-vs-stalker`, `playback-engines`, `desktop-vs-browser`) live in
|
|
`apps/website/src/pages/compare/`. They compare IPTVnator's own options against
|
|
each other, never other products, so every claim is checkable against this
|
|
repository; the registry is `src/lib/comparisons.ts`.
|
|
|
|
Each page opens with a one-paragraph verdict (`CompareHero`), carries at least
|
|
one `ComparisonTable` (cells are `true`, `false` or a qualifying string) and
|
|
emits `WebPage` / `FAQPage` / `BreadcrumbList` JSON-LD from
|
|
`src/lib/comparison-schema.ts` — deliberately not `SoftwareApplication`, since
|
|
these pages are guidance rather than a product listing, and
|
|
`tools/testing/website-compare-pages.test.mjs` asserts that.
|
|
|
|
Naming a competitor on these pages is a product decision, not a technical one.
|
|
Phase 3 of `.plans/2026-09-03-marketing-landing-pages.md` covers that and is
|
|
still open.
|