Files
iptvnator/apps/website/src/components/BaseHead.astro
T
4grayandClaude Opus 5 61ac15372c perf(website): serve fonts and the avatar locally, load comments on demand
Every page pulled its three typefaces from fonts.googleapis.com and
fonts.gstatic.com, each blog post fetched the author avatar from
githubusercontent.com, and the giscus client script ran on page load. That is
four outside origins contacted before a reader does anything, each costing a
DNS lookup and a TLS handshake on the critical path.

Fonts now come from the @fontsource packages the app already uses and are
emitted as .woff2 beside the site; the avatar is a 3 KB file in public/; and
the giscus embed is created by a "Show comments" button that carries the
configuration as data attributes, so the script is only built when a reader
asks for it.

A delivered page now makes no third-party request at all, verified across the
whole build. The variable Bricolage package names itself "Bricolage Grotesque
Variable", so that exact name leads the display stack in the Tailwind config.
The giscus test now checks the button configuration and asserts the client
script is absent from the delivered HTML.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 17:19:04 +02:00

81 lines
3.0 KiB
Plaintext

---
interface Props {
title: string;
description: string;
image?: string;
type?: 'website' | 'article';
noindex?: boolean;
keywords?: string[];
publishedTime?: string;
modifiedTime?: string;
jsonLd?: Record<string, unknown> | Array<Record<string, unknown>>;
}
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const {
title,
description,
image = '/iptvnator/og-image.png',
type = 'website',
noindex = false,
keywords = [],
publishedTime,
modifiedTime,
jsonLd,
} = Astro.props;
const absoluteImageURL = new URL(image, Astro.site);
const robotsContent = noindex
? 'noindex, nofollow, noarchive'
: 'index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1';
const schemaPayload = jsonLd
? JSON.stringify(Array.isArray(jsonLd) ? jsonLd : [jsonLd])
: null;
---
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/iptvnator/favicon.ico" sizes="any" />
<link rel="icon" type="image/png" sizes="16x16" href="/iptvnator/favicon-16x16.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/iptvnator/favicon-32x32.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/iptvnator/apple-touch-icon.png" />
<link rel="manifest" href="/iptvnator/site.webmanifest" />
<meta name="generator" content={Astro.generator} />
<meta name="robots" content={robotsContent} />
<meta name="referrer" content="strict-origin-when-cross-origin" />
<meta name="author" content="4gray" />
<meta name="theme-color" content="#0a0a08" />
<meta name="format-detection" content="telephone=no" />
{keywords.length > 0 && <meta name="keywords" content={keywords.join(', ')} />}
<!-- Canonical URL -->
<link rel="canonical" href={canonicalURL.toString()} />
<!-- Primary Meta Tags -->
<title>{title}</title>
<meta name="title" content={title} />
<meta name="description" content={description} />
<!-- Open Graph / Facebook -->
<meta property="og:type" content={type} />
<meta property="og:site_name" content="IPTVnator" />
<meta property="og:locale" content="en_US" />
<meta property="og:url" content={canonicalURL.toString()} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:image" content={absoluteImageURL.toString()} />
<meta property="og:image:secure_url" content={absoluteImageURL.toString()} />
{type === 'article' && publishedTime && <meta property="article:published_time" content={publishedTime} />}
{type === 'article' && modifiedTime && <meta property="article:modified_time" content={modifiedTime} />}
<!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={canonicalURL.toString()} />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} />
<meta property="twitter:image" content={absoluteImageURL.toString()} />
{schemaPayload && (
<script type="application/ld+json" set:html={schemaPayload} />
)}