Skip to content

Commit 076bf33

Browse files
authored
feat(landing): ship purpose-built OG card site-wide (#4292)
* feat(landing): ship purpose-built OG card site-wide Replace the hero-screenshot Open Graph image with a dedicated 1200×630 brand card (light paper, lime highlight, "the official open-source Claude Design alternative" headline, with Local-first / Apache-2.0 / BYO coding agent tags). The previous og:image reused hero.png, which crops awkwardly to 1.91:1 and carries no positioning. - image-assets.ts: ogDefaultImage now points at the raw R2 object (landing/assets/og-card.png) instead of the cdn-cgi/image resizer, so social crawlers always get a real PNG at exactly 1200×630 rather than a format=auto WebP. Export OG_IMAGE_WIDTH/HEIGHT. - index.astro: homepage og:image + twitter:image use the card; add og:image:width/height/type meta. - og.astro: rewrite the /og/ screenshotable source to match the shipped card (self-contained, inline brand mark), with regenerate steps. The static PNG is uploaded to R2 separately; this commit only wires the references. * fix(landing): use OG card as sub-page-layout default share image sub-page-layout.astro powers most non-homepage landing routes (/skills, /systems, /templates, /solutions, /agents, …). Its og:image fallback still resolved to the old hero screenshot (heroImage), so those pages kept unfurling the product shot after the site-wide card landed. Point the default at ogDefaultImage so the new card is genuinely site-wide; per-page ogImage overrides are untouched. --------- Co-authored-by: Joey <276262049+xne998808-ai@users.noreply.github.com>
1 parent 4763021 commit 076bf33

4 files changed

Lines changed: 197 additions & 336 deletions

File tree

apps/landing-page/app/_components/sub-page-layout.astro

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import LocaleSwitcherScript from './locale-switcher-script.astro';
2828
import PreciseLazyload from './precise-lazyload.astro';
2929
import TemplateCardAutoplay from './template-card-autoplay.astro';
3030
import SiteFooter from './site-footer.astro';
31-
import { heroImage } from '../image-assets';
31+
import { ogDefaultImage } from '../image-assets';
3232
import {
3333
LANDING_LOCALES,
3434
alternateLinksForPath,
@@ -80,9 +80,10 @@ const alternateLinks = localeCanonicalOnly
8080
const xDefaultHref = new URL(altEntries[0]!.hrefPath, Astro.site).toString();
8181
// Absolute URL for the social share card: og:image / twitter:image are read
8282
// by external crawlers outside the page-origin context, so a same-origin path
83-
// like `/hero-home.png?v=2` is unreliable for rich previews. `new URL()`
84-
// leaves an already-absolute `ogImage` untouched.
85-
const og = new URL(ogImage ?? heroImage, Astro.site).toString();
83+
// is unreliable for rich previews. The default is the site-wide OG card
84+
// (`ogDefaultImage`, already an absolute R2 URL); `new URL()` leaves an
85+
// already-absolute `ogImage` override untouched.
86+
const og = new URL(ogImage ?? ogDefaultImage, Astro.site).toString();
8687
const counts = await getCatalogCounts();
8788
const github = await getGithubRepoMeta();
8889
const headerHtml = renderToStaticMarkup(

apps/landing-page/app/image-assets.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,20 @@ export const heroProductSrcset = [
6767
].join(', ');
6868

6969
/**
70-
* Default Open Graph card image. Used by every page that doesn't supply
71-
* its own hero (most blog posts in the v1 layout). 1200 wide is what most
72-
* social platforms render at; aspect ratio is whatever hero.png ships with
73-
* — we omit explicit og:image:width/height so platforms can resolve it.
70+
* Default Open Graph card image — the purpose-built 1200×630 brand plate
71+
* (light paper, lime highlight, "official open-source Claude Design
72+
* alternative" headline). Used site-wide by every page that doesn't
73+
* supply its own card. Referenced as the raw R2 object (not via the
74+
* `cdn-cgi/image` resizer) so social crawlers always receive a real PNG
75+
* at exactly 1200×630 — `format=auto` would hand some of them WebP.
76+
*
77+
* Source of truth for the artwork is the `/og/` route (`pages/og.astro`):
78+
* render it at viewport 1200×630, screenshot, then upload the PNG to
79+
* R2 at `landing/assets/og-card.png`.
7480
*/
75-
export const ogDefaultImage = imageAsset('hero.png', { width: 1200, quality: 86 });
81+
export const ogDefaultImage = r2Asset('og-card.png');
82+
export const OG_IMAGE_WIDTH = 1200;
83+
export const OG_IMAGE_HEIGHT = 630;
7684

7785
/**
7886
* 1×1 transparent SVG used as the initial `src` for precise-lazyloaded

apps/landing-page/app/pages/index.astro

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import PreciseLazyload from '../_components/precise-lazyload.astro';
1414
import {
1515
heroBgImage,
1616
heroBgSrcset,
17-
heroImage,
17+
ogDefaultImage,
18+
OG_IMAGE_HEIGHT,
19+
OG_IMAGE_WIDTH,
1820
} from '../image-assets';
1921
import {
2022
LANDING_LOCALES,
@@ -184,7 +186,10 @@ const matterRuntime = readFileSync(
184186
<meta property="og:title" content={title} />
185187
<meta property="og:description" content={description} />
186188
<meta property="og:url" content={canonical} />
187-
<meta property="og:image" content={new URL(heroImage, Astro.site).toString()} />
189+
<meta property="og:image" content={ogDefaultImage} />
190+
<meta property="og:image:width" content={String(OG_IMAGE_WIDTH)} />
191+
<meta property="og:image:height" content={String(OG_IMAGE_HEIGHT)} />
192+
<meta property="og:image:type" content="image/png" />
188193
<meta property="og:locale" content={localeDef.ogLocale} />
189194
{LANDING_LOCALES.filter((entry) => entry.code !== locale).map((entry) => (
190195
<meta property="og:locale:alternate" content={entry.ogLocale} />
@@ -193,7 +198,7 @@ const matterRuntime = readFileSync(
193198
<meta name="twitter:card" content="summary_large_image" />
194199
<meta name="twitter:title" content={title} />
195200
<meta name="twitter:description" content={description} />
196-
<meta name="twitter:image" content={new URL(heroImage, Astro.site).toString()} />
201+
<meta name="twitter:image" content={ogDefaultImage} />
197202

198203
{/*
199204
* Single @graph JSON-LD block — WebSite + Organization +

0 commit comments

Comments
 (0)