/** * Formats an ISO date (`YYYY-MM-DD`) for display. * Forced to UTC so a post dated 2026-05-09 never renders as May 8 for * visitors west of Greenwich. */ export function formatDate(date: string): string { return new Date(date).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", timeZone: "UTC", }); } /** * Rough reading time in minutes, from raw MDX. * * Frontmatter is already stripped by `lib/devblog`, but markdown syntax is * not: fences, link targets and heading markers are dropped so a post is not * credited for characters nobody reads. 200 wpm, floored at one minute. */ export function readingTime(content: string): number { const words = content .replace(/```[\s\S]*?```/g, "") .replace(/\[([^\]]*)\]\([^)]*\)/g, "$1") .replace(/[#>*_`~-]/g, " ") .split(/\s+/) .filter(Boolean).length; return Math.max(1, Math.round(words / 200)); }