Commit Graph

11 Commits

Author SHA1 Message Date
nmemmert f5c4557e9f Add Tier 2 remaining features: publishing pipeline, broadcasts, audit log, drip trigger, today banner; v1.1.25
- CalendarPage: productionStatus field on episodes (idea→recorded→edited→scheduled→published), color dot on chips, dropdown in edit popover; "publishing today" banner with draft announcement button
- EmailPage: Broadcasts drawer (plain-text → Resend Broadcasts API); Audit Log drawer showing activity history; em-status-msg--ok style
- ContactsPage: ▶ Drip button in edit mode syncs contact to Resend audience and triggers drip automation
- server: appendAuditEntry() logged on reply-sent, email-sent, submission-deleted, contacts-merged, contacts-imported, broadcast-sent, drip-triggered; GET /api/admin-audit-log; POST /api/admin-broadcasts/send; POST /api/admin-contacts/trigger-drip; AUDIT_LOG_FILE persisted to data/audit-log.json

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-29 07:52:07 -04:00
nmemmert f0635753f1 Add general calendar events (recording, social, task, general); nav links; v1.1.16
- Four event types on the calendar: General, Recording, Social, Task — each color-coded
- + Event button opens form with type picker, title, date, notes, reminder
- Task events have a Mark Complete toggle; completed events show strikethrough
- Edit/delete popover for each event
- Email reminders work for calendar events same as episodes
- Added Email/Calendar nav links to /contacts header
- Added Email link to /calendar header (already had Admin)
- /email already links to Contacts and Calendar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 11:26:48 -04:00
nmemmert ce235ba9ef Add /contacts and /calendar pages; email signature settings; v1.1.12
- /contacts: standalone page with hybrid contact list (submissions + manual entry), inline edit, search, archive
- /calendar: monthly release scheduling calendar reading/writing podcast checklist episode dates
- /email settings: editable signature panel; signature persisted server-side and injected into outgoing emails
- Move contacts out of /admin panel (now links to /contacts route)
- Partial PATCH for contact submissions (name, notes, archived independently)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-28 10:12:52 -04:00
nmemmert 172e4a9358 Add version numbering (v1.0.0)
- package.json: bump to 1.0.0
- server/config.js: export APP_VERSION (from package.json) and GIT_COMMIT
  (from COMMIT_SHA env var set by CI, or git rev-parse --short HEAD fallback)
- GET /api/version: new public endpoint returning { version, commit }
- GET /api/admin-auth/status: includes version and commit in response
- AdminPage sidebar: displays version string (e.g. "v1.0.0 (1d43875)")
  below the Log Out button, styled as muted metadata text

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-16 07:55:52 -04:00
nmemmert f4fd177421 Add full /data backup export/import for server migration
- New admin endpoints: GET /api/admin-backup/export streams the entire
  data directory as tar.gz (after flushing queued writes); POST
  /api/admin-backup/import validates the archive, snapshots current
  data, replaces the folder, and reloads all in-memory state.
- Admin UI: "Full Data Backup" section with download and restore-from-
  file controls in the Analytics panel.
- Fix admin TOTP secret path to honor SITEFORGE_DATA_DIR (moved base
  path resolution to server/paths.js to avoid a circular import), so
  2FA for admin and study users survives backup/restore.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 12:08:23 -04:00
nmemmert 17c9cbbc8b Fix inbound-email data loss, MIME truncation, and header injection
- server/data.js: preserve source/htmlBody/inboundTo/messageId across
  server restarts (sanitizeLoadedContactSubmissions was silently
  dropping them on reload from disk)
- cloudflare/email-worker.js: rewrite MIME parsing to split on the
  actual boundary marker instead of any literal "--", unfold
  multi-line headers, and correctly recombine multi-byte UTF-8 in
  quoted-printable decoding
- server/routes/inbound-email.js: validate Message-ID against RFC 5322
  grammar before storing/using it, and compare the webhook secret with
  timingSafeEqual to match the rest of the codebase's auth checks
- server/routes/contact.js: re-validate messageId at the point it's
  injected into outgoing In-Reply-To/References headers; move the
  allowed reply-from addresses into a shared config constant
- src/AdminPage.tsx: 30s inbox poll now syncs field updates (e.g.
  archived) on already-loaded submissions instead of only appending
  new ones; consolidate the duplicated from-address list
- .claude/launch.json: add a vite dev server preview config used to
  verify these changes

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 08:21:50 -04:00
nmemmert 31426fccba Add comprehensive visitor engagement tracking and scroll-to-top on navigation
Tracks scroll depth (25/50/75/90%), time on page, UTM parameters, outbound
link clicks, search queries, audio pause/completion/listen time, and 404s.
Logged-in study users are now tied to their visitor record and surfaced in
the admin recent visits table. Scroll position resets on every route change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 14:06:21 -04:00
nmemmert 8450d81e7f Add per-episode play tracking with bar chart in admin analytics
- POST /api/analytics/play records a play event (title + date) on first
  play per player mount, skipping admin sessions
- Plays persisted to data/episode-plays.json with total + byDay buckets
- Admin stats response includes episodePlays sorted by total plays
- AnalyticsPanel shows horizontal bar chart + summary cards for all
  episodes dynamically — new episodes appear automatically as played

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 13:39:35 -04:00
nmemmert 48c2f81d00 Add QR code tracker to admin panel
Each QR code gets a /qr/<slug> redirect that logs scans (IP, user agent,
timestamp) to disk. The admin QR Codes view lets you add, edit, enable/disable,
and delete codes, with per-code scan history inline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-16 09:33:35 -04:00
nmemmert c4645e3475 Add cross-site improvements across three phases
Phase 1 — Quick wins:
- Image lazy-loading on series/resource cards
- Newsletter signup added to Episodes page (before highlights)
- Per-route meta tags via usePageMeta hook (title, og:title, og:description)
- Breadcrumbs on study index, section, and notes pages
- SVG completion checkmark badges on study section list
- Analytics time-range filter (7d / 30d / 90d) in admin panel

Phase 2 — Medium features:
- Related episodes on archived series detail pages
- Resource library two-tier filter (type + tag chips)
- Global search (Fuse.js) moved below sticky header as full-width bar
- Q&A anonymous upvoting with localStorage dedup + admin pin/unpin
- Study enrollment funnel tracking (firstVisitAt, firstCompletionAt) with funnel chart in analytics

Phase 3 — Larger features:
- Study section comments (auto-approve for enrolled users, admin moderation panel)
- Study completion certificate (canvas render, PNG download, shareable public URL)
- Episode script full-text search (mammoth docx extraction, server-side search, admin upload UI)
- Reflection questions renamed from Discussion Questions; quiz answers can be shared to section discussion
- Public certificate route at /certificate/:token with og meta tags
- Comment moderation panel added to admin under Manage > Study Comments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 09:10:29 -04:00
nmemmert 346ecb217c refractor server.js 2026-06-03 15:08:14 -04:00