From 0051355efaa5b4fea67baa1076ff4754fad92950 Mon Sep 17 00:00:00 2001 From: orta Date: Sat, 31 Jan 2026 22:44:52 +0000 Subject: [PATCH 1/2] Sets up a much more nuanced package opengraph image --- app/components/OgImage/Package.vue | 333 ++++++++++++++++++++++++----- app/pages/[...package].vue | 62 +++++- 2 files changed, 342 insertions(+), 53 deletions(-) diff --git a/app/components/OgImage/Package.vue b/app/components/OgImage/Package.vue index f16a22ea6..c11d89103 100644 --- a/app/components/OgImage/Package.vue +++ b/app/components/OgImage/Package.vue @@ -1,39 +1,87 @@ diff --git a/app/pages/[...package].vue b/app/pages/[...package].vue index d49492afb..a117c5c50 100644 --- a/app/pages/[...package].vue +++ b/app/pages/[...package].vue @@ -4,6 +4,12 @@ import type { JsrPackageInfo } from '#shared/types/jsr' import { assertValidPackageName } from '#shared/utils/npm' import { joinURL } from 'ufo' import { areUrlsEquivalent } from '#shared/utils/url' +import { parseRepoUrl } from '#shared/utils/git-providers' +import { + detectModuleFormat, + hasBuiltInTypes, + type ExtendedPackageJson, +} from '#shared/utils/package-analysis' definePageMeta({ name: 'package', @@ -258,6 +264,50 @@ function formatBytes(bytes: number): string { return `${(bytes / (1024 * 1024)).toFixed(1)} MB` } +// OG Image helpers +function formatOgDate(isoDate?: string): string { + if (!isoDate) return '' + const date = new Date(isoDate) + return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) +} + +function formatCompactNumber(num: number): string { + if (num >= 1_000_000_000) { + return `${(num / 1_000_000_000).toFixed(num >= 10_000_000_000 ? 0 : 1).replace(/\.0$/, '')}B` + } + if (num >= 1_000_000) { + return `${(num / 1_000_000).toFixed(num >= 10_000_000 ? 0 : 1).replace(/\.0$/, '')}M` + } + if (num >= 1_000) { + return `${(num / 1_000).toFixed(num >= 10_000 ? 0 : 1).replace(/\.0$/, '')}K` + } + return num.toString() +} + +// Computed values for OG image +const ogRepoRef = computed(() => { + const repoUrl = displayVersion.value?.repository?.url + if (!repoUrl) return null + return parseRepoUrl(normalizeGitUrl(repoUrl)) +}) + +const ogDirectDepsCount = computed(() => { + const deps = displayVersion.value?.dependencies + return deps ? Object.keys(deps).length : 0 +}) + +const ogModuleFormat = computed(() => { + const ver = displayVersion.value as ExtendedPackageJson | null + if (!ver) return 'unknown' + return detectModuleFormat(ver) +}) + +const ogHasTypes = computed(() => { + const ver = displayVersion.value as ExtendedPackageJson | null + if (!ver) return false + return hasBuiltInTypes(ver) +}) + function getDependencyCount(version: PackumentVersion | null): number { if (!version?.dependencies) return 0 return Object.keys(version.dependencies).length @@ -362,9 +412,19 @@ onKeyStroke('c', () => { defineOgImageComponent('Package', { name: () => pkg.value?.name ?? 'Package', version: () => displayVersion.value?.version ?? '', - downloads: () => (downloads.value ? $n(downloads.value.downloads) : ''), + downloads: () => (downloads.value ? formatCompactNumber(downloads.value.downloads) : ''), license: () => pkg.value?.license ?? '', primaryColor: '#60a5fa', + description: () => pkg.value?.description ?? '', + repoOwner: () => ogRepoRef.value?.owner ?? '', + repoName: () => ogRepoRef.value?.repo ?? '', + stars: () => stars.value ?? 0, + forks: () => forks.value ?? 0, + directDepsCount: () => ogDirectDepsCount.value, + updatedAt: () => formatOgDate(pkg.value?.time?.modified), + hasTypes: () => ogHasTypes.value, + hasESM: () => ogModuleFormat.value === 'esm' || ogModuleFormat.value === 'dual', + hasCJS: () => ogModuleFormat.value === 'cjs' || ogModuleFormat.value === 'dual', }) // We're using only @click because it catches touch events and enter hits From 5edff1c0eabdfbbf206ff769608d06f1d0e67789 Mon Sep 17 00:00:00 2001 From: orta Date: Sat, 31 Jan 2026 22:48:59 +0000 Subject: [PATCH 2/2] Adds geist mono font references for the opengraph renderer --- app/components/OgImage/Package.vue | 33 ++++++++++++++++++++++++----- app/pages/[...package].vue | 13 ------------ nuxt.config.ts | 9 ++++++++ public/fonts/Geist-Bold.ttf | Bin 0 -> 71804 bytes public/fonts/Geist-Medium.ttf | Bin 0 -> 72132 bytes public/fonts/Geist-Regular.ttf | Bin 0 -> 71112 bytes public/fonts/Geist-SemiBold.ttf | Bin 0 -> 72064 bytes public/fonts/GeistMono-Bold.ttf | Bin 0 -> 69804 bytes public/fonts/GeistMono-Medium.ttf | Bin 0 -> 70008 bytes public/fonts/GeistMono-Regular.ttf | Bin 0 -> 69936 bytes 10 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 public/fonts/Geist-Bold.ttf create mode 100644 public/fonts/Geist-Medium.ttf create mode 100644 public/fonts/Geist-Regular.ttf create mode 100644 public/fonts/Geist-SemiBold.ttf create mode 100644 public/fonts/GeistMono-Bold.ttf create mode 100644 public/fonts/GeistMono-Medium.ttf create mode 100644 public/fonts/GeistMono-Regular.ttf diff --git a/app/components/OgImage/Package.vue b/app/components/OgImage/Package.vue index c11d89103..9d7c19f86 100644 --- a/app/components/OgImage/Package.vue +++ b/app/components/OgImage/Package.vue @@ -1,4 +1,6 @@