Skip to content

Commit fc49253

Browse files
committed
fix(site): resolve Lighthouse contrast & robots.txt issues and overhaul branded OG cards
1 parent bf050b3 commit fc49253

24 files changed

Lines changed: 998 additions & 252 deletions

‎apps/site/baseline/robots.txt‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
User-Agent: *
22
Content-Signal: ai-train=no, search=yes, ai-input=yes
3-
Content-Usage: / train-ai=n, search=y
43
Allow: /
54
Allow: /api/search
65
Allow: /api/mcp
@@ -55,4 +54,3 @@ Allow: /
5554
Host: https://codingcat.dev
5655
Sitemap: https://codingcat.dev/sitemap.xml
5756
Sitemap: https://codingcat.dev/sitemap-index.xml
58-
Agentmap: https://codingcat.dev/.well-known/ai-catalog.json

‎apps/site/src/components/Header.astro‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const desktopLinks = navLinks.filter((link) => link?.sideOnly !== true);
4747
<circle cx="11" cy="11" r="8"></circle>
4848
<path d="m21 21-4.3-4.3"></path>
4949
</svg>
50-
<span class="hidden md:inline-flex items-center text-[10px] font-mono bg-muted px-1.5 py-0.5 rounded border border-border">⌘K</span>
50+
<span class="hidden md:inline-flex items-center text-[10px] font-mono bg-muted text-foreground px-1.5 py-0.5 rounded border border-border">⌘K</span>
5151
</button>
5252
<ThemeToggle />
5353
<button

‎apps/site/src/components/SocialMeta.astro‎

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ import { SITE_NAME } from "@/lib/site";
99
*/
1010
interface Props {
1111
title: string;
12+
ogTitle?: string | null;
1213
description?: string | null;
14+
ogDescription?: string | null;
1315
image?: { url: string; alt?: string; width?: number; height?: number } | null;
1416
type?: "website" | "article";
17+
twitterCard?: string | null;
1518
publishedAt?: string | null;
1619
modifiedAt?: string | null;
1720
authors?: Array<string | null | undefined>;
@@ -21,16 +24,27 @@ interface Props {
2124
2225
const {
2326
title,
27+
ogTitle,
2428
description,
29+
ogDescription,
2530
image,
2631
type = "website",
32+
twitterCard,
2733
publishedAt,
2834
modifiedAt,
2935
authors = [],
3036
canonical = Astro.url,
3137
noindex = false,
3238
} = Astro.props;
3339
40+
function cleanMetaText(value: string | null | undefined): string | undefined {
41+
const cleaned = stegaClean(value)?.trim();
42+
if (!cleaned || cleaned.toLowerCase() === "fix me") {
43+
return undefined;
44+
}
45+
return cleaned;
46+
}
47+
3448
// Per-request, not `Astro.site`: the origin differs between the dev and
3549
// production Workers but the build is shared.
3650
const site = Astro.locals.siteUrl;
@@ -39,9 +53,18 @@ const canonicalUrl = new URL(
3953
site,
4054
).href;
4155
42-
const cleanTitle = stegaClean(title) ?? SITE_NAME;
43-
const cleanDescription = stegaClean(description) ?? undefined;
56+
const cleanTitle = cleanMetaText(title) ?? SITE_NAME;
57+
const cleanOgTitle = cleanMetaText(ogTitle) ?? cleanTitle;
58+
const cleanDescription = cleanMetaText(description);
59+
const cleanOgDescription = cleanMetaText(ogDescription) ?? cleanDescription;
4460
const imageUrl = image?.url ? new URL(stegaClean(image.url), site).href : undefined;
61+
const imageAlt = cleanMetaText(image?.alt) ?? cleanOgTitle;
62+
const cardType =
63+
cleanMetaText(twitterCard) === "summary"
64+
? "summary"
65+
: imageUrl
66+
? "summary_large_image"
67+
: "summary";
4568
---
4669

4770
<title>{cleanTitle}</title>
@@ -50,26 +73,34 @@ const imageUrl = image?.url ? new URL(stegaClean(image.url), site).href : undefi
5073
{noindex && <meta name="robots" content="noindex, nofollow" />}
5174

5275
<meta property="og:site_name" content={SITE_NAME} />
76+
<meta property="og:locale" content="en_US" />
5377
<meta property="og:type" content={type} />
54-
<meta property="og:title" content={cleanTitle} />
55-
{cleanDescription && <meta property="og:description" content={cleanDescription} />}
78+
<meta property="og:title" content={cleanOgTitle} />
79+
{cleanOgDescription && <meta property="og:description" content={cleanOgDescription} />}
5680
<meta property="og:url" content={canonicalUrl} />
5781
{
5882
imageUrl && (
5983
<>
6084
<meta property="og:image" content={imageUrl} />
6185
{image?.width && <meta property="og:image:width" content={String(image.width)} />}
6286
{image?.height && <meta property="og:image:height" content={String(image.height)} />}
63-
{image?.alt && <meta property="og:image:alt" content={stegaClean(image.alt)} />}
87+
{imageAlt && <meta property="og:image:alt" content={imageAlt} />}
6488
</>
6589
)
6690
}
6791

68-
<meta name="twitter:card" content={imageUrl ? "summary_large_image" : "summary"} />
92+
<meta name="twitter:card" content={cardType} />
6993
<meta name="twitter:site" content="@CodingCatDev" />
70-
<meta name="twitter:title" content={cleanTitle} />
71-
{cleanDescription && <meta name="twitter:description" content={cleanDescription} />}
72-
{imageUrl && <meta name="twitter:image" content={imageUrl} />}
94+
<meta name="twitter:title" content={cleanOgTitle} />
95+
{cleanOgDescription && <meta name="twitter:description" content={cleanOgDescription} />}
96+
{
97+
imageUrl && (
98+
<>
99+
<meta name="twitter:image" content={imageUrl} />
100+
{imageAlt && <meta name="twitter:image:alt" content={imageAlt} />}
101+
</>
102+
)
103+
}
73104

74105
{
75106
type === "article" && (

‎apps/site/src/layouts/BaseLayout.astro‎

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@ import {
2020
2121
interface Props {
2222
title: string;
23+
ogTitle?: string | null;
2324
description?: string | null;
25+
ogDescription?: string | null;
2426
image?: { url: string; alt?: string; width?: number; height?: number } | null;
2527
type?: "website" | "article";
28+
twitterCard?: string | null;
2629
publishedAt?: string | null;
2730
modifiedAt?: string | null;
2831
authors?: Array<string | null | undefined>;
2932
canonical?: string | URL;
3033
noindex?: boolean;
3134
/**
32-
* Used to generate an OG card when `image` is absent. Documents without a
33-
* cover image previously shipped no og:image at all.
35+
* Used to generate an OG card when `image` is absent. When omitted, a
36+
* default branded OG card is generated automatically from `title` and
37+
* `description` so every route ships a 1200×630 social preview image.
3438
*/
3539
ogFallback?: OgFallback;
3640
/** Extra JSON-LD nodes merged into the site-wide @graph. */
@@ -41,9 +45,12 @@ interface Props {
4145
4246
const {
4347
title,
48+
ogTitle,
4449
description,
50+
ogDescription,
4551
image,
4652
type,
53+
twitterCard,
4754
publishedAt,
4855
modifiedAt,
4956
authors,
@@ -58,7 +65,14 @@ const origin = Astro.locals.siteUrl.origin;
5865
const preview = Astro.locals.sanity.preview.enabled;
5966
6067
const socialImage =
61-
image ?? (ogFallback ? fallbackOgImage(origin, ogFallback) : undefined);
68+
image ??
69+
fallbackOgImage(
70+
origin,
71+
ogFallback ?? {
72+
title: ogTitle ?? title,
73+
subtitle: ogDescription ?? description,
74+
},
75+
);
6276
6377
const graph = buildGraph([
6478
organizationSchema(origin, absoluteUrl("/icon.svg", origin)),
@@ -78,9 +92,12 @@ const graph = buildGraph([
7892
<Font cssVariable="--font-nunito" />
7993
<SocialMeta
8094
title={title}
95+
ogTitle={ogTitle}
8196
description={description}
97+
ogDescription={ogDescription}
8298
image={socialImage}
8399
type={type}
100+
twitterCard={twitterCard}
84101
publishedAt={publishedAt}
85102
modifiedAt={modifiedAt}
86103
authors={authors}

‎apps/site/src/lib/og-mascots.ts‎

Lines changed: 10 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)