Files
voculinux/web/src/components/optimized-image.tsx
T
Jatin K MalikandGitHub f7147bdb44 fix(web): SEO fixes from Search Console and Lighthouse audit (#1039)
* fix(web): SEO fixes from Search Console and Lighthouse audit

Technical:
- Emit BreadcrumbList JSON-LD from the same trail as the visual breadcrumbs
  on every SeoSubpageShell page.
- absoluteUrl() no longer appends a trailing slash to file paths. The
  Organization and publisher logo URLs pointed at /vocalinux.png/, a 404.
- Fetch the GitHub star count once at build time in next.config.js and
  drop the client-side api.github.com fetch and preconnect (Lighthouse
  "third-party code" on every page). Falls back to the "GitHub" label.
- Fix h1 -> h3 heading skips on 11 pages by promoting the leading card
  headings to h2; new .subpage-card-title keeps the old h3 sizing.
- Header and footer logo get alt="" next to the visible "Vocalinux" text.
- Footer links every guide, distro and feature page, so the pages added in
  #1038 and /vs-nerd-dictation/ (Discovered, not indexed) and /writers/
  (no inbound links) are linked sitewide.

Titles and descriptions:
- Rewrite titles/descriptions for pages with high impressions and low CTR
  in Search Console (home, FAQ, compare, languages, open-source, GPU,
  alternatives, offline, install) to lead with the queries they rank for.
- Distro pages use "<Distro> Speech to Text: Offline Voice Typing Setup"
  as the search title; the on-page h1 is unchanged.
- Remove brand repetition and shorten 75+ character titles.
- Bump sitemap lastmod for the rewritten pages.

* fix(web): keep home install card titles styled

The home page's install cards still use h3; only /install/ moved to h2.
Style both so the home cards keep their size and spacing.
2026-11-01 01:39:01 -07:00

79 lines
1.8 KiB
TypeScript

"use client";
import React from "react";
import Image from "next/image";
interface OptimizedImageProps {
src: string;
alt: string;
width: number;
height: number;
className?: string;
priority?: boolean;
}
/**
* Optimized image component that uses WebP format with PNG fallback.
* Browsers that support WebP will load the smaller WebP file, while older
* browsers will fallback to PNG format.
*/
export const OptimizedImage: React.FC<OptimizedImageProps> = ({
src,
alt,
width,
height,
className = "",
priority = false,
}) => {
// Get WebP version of the image
const webpSrc = src.replace(/\.(png|jpg|jpeg)$/i, '.webp');
// For Next.js Image component with priority and proper optimization
// we use the Next.js Image with WebP source
return (
<picture className={className}>
<source srcSet={webpSrc} type="image/webp" />
<Image
src={src}
alt={alt}
width={width}
height={height}
className={className}
priority={priority}
/>
</picture>
);
};
/**
* Specialized Vocalinux logo component with WebP support
*/
export const VocalinuxLogo: React.FC<{
className?: string;
width?: number;
height?: number;
priority?: boolean;
/** Set when the visible "Vocalinux" text sits next to the mark. */
decorative?: boolean;
}> = ({
className = "",
width = 32,
height = 32,
priority = false,
decorative = false,
}) => {
return (
// SVG lockup; next/image is for raster.
// eslint-disable-next-line @next/next/no-img-element
<img
src="/brand/vocalinux-mark-circle.svg"
alt={decorative ? "" : "Vocalinux"}
width={width}
height={height}
className={className}
decoding="async"
loading={priority ? "eager" : "lazy"}
/>
);
};