From f029b5a51638f8d7992dfeb46d45178878ffa409 Mon Sep 17 00:00:00 2001 From: SkateSpots Date: Wed, 28 Oct 2026 09:42:44 +0700 Subject: [PATCH] feat(newsletter): weekly generated drafts, covers, and admin preview - Add a browser-safe editorial generator with rotating satire and shipped highlights. - Generate a fresh 1200x630 cover from the Drop #006 foundation and upload it to Blossom. - Publish weekly drafts as NIP-78; add the admin Load draft/Preview composer flow and banner. - Add the Monday user timer (draft by default) and a manual newsletter:weekly script. - Remove static/live issue duplicates; translate the new admin strings to all 24 locales. --- AGENTS.md | 17 ++ package.json | 3 +- scripts/install-newsletter-timer.sh | 9 + scripts/newsletter-cover.ts | 134 +++++++++ scripts/newsletter-weekly.sh | 10 + scripts/newsletter-weekly.ts | 274 ++++++++++++++++++ scripts/systemd/skatespots-newsletter.service | 12 + scripts/systemd/skatespots-newsletter.timer | 10 + src/components/NewsletterComposer.tsx | 78 ++++- src/components/NewsletterIssueView.tsx | 5 + src/hooks/useNewsletterDraft.ts | 63 ++++ src/i18n/ca/batch1.ts | 8 +- src/i18n/cs/drift.ts | 6 + src/i18n/de/drift.ts | 6 + src/i18n/el/drift.ts | 6 + src/i18n/eu/batch1.ts | 8 +- src/i18n/fr/drift.ts | 6 + src/i18n/gl/batch1.ts | 8 +- src/i18n/hi/batch1.ts | 8 +- src/i18n/id/drift.ts | 6 + src/i18n/it/drift.ts | 6 + src/i18n/ja/drift.ts | 6 + src/i18n/ko/drift.ts | 6 + src/i18n/legacy/index.ts | 3 + src/i18n/legacy/newsletterDraftUi.ts | 16 + src/i18n/nl/drift.ts | 6 + src/i18n/pl/drift.ts | 6 + src/i18n/pt/drift.ts | 6 + src/i18n/ro/drift.ts | 6 + src/i18n/ru/drift.ts | 6 + src/i18n/sv/drift.ts | 6 + src/i18n/th/drift.ts | 6 + src/i18n/tr/drift.ts | 6 + src/i18n/uk/drift.ts | 6 + src/i18n/vi/drift.ts | 6 + src/i18n/zh-CN/drift.ts | 6 + src/i18n/zh-TW/drift.ts | 6 + src/lib/newsletterContent.ts | 204 +++++++++++++ src/pages/NewsletterPage.tsx | 21 +- 39 files changed, 999 insertions(+), 12 deletions(-) create mode 100755 scripts/install-newsletter-timer.sh create mode 100644 scripts/newsletter-cover.ts create mode 100755 scripts/newsletter-weekly.sh create mode 100644 scripts/newsletter-weekly.ts create mode 100644 scripts/systemd/skatespots-newsletter.service create mode 100644 scripts/systemd/skatespots-newsletter.timer create mode 100644 src/hooks/useNewsletterDraft.ts create mode 100644 src/i18n/legacy/newsletterDraftUi.ts create mode 100644 src/lib/newsletterContent.ts diff --git a/AGENTS.md b/AGENTS.md index c1cc0b0..b8f9f45 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -870,6 +870,23 @@ session with **no other memory of this project**. So: hook do this and fail loudly if every relay rejects. `useSpotChat` is the reference pattern. (Before the fix, an admin whose own NIP-65 lacked `goskatespots` would publish issues nobody could find.) + - **Weekly newsletter automation (2026-10-28).** `scripts/newsletter-weekly.ts` + generates the next issue (published max + 1), builds all fields, makes a + fresh 1200×630 cover from the Drop #006 foundation, uploads it to Blossom, + and publishes **only a draft** as NIP-78 `kind 30078`, + `d=skatespots:newsletter:draft`, `t=skatespotsnewsdraft`. The admin + `/newsletter` page shows a **Weekly draft ready** banner; the composer loads + it (`useNewsletterDraft`) and has a safe Markdown **Preview**. Set + `NEWSLETTER_AUTOPUBLISH=1` in the service to also publish the NIP-23 issue + + kind-1 teaser. The timer (`scripts/systemd/skatespots-newsletter.timer`, + Monday 08:00, install with `scripts/install-newsletter-timer.sh`) defaults to + `NEWSLETTER_AUTOPUBLISH=0` — review the voice/cover before enabling. The + editorial bank lives in `src/lib/newsletterContent.ts` (rotating South Park + jokes; 4 shipped highlights; current tech wires); issue 7 uses the curated + highlights, later issues parse the top of `release-notes.txt`. The static + archive now hides an issue number that is also live, so backfilled issues + don't duplicate. The draft event is public (it contains no private data); + never put `SIGN_WITH` in it or in tracked files. - **Nav parity (fixed 2026-09-27):** the desktop header is `max-w-[1700px]` (wider than the page `container`'s 1400px) and nav items are `px-3` + `whitespace-nowrap`; the nav keeps `min-w-0 overflow-x-auto scrollbar-hide`, so diff --git a/package.json b/package.json index ad5e6ba..f28f5ef 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "android:open": "npx cap open android", "android:version": "node scripts/sync-android-version.mjs", "android:build": "npm run android:build:apk && npx cap sync android && node scripts/sync-android-version.mjs && node scripts/inject-amber-queries.mjs && node scripts/inject-main-activity.mjs && node scripts/inject-network-security.mjs && node scripts/inject-signing-config.mjs && cd android && ./gradlew assembleRelease", - "android:build:apk": "CAPACITOR_BUILD=1 vite build && sed -i 's|||g' dist/index.html && sed -i 's|