mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-13 22:03:13 -06:00
* feat(seo): enable IndexNow (key file + submission script) Instant re-crawl pings to Bing/Yandex/Seznam/Naver on content changes (Google ignores IndexNow but uses the same sitemap). Hosts the ownership key at frontend/<key>.txt (served at https://screentinker.com/<key>.txt) and adds scripts/indexnow-submit.sh which POSTs the sitemap URLs to api.indexnow.org (DRY_RUN=1 to preview). Run after a content deploy / from CI. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(seo): landing-page optimization pass (schema fixes, FAQ, content depth, CWV) From a 3-way SEO audit (technical / structured-data / content). Highest-value fixes: Structured data (penalty risk + rich results): - REMOVE the fabricated aggregateRating (4.8/50) from SoftwareApplication — no visible reviews on the page = a "spammy structured markup" risk. Replace loose Offers with a proper AggregateOffer + publisher + image/screenshot. - Add a VISIBLE FAQ section (10 Q&As) so the FAQPage schema finally has on-page content (it shipped 4 Q&As with no visible counterpart — a mismatch); expand the FAQPage JSON-LD to mirror all 10. - Add a WebSite entity block; add YouTube to Organization sameAs + a description. - Fix the guides/compare BreadcrumbList position-2 target (dead /#features -> /). Content / keywords / IA: - Hero + Features subtitle rewritten to surface "digital signage software" / "digital signage CMS" / "self-host" / "free" above the fold. - New "How It Works" (3-step) and "Use Cases / Industries" (8 verticals) sections for snippet + long-tail intent. Platform tiles (Android TV / Fire TV / Raspberry Pi) now link to their guides. - FAQ answers add keyword-rich internal links to the guides + compare pages. Technical / Core Web Vitals: - Lazy-load the YouTube iframe (loading=lazy + youtube-nocookie + explicit width/height) — the top LCP/TBT win on mobile. - Title 84->~60 chars (keyword-front), meta description ~178->~156 + CTA. - <div> footer -> <footer> landmark; favicon sizes (192+512). - sitemap.xml: add <lastmod> to all 10 URLs. All JSON-LD validated (4 blocks parse; single H1; no fabricated data). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(seo): open-source/what-is pillars, Xibo+Anthias compares, integrations hub [#177] Competitor-SEO gap-fill from the Yodeck/ScreenCloud/OptiSigns/Xibo teardowns. 11 new static pages + sitemap/landing/README wiring. All match the existing seo-page.css template; BreadcrumbList on every page, FAQPage (visible-backed) on guides + integration spokes. No fabricated ratings. Pillar guides: - guides/open-source-digital-signage.html (head term "open source digital signage") - guides/what-is-digital-signage.html (TOFU definitional pillar + FAQ) Comparisons (the open-source SERP Xibo/Anthias own): - compare/xibo-alternative.html (wedge: every ScreenTinker player free vs Xibo's paid Android/Tizen/webOS licences; no free plan) - compare/anthias-alternative.html (wedge: fleet + video walls + multi-platform vs one-Pi-one-screen) Integrations (OptiSigns' top tactic — one page per app): - integrations/index.html hub - google-slides / canva / power-bi (honestly framed as the universal Webpage widget, with the X-Frame-Options / publish-vs-edit-URL caveat + Power BI public-data warning) - youtube / rss / weather (native widgets) Wiring: - sitemap.xml +11 URLs (lastmod 2026-07-13) - landing.html Resources grid: 6 new cards (open-source, what-is, vs Xibo, vs Anthias, integrations hub) - README.md: keyword-rich open-source/self-hosted intro + platform list + guide links (GitHub-SERP asset) - docs/seo-directory-listings.md: off-repo G2/Capterra/AlternativeTo/awesome-selfhosted/fingoweb submission checklist + reusable kit Validated: all JSON-LD parses, canonicals match paths, 0 broken internal links, sitemap well-formed (21 URLs). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
32 lines
1.6 KiB
Bash
Executable file
32 lines
1.6 KiB
Bash
Executable file
#!/bin/bash
|
|
# Submit the sitemap URLs to IndexNow — instant "this changed, re-crawl it" pings to Bing,
|
|
# Yandex, Seznam, Naver (and anyone else on the shared IndexNow endpoint). Google doesn't use
|
|
# IndexNow but honors the same sitemap. Run after a content deploy, or from CI/cron.
|
|
#
|
|
# Prereq: the IndexNow key file (frontend/<KEY>.txt) must be DEPLOYED and reachable at
|
|
# https://<host>/<KEY>.txt — that's how IndexNow verifies ownership.
|
|
#
|
|
# scripts/indexnow-submit.sh [host] (default host: screentinker.com)
|
|
# DRY_RUN=1 scripts/indexnow-submit.sh (print the payload, don't POST)
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.."
|
|
HOST="${1:-screentinker.com}"
|
|
|
|
KEY_FILE="$(find frontend -maxdepth 1 -type f -name '*.txt' | grep -E '/[0-9a-f]{16,}\.txt$' | head -1 || true)"
|
|
[ -n "$KEY_FILE" ] || { echo "ERROR: no IndexNow key file (frontend/<hex>.txt) found." >&2; exit 1; }
|
|
KEY="$(basename "$KEY_FILE" .txt)"
|
|
|
|
mapfile -t URLS < <(grep -oE '<loc>[^<]+</loc>' frontend/sitemap.xml | sed -E 's#</?loc>##g')
|
|
[ "${#URLS[@]}" -gt 0 ] || { echo "ERROR: no <loc> URLs in frontend/sitemap.xml." >&2; exit 1; }
|
|
|
|
PAYLOAD="$(node -e '
|
|
const [host, key] = [process.argv[1], process.argv[2]];
|
|
const urlList = process.argv.slice(3);
|
|
process.stdout.write(JSON.stringify({ host, key, keyLocation: `https://${host}/${key}.txt`, urlList }));
|
|
' "$HOST" "$KEY" "${URLS[@]}")"
|
|
|
|
echo "IndexNow: ${#URLS[@]} URLs, host=$HOST, key=$KEY"
|
|
if [ "${DRY_RUN:-0}" = "1" ]; then echo "$PAYLOAD"; echo "(DRY_RUN — not submitted)"; exit 0; fi
|
|
curl -sS -w '\nHTTP %{http_code}\n' -X POST 'https://api.indexnow.org/indexnow' \
|
|
-H 'Content-Type: application/json; charset=utf-8' --data "$PAYLOAD"
|