home: drop Selected Works card + juice hero; per-pillar OG cards; sitemap freshness

Home: the big empty 'Selected Works' section-container card is gone in favour of a compact
centered heading, pulling the bento up ~300px so the work leads directly under the hero.
Hero juice (all LCP-safe + motion-safe): the H1 gets an animated gradient sheen (only the
gradient POSITION animates, so the largest paint is never delayed; verified opacity stays 1),
a soft breathing cyan aura sits behind it (aria-hidden), and the CTAs get a cyan glow + hover
lift.

Services: each pillar page (and the hub) now generates its own OG social card via the shared
gameOgImage helper with a 'Services' badge and the pillar accent, so sharing a pillar shows
a distinct card instead of the generic banner. Verified: distinct per-slug image URLs, valid
1200x630 PNGs.

Sitemap: bump lastModified 2026-06-01 -> 2026-07-12 (we've meaningfully changed the site).
This commit is contained in:
jwinterm
2026-07-12 14:15:46 -04:00
parent 1e5719a1da
commit 651be20100
5 changed files with 79 additions and 15 deletions
@@ -0,0 +1,31 @@
import { gameOgImage, OG_SIZE, OG_CONTENT_TYPE } from "@/lib/og";
import { pillars, pillarBySlug } from "@/lib/services";
export const alt = "Such Software services";
export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
// Prebuild one card per pillar (matches the page's dynamicParams=false).
export function generateStaticParams() {
return pillars.map((p) => ({ pillar: p.slug }));
}
// Hex accents for the OG card (the pages use Tailwind stems; ImageResponse needs literal colours).
const ogAccent: Record<string, string> = {
commerce: "#3b82f6", // blue
games: "#a855f7", // purple
crypto: "#22d3ee", // cyan
education: "#f59e0b", // amber
};
export default async function Image({ params }: { params: Promise<{ pillar: string }> }) {
const { pillar: slug } = await params;
const pillar = pillarBySlug(slug);
if (!pillar) return gameOgImage({ title: "Services", tagline: "Such Software", accent: "#34d399", badge: "Services" });
return gameOgImage({
title: pillar.title,
tagline: pillar.card,
accent: ogAccent[pillar.slug] ?? "#34d399",
badge: "Services",
});
}
@@ -0,0 +1,14 @@
import { gameOgImage, OG_SIZE, OG_CONTENT_TYPE } from "@/lib/og";
export const alt = "Such Software — four things, done well";
export const size = OG_SIZE;
export const contentType = OG_CONTENT_TYPE;
export default function Image() {
return gameOgImage({
title: "Four things, done well",
tagline: "Commerce & web, games & apps, crypto & payments, and PhD-led science education.",
accent: "#34d399",
badge: "Services",
});
}