- Atomic temp-file + rename for all JSON data writes (no truncated files on crash)
- /api/bible-passage: rate limit, range caps (60 verses), bounded cache
- Admin webhooks: https-only, block private/internal/Tailscale addresses (checked at registration and delivery), no redirects
- Resend webhook token compare is timing-safe
- DOMPurify on rendered study notes and broadcast preview
- CI runs lint + tests before build
- Permissions-Policy and HSTS (production) headers; JSON error handler for /api
- Tests for URL safety and atomic writes
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Second series gets its own guide (Resources page card, download page, admin fields)
- When a series ends (scheduled or manual) its guide moves onto its Finished Book, which shows a guide button; the main series' guide is cleared unless the launch supplies a new one
- Lane B launch schedule can supply the incoming series' guide
- Download lookup covers second-series and finished-book guides; guide URLs are sanitized on save and on use
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Scripts keyed "<season>-<episode>" (legacy ones migrate on first start; unseasoned ones keep their plain key)
- Season backfill handles episode numbers shared across seasons (title match fallback)
- Fix: "Backfill seasons from RSS" was swallowed by the upload route
- Global search labels script results with the title of the series playing now (both lanes), not just finished books
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Shared tab bar; chosen tab is remembered per page
- Current Series: Main Series / Second Series / Launch: Main / Launch: Second
- Resources, Footer & Global, SEO, Legal, Start Here, Custom Links: former "Jump to" scroll links are now tabs
- Dashboard: Overview / Recent Activity / Study Users
- Studies editor: Lessons / Study Settings
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Highlights get a Series field (Lane A / Lane B / General); legacy highlights count as Lane A
- Episodes page groups highlights under each series' title
- Ending a series (scheduled or manual) moves only that series' highlights onto its Finished Book page; other lane and General stay
- Archived highlights keep working: detail pages, sitemap, scripture index and search include them
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Study status 'complete' (manual or auto when all lessons released); stays enrollable and self-paced (no sequential lock, Resume button, Finished Studies hub section)
- Studies get lane (A/B) and expected start date; planned studies show "Starts <date>"; hub shows next lesson date instead of hardcoded pace
- Second concurrent series (homepage card, admin panel) with its own scheduled launch; transitions are per lane and flip the ending study to Complete and the incoming study to Active
- Finished books link to their study: "Study This Book" on playlist page, audio-only link from hub (playlist stays public, no account)
- Admin: bulk release scheduler (every N days), same-day collision warning, linked-study selects
- Weekly digest no longer dumps a finished study's backlog on late enrollees
- CI: build and tag the container as :beta on pushes to the beta branch
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Broadcast Email creates and sends a Resend Broadcast to the Resend segment (unsubscribe handling, reports, New Episode topic, scheduling, test send)
- Subscribers: import chosen Resend-only contacts into the app list
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Subscribers: compare in-app list with Resend audience/segment, with one-click fixes
- syncContactToResend no longer resets unsubscribed on existing contacts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Asset Manager: search/filter/sort, list+grid views, rename, move between R2 folders, tag chips, bulk actions, used-in counts; fix R2 delete lookup
- Inbox: readable wrapped rows with subject/preview, real read state, type filters, bulk actions, mojibake repair
- Broadcast: pick a Resend template to fill subject and body
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Web-hosted copies of episode newsletters, published from Resend broadcasts
tagged with the "New Episode" topic. Gives Facebook (and anyone else) a
proper link to share instead of raw HTML email, and makes issues findable
via site search and Google.
- Admin "Newsletter Archive" tab lists sent Resend broadcasts, flags ones
tagged "New Episode", and publishes them with one click (pulls the HTML
straight from Resend's API)
- Public /newsletter archive index and /newsletter/:slug issue pages,
server-rendered with per-issue Open Graph tags for social previews
- Unsubscribe merge-tag stripped from the web copy; archive + subscribe
links appended
- Issues added to sitemap.xml and the on-site search index
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds forgot/reset password, signup email verification, sign-out-of-all-devices,
note-usage and certificate display in account settings, and password-changed
security emails. Fixes study sessions being lost on server restart by
persisting them to disk, and fixes sanitizeStudyUsers silently dropping the
new pending-token fields on load. Also surfaces the lesson discussion board
in the main site nav, trims the sign-in page for returning users, and renames
colossiansStudy.tsx/colossiansStudyData.ts to studyPages.tsx/legacyColossiansData.ts
now that the study system covers more than Colossians.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tag scripts with a season number (with an RSS-feed backfill for
existing uploads), surface it in search results, and fix word-boundary
matching plus a title/script-match dedup bug in the search merge logic.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Upload dropdown lets you choose R2 folder (uploads/images/guides/finished)
or local server disk. Asset table shows location column for each file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
One scheduled date/time in the Current Series admin panel archives the active series to
Finished Books and atomically swaps in new content for the series card, Start Here steps,
and Companion Study Guide. Server checks every hour via setInterval; also runs on restart
so the transition fires even if the server was down at the scheduled moment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add downloadUrl field to FinishedBook type
- Admin: paste any external URL (Drive, Dropbox, etc.) per finished book
- Public series page: replace square hero image with circular CD disc artwork
(conic-gradient sheen, center hole, drop shadow, slight tilt)
- Stream Episodes + Download Album action buttons in the hero
- Grid cards show a gold download badge when a download URL is set
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove raw IP storage; store only SHA-256 hash prefix in visitor records
- Non-blocking geo lookup: recordVisitor now synchronous, geo resolved in background
- UTM capture race condition fixed via sessionStorage pre-consent capture
- Add consent + bot checks to play endpoint (was missing)
- Add rate limiter to pageview endpoint (60 req/min per IP)
- Add 'All time' range option alongside 7d/30d/90d with trendData aggregation
- AnalyticsPanel: tabbed layout (Traffic/Engagement/System), dynamic chart titles,
range buttons with active state, visitor log uses ipHash instead of raw IP,
trendData drives main chart with weekly bucketing for all-time view
- Re-add prop-types dependency (required by react-simple-maps bundler)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>