diff --git a/apps/web/src/lib/blob-proxy.ts b/apps/web/src/lib/blob-proxy.ts new file mode 100644 index 0000000..ac4ac0c --- /dev/null +++ b/apps/web/src/lib/blob-proxy.ts @@ -0,0 +1,26 @@ +/** + * Rewrites a PDS getBlob URL to the site's own /blob route, which proxies the + * blob and applies image transformations where the platform provides them. + */ + +const WIDTHS = [256, 1600] as const; +export type BlobWidth = (typeof WIDTHS)[number]; + +export function isBlobWidth(value: number): value is BlobWidth { + return (WIDTHS as readonly number[]).includes(value); +} + +/** Unrecognized URLs pass through untouched. */ +export function blobProxyPath(blobUrl: string, width: BlobWidth): string { + let url: URL; + try { + url = new URL(blobUrl); + } catch { + return blobUrl; + } + if (url.pathname !== '/xrpc/com.atproto.sync.getBlob') return blobUrl; + const did = url.searchParams.get('did'); + const cid = url.searchParams.get('cid'); + if (!did || !cid) return blobUrl; + return `/blob/${encodeURIComponent(did)}/${encodeURIComponent(cid)}?w=${width}`; +} diff --git a/apps/web/src/lib/components/theme/SiteLayout.svelte b/apps/web/src/lib/components/theme/SiteLayout.svelte index cfa6e43..3eab034 100644 --- a/apps/web/src/lib/components/theme/SiteLayout.svelte +++ b/apps/web/src/lib/components/theme/SiteLayout.svelte @@ -65,9 +65,9 @@ @@ -97,6 +97,7 @@ --accent: #9c3218; --accent-ink: #fdfbf6; --rule: #e0d8c8; + --airmail-blue: #1c3f6e; --font-serif: 'Iowan Old Style', 'Hoefler Text', 'Palatino Linotype', Palatino, 'Book Antiqua', Georgia, serif; @@ -134,6 +135,7 @@ --accent: #d4714f; --accent-ink: #101520; --rule: #242c3a; + --airmail-blue: #3a6ea8; } } @@ -144,7 +146,7 @@ -45deg, var(--accent) 0 10px, var(--paper) 10px 20px, - #1c3f6e 20px 30px, + var(--airmail-blue) 20px 30px, var(--paper) 30px 40px ); } @@ -183,7 +185,9 @@ nav a { color: var(--muted); text-decoration: none; - padding-bottom: 2px; + /* Small type, big target: pad the hit area without moving the layout. */ + padding: 0.5rem 0.25rem 2px; + margin: -0.5rem -0.25rem 0; border-bottom: 1px solid transparent; transition: color 160ms ease, border-color 160ms ease; } @@ -227,6 +231,9 @@ footer a { color: inherit; + display: inline-block; + padding: 0.45rem 0.25rem; + margin: -0.45rem -0.25rem; } .handle { diff --git a/apps/web/src/lib/components/theme/SiteSections.svelte b/apps/web/src/lib/components/theme/SiteSections.svelte index 09801ab..b5d84f2 100644 --- a/apps/web/src/lib/components/theme/SiteSections.svelte +++ b/apps/web/src/lib/components/theme/SiteSections.svelte @@ -1,7 +1,9 @@