diff --git a/package.json b/package.json index 3d07202..700e001 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "skate-spots", "private": true, - "version": "1.2.40", + "version": "1.2.41", "type": "module", "homepage": "https://skate-spots.com", "scripts": { diff --git a/src/components/NewsletterComposer.tsx b/src/components/NewsletterComposer.tsx index 662672b..0d88996 100644 --- a/src/components/NewsletterComposer.tsx +++ b/src/components/NewsletterComposer.tsx @@ -48,12 +48,24 @@ export function NewsletterComposer() { if (!isAdminPubkey(user?.pubkey)) return null; - const effectiveSlug = slug.trim() || slugify(title); - const canPublish = title.trim().length >= 2 && body.trim().length >= 10 && !!effectiveSlug; + // A manual slug is used verbatim (lets an admin intentionally EDIT/replace a + // specific existing issue). When left blank we must NOT use the bare + // title-slug: kind 30023 is addressable, so two issues that slugify the same + // (e.g. a recurring "Weekly Roundup", or "Update!" vs "Update?") would share a + // `d` and the newer one would silently OVERWRITE the older. So an auto-slug + // gets a short date suffix to make each published issue its own coordinate. + const manualSlug = slug.trim(); + const canPublish = title.trim().length >= 2 && body.trim().length >= 10 && (!!manualSlug || title.trim().length >= 2); const handlePublish = async () => { if (!canPublish) return; const now = Math.floor(Date.now() / 1000); + // YYYYMMDD suffix (UTC) keeps auto-slugs readable and unique per day; a + // second same-title issue on the same day also gets a time component. + const d = new Date(now * 1000); + const dateSuffix = `${d.getUTCFullYear()}${String(d.getUTCMonth() + 1).padStart(2, '0')}${String(d.getUTCDate()).padStart(2, '0')}`; + const autoSlug = `${slugify(title) || 'issue'}-${dateSuffix}-${now.toString(36).slice(-4)}`; + const effectiveSlug = manualSlug || autoSlug; try { await publish({ kind: NEWSLETTER_KIND,