- Focus effect now only fires when compose/reply first opens, not on every
keystroke — typing in the To field no longer jumps focus to the body
- 👥 button next to To field opens a searchable contact picker dropdown;
selecting a contact fills in email and name instantly
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- Per-episode reminder select (1d/2d/3d/1wk/2wk before publish date)
- Server checks hourly; fires Resend email to admin on reminder day
- reminderSentAt persisted so reminders don't re-fire; cleared if date or setting changes
- Bell indicator on calendar chips; sent confirmation in edit popover
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts the email inbox from /admin and builds it as a full-viewport
email client at /email with the same admin auth. Key improvements over
the old embedded panel:
- Full-height split-pane layout (sidebar list + detail pane)
- Subject line extracted and shown separately for inbound emails
- Inline reply composer inside the detail pane (no more page-jump)
- Compose-new button for outbound messages to arbitrary addresses
- Search/filter across name, email, subject, and body
- Unread dot indicators with localStorage tracking (marks read on open)
- Keyboard navigation: ↑/↓ or j/k to move, r to reply, e to archive, Esc to close
- Source badges (contact-form / inbound-email) on list items
- Sent history and reply templates accessible via footer drawers
- 30-second polling for new messages
- New POST /api/admin-email/compose server endpoint for outbound sends
- Dashboard card "Open Inbox" now links to /email
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- EpisodeAudioPlayer restored to original horizontal layout (unchanged
for individual episode detail pages chosen in /admin)
- LatestEpisodePlayer on /episodes page gets its own markup + CSS
(.latest-episode-player__*) with the centered layout A — large gold
play button, skip-back 15s / skip-forward 30s, full-width scrubber
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- EpisodeAudioPlayer full variant: centered title, large gold play button,
skip-back 15s / skip-forward 30s flanking controls, full-width scrubber
- Compact variant (study sections) unchanged
- Episode detail page fetches direct Anchor MP3 URL from /api/episodes by
title match; falls back to resolvedEmbedUrl while loading
- Plays stream from Anchor CDN so stats still count
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add qa-cards--compact class to container when active. Compact mode now
tightens padding, reduces font sizes, hides related questions, and
reduces card gaps — making the density difference obvious.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Testimonials: new Testimonial type, CMS field, admin UI under About,
and TestimonialsSection rendered on homepage and About page (hidden when empty)
- Q&A: "Submit a Question →" CTA at bottom of Q&A page linking to /contact
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These rules became orphaned after converting QuestionsPage to a full site
layout and removing the back-to-site nav link from QASection.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
Public:
- /finished page with ornament heading, intro text, book grid, and styled empty state
- /finished/:id episode playlist page filtered by RSS season number
- Episodes nav becomes click-toggle dropdown (Current Series / Finished Books)
- Finished Books link in footer
- Dropdown font fixed to match other nav links
Admin:
- End Current Series & Start New Book wizard on Current Series tab
- Finished Books management tab with add/edit/remove and image asset picker
Data:
- FinishedBook type + finishedBooks[] field on SiteContent
- RSS parser extracts itunes:season per episode
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New FinishedBook type in content.ts + finishedBooks[] field on SiteContent
- RSS parser now extracts itunes:season into each episode object
- /finished grid page and /finished/:id playlist page (filters episodes by season)
- Episodes nav link replaced with dropdown: Current Series / Finished Books
- Finished Books link added to footer
- Admin: "End Current Series & Start New Book" wizard on Current Series tab
- Admin: Finished Books management tab (add/edit/remove entries)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each visit is now a card showing name/IP, page path, location, device,
visit count, new/returning tag, and timestamp at a glance. Logged-in users
show their display name prominently. Click to expand still shows full page
history and raw details. Adds a purple "Logged in" tag for study users.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- Add /api/episode-audio route returning MP3 URLs from Anchor RSS feed
- Replace Spotify URL text inputs in admin with RSS episode dropdowns
- New EpisodeAudioPlayer component with podcast art, show name, progress
bar, and Spotify icon link — full and compact sizes
- Backward-compatible: legacy Spotify embed URLs still render as iframes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The .section-resources CSS overrides were breaking the Downloads page
resource link layout. Added .section-external-sites class to the
ExternalSitesSection and scoped all image/layout overrides to it.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the configured imageUrl as a full-width banner at the top of each
External Sites card, above the link name and description.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
- **Tag filter bar** appears above the grid whenever any download has tags assigned. Chips for "All" + each unique tag, centered under the heading.
- **Clicking a tag** filters the grid to only matching downloads. Clicking the active tag again (or "All") clears the filter.
- **Empty state** — if a tag has no results it shows a friendly message instead of a blank grid.
- The filter only shows when tags exist — so it's invisible today (your 3 current downloads have no tags) and appears automatically once you start tagging items in the admin.
To use it: go to Admin → Downloads → edit a download item → add tags like `Colossians`, `Worksheet`, `Devotional`. Those tags will show up as filter chips on the public page instantly after publishing.
---
**🐛 Bugs fixed**
- Study hub/lesson pages turned gold — CSS merge error with `.study-index-page` fixed
- Lesson announcements not saving — `announcement` field missing from `sanitizeColossiansStudySections` whitelist
- 2FA email method blocked with "not configured" — guard checked `totpSecret` instead of `twoFaMethod`
- `STUDY_REMINDERS_FILE` constant never defined — server would crash on first reminder write
- `sanitizeStudyUsers` stripped all 2FA fields — data lost on every restart
- `scheduleStudyReminders` missing from refactored modules
**✨ Features added**
- Commentary supports paragraph formatting (double newline = new paragraph)
- Lesson announcement banner — full-width gold stripe at top of lesson page
- "Take the Quiz" renamed to "Discussion Questions" throughout
- Students must complete checkpoint before unlocking next lesson (lesson list + Next Lesson button both gate on it)
- No checkpoint questions → simple Mark as Completed button as fallback
- Truth For Life syndication widget on homepage
- Newsletter welcome email updated to your new HTML template
**🔧 Maintenance**
- `server.js` refactored from 6,013 lines into 12 focused modules
- Fix "Invalid Date" on student account page (memberSince guard)
- Fix study community author showing full email instead of username
- Add newsletter sign-up section to homepage (between PRISM and Current Series)
- Add newsletter opt-in nudge to study enrollment flow
- Redesign episodes page: latest episode featured card + per-episode Spotify embed
- Add SEO description field to episodes page (visually hidden, admin-editable)
- Expand default sitemap paths to include /about, /contact, /episodes, /resources, /study, /study/titus, /study/colossians
- Add featured Q&A callout section to homepage
- Add Q&A callout to study hub footer
- Tag both untagged image assets in Asset Manager