- Studies nav item is now a dropdown (same pattern as Episodes): hover to expand,
click the label to navigate directly to /study
- Dropdown contains: All Studies (/study) and Scripture Index (/scripture)
- Episodes dropdown follows the same split pattern: label navigates, caret toggles
- Dropdown menus open on CSS :hover (desktop) and stay toggle-able on mobile
- v1.2.1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin > Audience > Broadcast Email: compose and send one-off HTML emails
to all subscribers via Resend batch API; {{name}} personalization; confirm step
- Admin > Configure > Webhooks: CRUD UI for managing POST event webhooks;
backend GET/POST/DELETE /api/admin-webhooks routes wired to existing state.webhooks
- Sitemap: dynamically appends released study lesson URLs (/study/:slug/:id)
and episode highlight URLs (/episodes/:id) to /sitemap.xml
- Scripture Index: public /scripture page listing every released lesson grouped
by study with passage reference links; served by /api/public/scripture-index
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Episode Highlights and the Downloads Library section now use the same compact
list → click to edit pattern as Studies. Both sections show a scannable row
list (title, key meta, edit/delete buttons) and open a focused editor for a
single item. Testimonials and Finished Books remain as collapsible cards since
they have few fields and grow slowly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Studies section now uses a three-level navigation: study list → study detail
with compact sortable lesson rows → individual lesson editor. Eliminates the
40+ expanding AdminCollapsibleCard items for lessons, replacing them with a
compact table (drag handle, reference, title, live/draft status, edit/preview/
delete per row) and a focused lesson editor opened by clicking Edit. Prev/Next
navigation between lessons added. BsbFetchButton extracted as a standalone
component for the inline lesson editor.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace flat sidebar with accordion nav: parent items (Homepage, About,
Contact, Podcast Hub) expand to reveal focused sub-items
- Split big sections into granular sub-views so each form shows only 3-8
fields (Homepage: Hero/Share/PRISM/Where-to-Next, About: Show Copy/Bio/
Testimonials, Contact: Profile/Copy & Scripture, Podcast: Current Series/
Highlights/Finished Books/Scripts/RSS)
- New topbar: brand + breadcrumb (Homepage › Hero), clean gold Save Draft
button, ghost Preview/Publish buttons — no more jump-to select
- New sidebar: compact 196px width, filter input at top, small-caps group
labels, chevron-animated parent items, indented sub-items with active
highlight, Back-to-site/Log-out/version at the bottom
- Replace PodcastTab state with adminView sub-views (podcast:current-series
etc.) eliminating the secondary tab bar inside the panel
- Extend AdminView type with all new colon-separated sub-view values
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename all user-facing "Downloads" text to "Resources" (nav, page eyebrows, buttons, admin labels, page title, content defaults)
- Add usePageMeta to ContactPage, EpisodeDetailPage, DownloadDetailPage, StartHerePage for correct social share previews
- Wire contactEyebrow and aboutShowEyebrow fields to the UI (were editable in admin but never rendered)
- Wrap StartHerePage in full site chrome (header, search, footer); fix Step 2 link from /#qa to /questions
- Fix admin "View All Contacts" link (was 404); now navigates to Contact admin panel
- Remove broken "Previous Studies" jump nav entry (no matching anchor)
- Remove /studys typo route
- Make dashboard "Top Resource Downloads" stat dynamic instead of hardcoded to titus-study key
- Add Newsletter link (/subscribe) to footer legal nav
- Fix server.js startup log ("Portfolio app" → "Siteforge")
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Deleted ~24 unused API routes from contact.js (email inbox/CRM feature
never wired to frontend): reply, compose, draft, broadcast, webhooks,
audit-log, contact CRUD, merge, import, and health endpoints
- Removed dead imports from contact.js (config, data, email modules)
- Removed broken /email Link from admin dashboard Inbox card
- Cleaned up AdminView type: removed unreachable 'current-series' and
'episode-highlights' top-level values (only valid as podcast sub-tabs)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docker-compose.yml was still pointing to the old GHCR image
(ghcr.io/nmemmert/siteforge:latest) after CI was switched to push
to git.necloud.us/nate/siteforge:latest, so servers were pulling
a stale build that predated the download/header changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace hero study guide form with PageBanner + featured download card in library
- Add PageBanner component used consistently across all interior pages (Downloads, Episodes, About, Contact, Q&A, Finished Books)
- Remove duplicate headings/eyebrows that conflicted with banner titles on About, Contact, Q&A, Finished Books pages
- Compact download card sizing (padding, border-radius, image size)
- Add Books & Resources tabbed section with fallback to TruthForLife widget
- Fix server sanitizer to pass through 'resources' placement items without URL
- Add featured-badge and featured card styling for primary guide
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 'books' and 'recommended' to the placement whitelist in sanitizeCustomLinks
- Allow items with no url when placement is books/recommended (they use amazonUrl)
- Preserve linkUrl and linkLabel through sanitizeCustomBlocks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CustomBlock: add linkUrl/linkLabel fields for a styled button below the body
- Body text auto-linkifies raw URLs into gold anchor tags
- New 'books' placement: Reading List grid on Downloads page (cover, desc, Amazon btn)
- New 'recommended' placement: editable Recommended Resources section on Downloads
page; falls back to Truth For Life widget when empty
- Admin: Books and Recommended Resources panels added to Content nav
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a one-click "Fetch from BSB" button in the lesson passage text field
that calls the BSB API and overwrites the field with verse-numbered text.
Also fixes reference parsing to tolerate leading book abbreviations like
t:1-2 or col:1-2 by stripping letters before the chapter:verse pattern.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds /api/bible-passage server route that proxies the Berean Standard Bible
from Bolls.life per-verse, with in-memory caching. Study lesson scripture
block now displays live BSB text instead of static passageText. Adds
bibleBook field to StudyProgram so admins can set the book name explicitly
when the study slug doesn't match (e.g. a study titled "ephesians-part-2").
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Splits the analytics panel into Traffic / Engagement / System tabs so
episode plays, engagement metrics, and contact/study data are no longer
buried under the visitor log.
Fixes a bug where topCountries, topStates, topCities, device breakdown,
and referrers were computed from only the 100 most-recent visitor rows
instead of all rows in the selected range — causing older geographic data
(e.g. visits from India, Texas, Georgia) to silently disappear from the
aggregate totals.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces outbound-only tracking with a useLinkClickTracking hook that
captures every <a> click on the site. Stores as link_click events keyed
by destination URL, with an internal flag. Admin analytics page gains a
Link Clicks table sorted by count, showing type (internal/external).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The SW's navigateFallback was using a denylist, so any path not explicitly
excluded (e.g. /spotify, /apple, /amazon, custom admin redirects) got served
the cached index.html instead of reaching the server's redirect handler.
Switch to navigateFallbackAllowlist: the SW only intercepts known SPA routes;
all other paths hit the network so server-side 301/302 redirects work correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Admin can set birthday (month/day) per student in Study Users panel
- Summer birthdays (Jun–Aug) prompt admin to set an alternate school-year date
- 🎂 badge on student card header during birthday week
- Dismissible happy birthday banner shown to student on their study hub
- Admin receives email notification on the celebration day, once per year
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
package.json was missing from the runtime stage, causing readPackageVersion()
to throw and fall back to 'unknown'. The git commit hash (from COMMIT_SHA env)
was the only identifier shown.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Day thresholds and per-tier subject/body/CTA are now editable in the
Email Templates panel. Tier keys are position-based (t1/t2/t3) so
changing day values never re-sends emails already fired.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sends 7/14/30-day inactivity emails to study users who haven't logged in,
with one-click HMAC-signed unsubscribe and automatic re-arm on next login.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Inbound emails from some clients (Outlook, mobile) send htmlBody as
base64. Decode it on the server before storing (future emails) and on
the client before passing to the iframe srcDoc (existing stored emails).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>