From 729cf94c12eddcf2d2496b35ae084e22dbfc24e2 Mon Sep 17 00:00:00 2001 From: nmemmert Date: Tue, 13 Oct 2026 07:56:11 -0400 Subject: [PATCH] Home page redesign: latest-episode player beside current series, ways-in cards, finished-books shelf, shortened PRISM, newsletter + share band, quieter 'more from us' group; v2.32.0 Co-Authored-By: Claude Sonnet 5.5 --- package-lock.json | 4 +- package.json | 2 +- src/App.css | 48 +++++++ src/App.tsx | 359 +++++++++++++++++++++++++++------------------- 4 files changed, 263 insertions(+), 150 deletions(-) diff --git a/package-lock.json b/package-lock.json index 330e1c7..a957bf5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "siteforge", - "version": "2.31.1", + "version": "2.32.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "siteforge", - "version": "2.31.1", + "version": "2.32.0", "dependencies": { "@aws-sdk/client-s3": "^3.1135.0", "@dnd-kit/core": "^6.3.1", diff --git a/package.json b/package.json index 108a3b5..06c1841 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "siteforge", "private": true, - "version": "2.31.1", + "version": "2.32.0", "type": "module", "scripts": { "dev": "vite", diff --git a/src/App.css b/src/App.css index 167a020..8f33ae3 100644 --- a/src/App.css +++ b/src/App.css @@ -13825,3 +13825,51 @@ a.study-track-card:hover { .finished-book-card--featured .finished-book-card-img { aspect-ratio: 16 / 9; height: auto; } } .ep-hero-player { margin-bottom: 0.5rem; } + +/* ── Home page redesign ── */ +.hero-stats { margin: 1.1rem 0 0; font-size: 0.85rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--brand-gold); opacity: 0.85; } + +.section-home-now { background: #080808; border-top: 1px solid rgba(201, 168, 76, 0.18); border-bottom: 1px solid rgba(201, 168, 76, 0.18); padding: 3.5rem 0; } +.home-now-grid { max-width: 1100px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: 2.5rem; align-items: start; } +.home-now-player .eyebrow, .home-now-series .eyebrow { margin-bottom: 0.9rem; } +.home-now-all { display: inline-block; margin-top: 0.9rem; font-size: 0.88rem; color: var(--brand-gold); text-decoration: none; letter-spacing: 0.04em; } +.home-now-series { display: flex; flex-direction: column; gap: 1rem; } +.home-now-series .eyebrow { margin-bottom: 0; } +.home-series-card { display: grid; grid-template-columns: 120px 1fr; gap: 1.25rem; align-items: start; background: #131313; border: 1px solid rgba(201, 168, 76, 0.22); border-radius: 14px; padding: 1.1rem; } +.home-series-art { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 8px; } +.home-series-info h3 { font-family: var(--brand-font-heading); font-size: 1.3rem; color: var(--brand-warm-white); margin: 0 0 0.4rem; } +.home-series-desc { color: var(--brand-muted); font-size: 0.95rem; line-height: 1.55; margin: 0 0 0.9rem; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } +.home-series-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; } + +.section-home-shelf { padding: 3rem 0 2.5rem; background: var(--brand-black); } +.home-shelf-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; } +.home-shelf-row { display: flex; gap: 1rem; overflow-x: auto; padding-bottom: 0.75rem; scroll-snap-type: x proximity; scrollbar-width: thin; } +.home-shelf-book { flex: 0 0 130px; scroll-snap-align: start; text-decoration: none; color: #e8d9b5; font-size: 0.88rem; text-align: center; display: flex; flex-direction: column; gap: 0.5rem; } +.home-shelf-book img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 8px; border: 1px solid rgba(201, 168, 76, 0.25); transition: transform 180ms, border-color 180ms; } +.home-shelf-book:hover img { transform: translateY(-3px); border-color: rgba(201, 168, 76, 0.6); } + +.prism-steps--chips { display: flex; flex-wrap: wrap; gap: 0.45rem; margin: 1rem 0; } +.prism-steps--chips p { padding: 0.4rem 0.8rem; border-radius: 999px; font-size: 0.82rem; } +.prism-more { background: transparent; border: 0; padding: 0; color: var(--brand-gold); font-family: var(--brand-font-body); font-size: 0.9rem; letter-spacing: 0.04em; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; } +.section-prism { padding: 3.5rem 0; } + +.section-home-connect { background: #0c0c08; border-top: 1px solid rgba(201, 168, 76, 0.15); border-bottom: 1px solid rgba(201, 168, 76, 0.15); padding: 3.5rem 0; } +.home-connect-grid { max-width: 1100px; display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; } +.home-connect-card { background: rgba(26, 26, 21, 0.7); border: 1px solid rgba(201, 168, 76, 0.18); border-radius: 14px; padding: 2rem; } +.home-connect-card--newsletter { text-align: center; } +.home-connect-card--newsletter .newsletter-inner { max-width: none; } +.home-connect-card .section-heading { font-size: 1.5rem; } +.home-connect-card .share-p { margin-bottom: 1.1rem; } +.home-connect-share-row { display: flex; align-items: center; justify-content: space-between; gap: 1.25rem; flex-wrap: wrap; } +.home-connect-share-row .share-qr { width: 110px; height: 110px; } + +.home-more .section-qa-callout, .home-more .section-tfl, .home-more .section-external-sites { padding-top: 3rem; padding-bottom: 3rem; } + +@media (max-width: 860px) { + .home-now-grid, .home-connect-grid { grid-template-columns: 1fr; gap: 2rem; } +} +@media (max-width: 520px) { + .home-series-card { grid-template-columns: 84px 1fr; gap: 0.9rem; padding: 0.9rem; } + .home-series-info h3 { font-size: 1.1rem; } + .home-connect-card { padding: 1.4rem; } +} diff --git a/src/App.tsx b/src/App.tsx index 1a6c963..fa88a64 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1052,7 +1052,7 @@ function ExternalSitesSection({ content }: { content: SiteContent }) { ) } -function HomepageNewsletterSection() { +function HomepageNewsletterSection({ embedded = false }: { embedded?: boolean }) { const [email, setEmail] = useState('') const [firstName, setFirstName] = useState('') const [honey, setHoney] = useState('') @@ -1074,44 +1074,52 @@ function HomepageNewsletterSection() { } } + const content = ( + <> +

Stay in the Word

+

Get episode updates by email

+

New episodes, study resources, and ministry updates — delivered to your inbox.

+ {status === 'done' ? ( +

You're subscribed! Thank you for signing up.

+ ) : ( +
+ setHoney(e.target.value)} /> +
+ setFirstName(e.target.value)} + className="newsletter-input" + /> + setEmail(e.target.value)} + className="newsletter-input" + /> + +
+ {status === 'error' &&

Something went wrong. Please try again.

} +
+ )} + + ) + + // `embedded` drops the full-width band so the signup can sit inside another section (homepage connect row). + if (embedded) { + return
{content}
+ } return (
-
-

Stay in the Word

-

Get episode updates by email

-

New episodes, study resources, and ministry updates — delivered to your inbox.

- {status === 'done' ? ( -

You're subscribed! Thank you for signing up.

- ) : ( -
- setHoney(e.target.value)} /> -
- setFirstName(e.target.value)} - className="newsletter-input" - /> - setEmail(e.target.value)} - className="newsletter-input" - /> - -
- {status === 'error' &&

Something went wrong. Please try again.

} -
- )} -
+
{content}
) } @@ -1224,6 +1232,44 @@ function TestimonialsSection({ testimonials }: { testimonials: Testimonial[] }) function LandingPage({ content }: { content: SiteContent }) { const featuredStudy = getHomepageFeaturedStudy(content) + const { episodes } = useAllEpisodes() + const [prismOpen, setPrismOpen] = useState(false) + const finishedBooks = [...(content.finishedBooks ?? [])].sort((a, b) => b.season - a.season) + const episodesInSeason = (season?: number) => (season ? episodes.filter(ep => ep.season === String(season)).length : 0) + + const liveSeries = [ + { + key: 'primary', + imageUrl: content.seriesImageUrl, + title: content.seriesTitle, + label: content.seriesLabel, + description: content.seriesDescription, + listenUrl: content.seriesListenUrl, + listenBtnLabel: content.seriesListenBtnLabel, + studySlug: content.seriesStudySlug, + season: content.seriesSeason, + }, + ...(content.secondSeries?.title?.trim() + ? [{ + key: 'second', + imageUrl: content.secondSeries.imageUrl, + title: content.secondSeries.title, + label: content.secondSeries.label, + description: content.secondSeries.description, + listenUrl: content.secondSeries.listenUrl, + listenBtnLabel: content.secondSeries.listenBtnLabel, + studySlug: content.secondSeries.studySlug, + season: content.secondSeries.season, + }] + : []), + ] + + // Fixed "ways in" cards go first; the admin-managed cards follow, skipping any that point to the same page. + const adminCards = content.whereToNextCards ?? [] + const fixedCards = [ + { id: 'start', path: '/start-here', title: 'Start here', description: 'New to the show? A short path through the best first episodes.' }, + { id: 'verse', path: '/scripture', title: 'Find a verse', description: 'Look up any passage and jump to the episode or lesson that covers it.' }, + ].filter(card => !adminCards.some(c => c.path === card.path)) return (
@@ -1259,12 +1305,108 @@ function LandingPage({ content }: { content: SiteContent }) { {content.heroBtnSpotify || 'Listen on Spotify'} - {content.heroBtnEpisodes || 'Explore Episodes ↓'} {content.heroBtnStartHere || 'New here? Start here →'} + {content.heroBtnEpisodes || 'Explore Episodes ↓'} +
+ {episodes.length > 0 && ( +

+ {episodes.length} episodes + {finishedBooks.length > 0 && <> · {finishedBooks.length} {finishedBooks.length === 1 ? 'book' : 'books'} completed} +

+ )} + + + + {/* ── LISTEN NOW: latest episode + current series ── */} +
+
+
+

Latest Episode

+ + Browse all episodes → +
+
+

Current Series

+ {liveSeries.map(series => { + const count = episodesInSeason(series.season) + return ( + + ) + })}
+ {/* ── WAYS IN ── */} +
+
+
+

{content.whereToNextEyebrow || 'Where to Next'}

+

{content.whereToNextHeading || 'Choose the page you need.'}

+
+
+ {[...fixedCards, ...adminCards].map(card => ( + +

{card.title}

+

{card.description}

+ + ))} + {featuredStudy && ( + +
+

{featuredStudy.homepageEyebrow || 'Study'}

+ {featuredStudy.showNewTag && {featuredStudy.newTagLabel || 'NEW'}} +
+

{featuredStudy.title}

+

{featuredStudy.description || 'Explore this study track with lesson notes, commentary, and guided questions.'}

+ + )} +
+
+
+ + {/* ── FINISHED BOOKS SHELF ── */} + {finishedBooks.length > 0 && ( +
+
+
+

Books We've Finished

+ See all → +
+
+ {finishedBooks.map(book => ( + + {book.imageUrl && {book.title}} + {book.title} + + ))} +
+
+
+ )} + + {/* ── PRISM ── */}
@@ -1288,136 +1430,59 @@ function LandingPage({ content }: { content: SiteContent }) {

{content.prismIntro || 'What if every time you opened your Bible, you had a clear, repeatable method to actually dig in?'}

-

- {content.prismPatternIntro || 'In this bonus episode, I walk you through P.R.I.S.M. — a five-step daily Bible study pattern designed to help you slow down, go deep, and let the Word do its work.'} -

-
+

{content.prismStep1 || 'P — Pray before you read'}

{content.prismStep2 || 'R — Read slowly and observe'}

{content.prismStep3 || 'I — Interpret with context'}

{content.prismStep4 || 'S — Study and apply specifically'}

{content.prismStep5 || 'M — Memorize one verse at a time'}

-

- {content.prismOutro || "Whether you're brand new to daily Bible reading or you've been at it for years, P.R.I.S.M. gives you a consistent framework for every passage, every day."} -

-

- {content.prismClosing || "The goal isn't to get through the text — it's to let the text get through to you."} -

-
-
-
- - - -
-
-

- ✦ Current Series{' '} - ✦ -

-
- {[ - { - key: 'primary', - imageUrl: content.seriesImageUrl, - title: content.seriesTitle, - label: content.seriesLabel, - description: content.seriesDescription, - listenUrl: content.seriesListenUrl, - listenBtnLabel: content.seriesListenBtnLabel, - studySlug: content.seriesStudySlug, - }, - ...(content.secondSeries?.title?.trim() - ? [{ - key: 'second', - imageUrl: content.secondSeries.imageUrl, - title: content.secondSeries.title, - label: content.secondSeries.label, - description: content.secondSeries.description, - listenUrl: content.secondSeries.listenUrl, - listenBtnLabel: content.secondSeries.listenBtnLabel, - studySlug: content.secondSeries.studySlug, - }] - : []), - ].map(series => ( - - ))} -
-
-
- - - - - -
-
-
-

{content.whereToNextEyebrow || 'Where to Next'}

-

{content.whereToNextHeading || 'Choose the page you need.'}

-
-
- {(content.whereToNextCards ?? []).map(card => ( - -

{card.title}

-

{card.description}

- - ))} - {featuredStudy && ( - -
-

{featuredStudy.homepageEyebrow || 'Study'}

- {featuredStudy.showNewTag && {featuredStudy.newTagLabel || 'NEW'}} -
-

{featuredStudy.title}

-

{featuredStudy.description || 'Explore this study track with lesson notes, commentary, and guided questions.'}

- + {prismOpen && ( + <> +

+ {content.prismPatternIntro || 'In this bonus episode, I walk you through P.R.I.S.M. — a five-step daily Bible study pattern designed to help you slow down, go deep, and let the Word do its work.'} +

+

+ {content.prismOutro || "Whether you're brand new to daily Bible reading or you've been at it for years, P.R.I.S.M. gives you a consistent framework for every passage, every day."} +

+

+ {content.prismClosing || "The goal isn't to get through the text — it's to let the text get through to you."} +

+ )} +
- - -
-
-
+ {/* ── CONNECT: newsletter + share ── */} +
+
+ +

{content.shareHeading || 'Help one more person hear the Word this week.'}

{content.shareP || 'Scan the QR code or text the show link to a friend who needs encouragement today.'}

- +
+ + QR code to share the show +
- QR code to share the show
+ {/* ── MORE FROM US ── */} +
+ + + +
+