diff --git a/.github/workflows/unified-pipeline.yml b/.github/workflows/unified-pipeline.yml index 957e16b..c11d15b 100644 --- a/.github/workflows/unified-pipeline.yml +++ b/.github/workflows/unified-pipeline.yml @@ -576,6 +576,9 @@ jobs: - name: Install and build working-directory: ./web + env: + # next.config.js reads the repo star count at build time + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci || npm install npm run deploy diff --git a/web/next.config.js b/web/next.config.js index 992156e..063779c 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -1,3 +1,5 @@ +import { PHASE_PRODUCTION_BUILD } from 'next/constants.js'; + // @ts-ignore /** @type {import("next").NextConfig} */ const config = { @@ -70,4 +72,30 @@ const config = { return config; }, }; -export default config; + +// The header star count is fetched once per production build and inlined, so +// visitors never call api.github.com (Lighthouse flagged it as third-party +// code on every page). Any failure falls back to the plain "GitHub" label. +async function fetchGitHubStars() { + try { + const res = await fetch('https://api.github.com/repos/VocaHQ/vocalinux', { + headers: process.env.GITHUB_TOKEN + ? { Authorization: `Bearer ${process.env.GITHUB_TOKEN}` } + : {}, + signal: AbortSignal.timeout(5000), + }); + if (!res.ok) return ''; + const data = await res.json(); + return data.stargazers_count ? String(data.stargazers_count) : ''; + } catch { + return ''; + } +} + +export default async function nextConfig(phase) { + if (phase !== PHASE_PRODUCTION_BUILD) return config; + return { + ...config, + env: { NEXT_PUBLIC_GITHUB_STARS: await fetchGitHubStars() }, + }; +} diff --git a/web/public/sitemap.xml b/web/public/sitemap.xml index b3252ed..a2fd7c2 100644 --- a/web/public/sitemap.xml +++ b/web/public/sitemap.xml @@ -2,37 +2,37 @@ https://vocalinux.com/ - 2026-06-11 + 2026-11-01 weekly 1.0 https://vocalinux.com/install/ - 2026-02-22 + 2026-11-01 weekly 0.9 https://vocalinux.com/install/ubuntu/ - 2026-02-22 + 2026-11-01 monthly 0.8 https://vocalinux.com/install/fedora/ - 2026-02-22 + 2026-11-01 monthly 0.8 https://vocalinux.com/install/arch/ - 2026-02-22 + 2026-11-01 monthly 0.8 https://vocalinux.com/compare/ - 2026-06-11 + 2026-11-01 monthly 0.8 @@ -50,7 +50,7 @@ https://vocalinux.com/faq/ - 2026-06-11 + 2026-11-01 monthly 0.8 @@ -80,14 +80,14 @@ https://vocalinux.com/alternatives/ - 2026-02-22 + 2026-11-01 monthly 0.8 https://vocalinux.com/languages/ - 2026-02-22 + 2026-11-01 monthly 0.8 @@ -129,13 +129,13 @@ https://vocalinux.com/gpu-acceleration/ - 2026-02-22 + 2026-11-01 monthly 0.8 https://vocalinux.com/open-source/ - 2026-02-22 + 2026-11-01 monthly 0.8 @@ -153,7 +153,7 @@ https://vocalinux.com/offline/ - 2026-02-22 + 2026-11-01 monthly 0.8 diff --git a/web/src/app/alternatives/page.tsx b/web/src/app/alternatives/page.tsx index 67d548f..6dfb510 100644 --- a/web/src/app/alternatives/page.tsx +++ b/web/src/app/alternatives/page.tsx @@ -56,9 +56,9 @@ const comparisonTable = [ ]; export const metadata: Metadata = buildPageMetadata({ - title: "Vocalinux Alternatives - Linux Voice Dictation Comparison", + title: "Linux Alternatives to Dragon, Otter.ai and Speechnotes", description: - "Compare Vocalinux to Dragon, Otter.ai, Google Voice Typing, and other speech-to-text alternatives. See why Vocalinux is the best choice for Linux voice dictation.", + "Looking for Dragon NaturallySpeaking, Otter.ai or Google Voice Typing on Linux? Compare offline Linux dictation options, including Vocalinux and Nerd Dictation.", path: "/alternatives", keywords: [ "vocalinux alternatives", diff --git a/web/src/app/autostart/page.tsx b/web/src/app/autostart/page.tsx index 64c6ddc..b594db2 100644 --- a/web/src/app/autostart/page.tsx +++ b/web/src/app/autostart/page.tsx @@ -165,7 +165,7 @@ export default function AutostartPage() { className="rounded-[12px] border border-border bg-background p-5" > -

{method.method}

+

{method.method}

{method.description}

); diff --git a/web/src/app/changelog/page.tsx b/web/src/app/changelog/page.tsx index 5684e57..7a5cc62 100644 --- a/web/src/app/changelog/page.tsx +++ b/web/src/app/changelog/page.tsx @@ -519,7 +519,7 @@ const getTypeStyles = (type: string) => { }; export const metadata: Metadata = buildPageMetadata({ - title: "Vocalinux Changelog - Release History", + title: "Changelog and Release Notes", description: "Track Vocalinux release history and version updates. See what's new in each version of our Linux voice dictation software.", path: "/changelog", diff --git a/web/src/app/compare/page.tsx b/web/src/app/compare/page.tsx index 1f3be6a..a790e3f 100644 --- a/web/src/app/compare/page.tsx +++ b/web/src/app/compare/page.tsx @@ -81,9 +81,9 @@ const engineTable = [ ]; export const metadata: Metadata = buildPageMetadata({ - title: "Whisper.cpp vs Whisper vs VOSK vs Remote API for Linux", + title: "Vosk vs Whisper vs whisper.cpp: Linux Speech Engines", description: - "Compare whisper.cpp, Whisper, VOSK, and Remote API for Linux speech-to-text. See speed, hardware requirements, privacy tradeoffs, and best use cases.", + "Vosk vs Whisper vs whisper.cpp for offline Linux speech to text, plus Faster Whisper, Parakeet and Remote API: speed, accuracy, hardware needs and privacy.", path: "/compare", keywords: [ "whisper.cpp vs vosk", diff --git a/web/src/app/custom-dictionary/page.tsx b/web/src/app/custom-dictionary/page.tsx index a649e45..b3146b5 100644 --- a/web/src/app/custom-dictionary/page.tsx +++ b/web/src/app/custom-dictionary/page.tsx @@ -164,7 +164,7 @@ export default function CustomDictionaryPage() {