Make welcome email editable in admin and skip admin notice for newsletter signups
This commit is contained in:
@@ -1877,28 +1877,85 @@ app.post('/api/contact', contactRateLimit, async (req, res) => {
|
|||||||
|
|
||||||
if (shouldSendWelcome && !USE_RESEND_AUTOMATION_WELCOME) {
|
if (shouldSendWelcome && !USE_RESEND_AUTOMATION_WELCOME) {
|
||||||
const greetingName = splitName(trimmedName).firstName?.trim() ?? ''
|
const greetingName = splitName(trimmedName).firstName?.trim() ?? ''
|
||||||
|
let publishedSiteContent = cachedSiteContent
|
||||||
|
if (!publishedSiteContent) {
|
||||||
|
try {
|
||||||
|
const published = await loadSiteContentFile(DATA_FILE)
|
||||||
|
publishedSiteContent = published?.siteContent ?? null
|
||||||
|
} catch {
|
||||||
|
publishedSiteContent = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const emailConfig = publishedSiteContent ?? {}
|
||||||
|
const welcomeBaseUrl = typeof emailConfig?.seo?.canonicalUrl === 'string' && emailConfig.seo.canonicalUrl.trim()
|
||||||
|
? emailConfig.seo.canonicalUrl.trim()
|
||||||
|
: DEFAULT_SEO.canonicalUrl
|
||||||
|
const welcomeSubject = process.env.RESEND_WELCOME_SUBJECT ?? emailConfig.welcomeEmailSubject ?? 'Welcome to Verse by Verse with Nate'
|
||||||
|
const welcomeGreetingPrefix = emailConfig.welcomeEmailGreetingPrefix?.trim() || "Glad you're here"
|
||||||
const welcomeHeading = greetingName
|
const welcomeHeading = greetingName
|
||||||
? `Glad you’re here, ${escapeHtml(greetingName)}.`
|
? `${escapeHtml(welcomeGreetingPrefix)}, ${escapeHtml(greetingName)}.`
|
||||||
: 'Glad you’re here.'
|
: `${escapeHtml(welcomeGreetingPrefix)}.`
|
||||||
const welcomeSpotifyUrl = process.env.RESEND_WELCOME_SPOTIFY_URL ?? 'https://versebyversewithnate.us/spotify'
|
const welcomeIntro = emailConfig.welcomeEmailIntro?.trim()
|
||||||
const welcomeAppleUrl = process.env.RESEND_WELCOME_APPLE_URL ?? 'https://versebyversewithnate.us/apple'
|
|| 'Thanks for subscribing to Verse by Verse with Nate - a Bible teaching podcast where we slow down, dig into the text, and pull out the nuggets God has for us word by word.'
|
||||||
const welcomeAmazonUrl = process.env.RESEND_WELCOME_AMAZON_URL ?? 'https://versebyversewithnate.us/amazon'
|
const welcomeCurrentSeries = emailConfig.welcomeEmailCurrentSeries?.trim()
|
||||||
const welcomeWebsiteUrl = process.env.RESEND_WELCOME_WEBSITE_URL ?? 'https://versebyversewithnate.us'
|
|| 'Right now we\'re working through the book of Titus - a short letter packed with practical wisdom about grace, godliness, and what the Christian life looks like when it\'s rooted in sound doctrine.'
|
||||||
const welcomeEpisodeUrl = process.env.RESEND_WELCOME_EPISODE_URL ?? 'https://versebyversewithnate.us/start-here'
|
const welcomeStartHereTitle = emailConfig.welcomeEmailStartHereTitle?.trim() || 'Episode 1 - Introduction to Titus'
|
||||||
const welcomeImageUrl = process.env.RESEND_WELCOME_IMAGE_URL ?? 'https://versebyversewithnate.us/images/podcast-art.jpeg'
|
const welcomeStartHereSummary = emailConfig.welcomeEmailStartHereSummary?.trim() || 'Who wrote it, who received it, and why it still matters.'
|
||||||
|
const welcomeExpect1 = emailConfig.welcomeEmailWhatToExpect1?.trim() || 'Verse-by-verse teaching - we go slow and let the text speak for itself.'
|
||||||
|
const welcomeExpect2 = emailConfig.welcomeEmailWhatToExpect2?.trim() || 'Greek word studies - the kind that open up meaning without being a lecture.'
|
||||||
|
const welcomeExpect3 = emailConfig.welcomeEmailWhatToExpect3?.trim() || 'New episodes + study notes delivered right to your inbox.'
|
||||||
|
const welcomeScripture = emailConfig.welcomeEmailScripture?.trim() || 'For the grace of God has appeared, bringing salvation to all people.'
|
||||||
|
const welcomeScriptureRef = emailConfig.welcomeEmailScriptureRef?.trim() || 'Titus 2:11 - BSB'
|
||||||
|
const welcomeSignoff = emailConfig.welcomeEmailSignoff?.trim() || 'Grace and peace,\nNate'
|
||||||
|
const welcomeSignoffHtml = escapeHtml(welcomeSignoff).replace(/\n/g, '<br/>')
|
||||||
|
const welcomeSpotifyUrl = buildAbsoluteUrl(
|
||||||
|
welcomeBaseUrl,
|
||||||
|
process.env.RESEND_WELCOME_SPOTIFY_URL ?? emailConfig.welcomeEmailSpotifyUrl ?? '/spotify',
|
||||||
|
)
|
||||||
|
const welcomeAppleUrl = buildAbsoluteUrl(
|
||||||
|
welcomeBaseUrl,
|
||||||
|
process.env.RESEND_WELCOME_APPLE_URL ?? emailConfig.welcomeEmailAppleUrl ?? '/apple',
|
||||||
|
)
|
||||||
|
const welcomeAmazonUrl = buildAbsoluteUrl(
|
||||||
|
welcomeBaseUrl,
|
||||||
|
process.env.RESEND_WELCOME_AMAZON_URL ?? emailConfig.welcomeEmailAmazonUrl ?? '/amazon',
|
||||||
|
)
|
||||||
|
const welcomeWebsiteUrl = buildAbsoluteUrl(
|
||||||
|
welcomeBaseUrl,
|
||||||
|
process.env.RESEND_WELCOME_WEBSITE_URL ?? emailConfig.welcomeEmailWebsiteUrl ?? '/',
|
||||||
|
)
|
||||||
|
const welcomeEpisodeUrl = buildAbsoluteUrl(
|
||||||
|
welcomeBaseUrl,
|
||||||
|
process.env.RESEND_WELCOME_EPISODE_URL ?? emailConfig.welcomeEmailStartHereUrl ?? '/start-here',
|
||||||
|
)
|
||||||
|
const welcomeImageUrl = buildAbsoluteUrl(
|
||||||
|
welcomeBaseUrl,
|
||||||
|
process.env.RESEND_WELCOME_IMAGE_URL ?? emailConfig.welcomeEmailImageUrl ?? '/images/podcast-art.jpeg',
|
||||||
|
)
|
||||||
|
|
||||||
const { error: welcomeError } = await resend.emails.send({
|
const { error: welcomeError } = await resend.emails.send({
|
||||||
from: process.env.RESEND_FROM ?? 'Verse by Verse with Nate <hello@versebyversewithnate.us>',
|
from: process.env.RESEND_FROM ?? 'Verse by Verse with Nate <hello@versebyversewithnate.us>',
|
||||||
to: [trimmedEmail],
|
to: [trimmedEmail],
|
||||||
subject: process.env.RESEND_WELCOME_SUBJECT ?? 'Welcome to Verse by Verse with Nate',
|
subject: welcomeSubject,
|
||||||
text:
|
text:
|
||||||
`Welcome to Verse by Verse with Nate!\n\n` +
|
`Welcome to Verse by Verse with Nate!\n\n` +
|
||||||
`${greetingName ? `Glad you're here, ${greetingName}.` : "Glad you're here."}\n\n` +
|
`${greetingName ? `Glad you're here, ${greetingName}.` : "Glad you're here."}\n\n` +
|
||||||
|
`${welcomeIntro}\n\n` +
|
||||||
|
`${welcomeCurrentSeries}\n\n` +
|
||||||
`Start here: ${welcomeEpisodeUrl}\n` +
|
`Start here: ${welcomeEpisodeUrl}\n` +
|
||||||
|
`${welcomeStartHereTitle}\n` +
|
||||||
|
`${welcomeStartHereSummary}\n` +
|
||||||
`Spotify: ${welcomeSpotifyUrl}\n` +
|
`Spotify: ${welcomeSpotifyUrl}\n` +
|
||||||
`Apple Podcasts: ${welcomeAppleUrl}\n` +
|
`Apple Podcasts: ${welcomeAppleUrl}\n` +
|
||||||
`Amazon Music: ${welcomeAmazonUrl}\n\n` +
|
`Amazon Music: ${welcomeAmazonUrl}\n` +
|
||||||
`Grace and peace,\nNate`,
|
`Website: ${welcomeWebsiteUrl}\n\n` +
|
||||||
|
`What to expect:\n` +
|
||||||
|
`- ${welcomeExpect1}\n` +
|
||||||
|
`- ${welcomeExpect2}\n` +
|
||||||
|
`- ${welcomeExpect3}\n\n` +
|
||||||
|
`${welcomeScripture}\n${welcomeScriptureRef}\n\n` +
|
||||||
|
`${welcomeSignoff}`,
|
||||||
html:
|
html:
|
||||||
`<div style="margin:0;padding:0;background-color:#0a0a08;font-family:Georgia,serif;">` +
|
`<div style="margin:0;padding:0;background-color:#0a0a08;font-family:Georgia,serif;">` +
|
||||||
`<table width="100%" cellpadding="0" cellspacing="0" border="0" role="presentation" style="background-color:#0a0a08;">` +
|
`<table width="100%" cellpadding="0" cellspacing="0" border="0" role="presentation" style="background-color:#0a0a08;">` +
|
||||||
@@ -1915,15 +1972,15 @@ app.post('/api/contact', contactRateLimit, async (req, res) => {
|
|||||||
`<div style="width:40px;height:2px;background-color:#c9a84c;margin-bottom:28px;"></div>` +
|
`<div style="width:40px;height:2px;background-color:#c9a84c;margin-bottom:28px;"></div>` +
|
||||||
`</td></tr>` +
|
`</td></tr>` +
|
||||||
`<tr><td style="padding:0 40px 32px;">` +
|
`<tr><td style="padding:0 40px 32px;">` +
|
||||||
`<p style="margin:0 0 18px;font-family:Georgia,serif;font-size:18px;font-weight:300;color:#c8c0ac;line-height:1.75;">Thanks for subscribing to <em>Verse by Verse with Nate</em> - a Bible teaching podcast where we slow down, dig into the text, and pull out the nuggets God has for us word by word.</p>` +
|
`<p style="margin:0 0 18px;font-family:Georgia,serif;font-size:18px;font-weight:300;color:#c8c0ac;line-height:1.75;">${escapeHtml(welcomeIntro)}</p>` +
|
||||||
`<p style="margin:0 0 18px;font-family:Georgia,serif;font-size:18px;font-weight:300;color:#c8c0ac;line-height:1.75;">Right now we’re working through the book of <strong style="color:#f0ead8;font-weight:400;">Titus</strong> - a short letter packed with practical wisdom about grace, godliness, and what the Christian life looks like when it’s rooted in sound doctrine.</p>` +
|
`<p style="margin:0 0 18px;font-family:Georgia,serif;font-size:18px;font-weight:300;color:#c8c0ac;line-height:1.75;">${escapeHtml(welcomeCurrentSeries)}</p>` +
|
||||||
`<p style="margin:0;font-family:Georgia,serif;font-size:18px;font-weight:300;color:#c8c0ac;line-height:1.75;">If you’re just joining us, the best place to start is Episode 1. It sets the table for everything that follows.</p>` +
|
`<p style="margin:0;font-family:Georgia,serif;font-size:18px;font-weight:300;color:#c8c0ac;line-height:1.75;">If you’re just joining us, the best place to start is Episode 1. It sets the table for everything that follows.</p>` +
|
||||||
`</td></tr>` +
|
`</td></tr>` +
|
||||||
`<tr><td style="padding:0 40px;"><div style="height:1px;background-color:#2a2518;margin-bottom:32px;"></div></td></tr>` +
|
`<tr><td style="padding:0 40px;"><div style="height:1px;background-color:#2a2518;margin-bottom:32px;"></div></td></tr>` +
|
||||||
`<tr><td style="padding:0 40px 32px;">` +
|
`<tr><td style="padding:0 40px 32px;">` +
|
||||||
`<p style="margin:0 0 6px;font-family:Georgia,serif;font-size:13px;font-weight:400;color:#7a7060;letter-spacing:0.12em;text-transform:uppercase;">Start here</p>` +
|
`<p style="margin:0 0 6px;font-family:Georgia,serif;font-size:13px;font-weight:400;color:#7a7060;letter-spacing:0.12em;text-transform:uppercase;">Start here</p>` +
|
||||||
`<p style="margin:0 0 6px;font-family:Georgia,serif;font-size:22px;font-weight:600;color:#f0ead8;">Episode 1 - Introduction to Titus</p>` +
|
`<p style="margin:0 0 6px;font-family:Georgia,serif;font-size:22px;font-weight:600;color:#f0ead8;">${escapeHtml(welcomeStartHereTitle)}</p>` +
|
||||||
`<p style="margin:0 0 20px;font-family:Georgia,serif;font-size:16px;font-weight:300;color:#7a7060;line-height:1.6;">Who wrote it, who received it, and why it still matters.</p>` +
|
`<p style="margin:0 0 20px;font-family:Georgia,serif;font-size:16px;font-weight:300;color:#7a7060;line-height:1.6;">${escapeHtml(welcomeStartHereSummary)}</p>` +
|
||||||
`<table cellpadding="0" cellspacing="0" border="0" role="presentation"><tr>` +
|
`<table cellpadding="0" cellspacing="0" border="0" role="presentation"><tr>` +
|
||||||
`<td style="padding-right:12px;"><a href="${escapeHtml(welcomeSpotifyUrl)}" target="_blank" style="display:inline-block;padding:11px 22px;background-color:#c9a84c;color:#0d0d0a;font-family:Georgia,serif;font-size:14px;font-weight:600;letter-spacing:0.06em;text-decoration:none;border-radius:3px;">Listen on Spotify</a></td>` +
|
`<td style="padding-right:12px;"><a href="${escapeHtml(welcomeSpotifyUrl)}" target="_blank" style="display:inline-block;padding:11px 22px;background-color:#c9a84c;color:#0d0d0a;font-family:Georgia,serif;font-size:14px;font-weight:600;letter-spacing:0.06em;text-decoration:none;border-radius:3px;">Listen on Spotify</a></td>` +
|
||||||
`<td><a href="${escapeHtml(welcomeAppleUrl)}" target="_blank" style="display:inline-block;padding:11px 22px;background-color:transparent;color:#c9a84c;font-family:Georgia,serif;font-size:14px;font-weight:600;letter-spacing:0.06em;text-decoration:none;border-radius:3px;border:1px solid #c9a84c;">Apple Podcasts</a></td>` +
|
`<td><a href="${escapeHtml(welcomeAppleUrl)}" target="_blank" style="display:inline-block;padding:11px 22px;background-color:transparent;color:#c9a84c;font-family:Georgia,serif;font-size:14px;font-weight:600;letter-spacing:0.06em;text-decoration:none;border-radius:3px;border:1px solid #c9a84c;">Apple Podcasts</a></td>` +
|
||||||
@@ -1933,15 +1990,15 @@ app.post('/api/contact', contactRateLimit, async (req, res) => {
|
|||||||
`<tr><td style="padding:0 40px;"><div style="height:1px;background-color:#2a2518;margin-bottom:32px;"></div></td></tr>` +
|
`<tr><td style="padding:0 40px;"><div style="height:1px;background-color:#2a2518;margin-bottom:32px;"></div></td></tr>` +
|
||||||
`<tr><td style="padding:0 40px 32px;">` +
|
`<tr><td style="padding:0 40px 32px;">` +
|
||||||
`<p style="margin:0 0 20px;font-family:Georgia,serif;font-size:13px;font-weight:400;color:#7a7060;letter-spacing:0.12em;text-transform:uppercase;">What to expect</p>` +
|
`<p style="margin:0 0 20px;font-family:Georgia,serif;font-size:13px;font-weight:400;color:#7a7060;letter-spacing:0.12em;text-transform:uppercase;">What to expect</p>` +
|
||||||
`<p style="margin:0 0 12px;font-family:Georgia,serif;font-size:17px;font-weight:400;color:#c8c0ac;line-height:1.65;"><strong style="color:#f0ead8;font-weight:400;">Verse-by-verse teaching</strong> - we go slow and let the text speak for itself.</p>` +
|
`<p style="margin:0 0 12px;font-family:Georgia,serif;font-size:17px;font-weight:400;color:#c8c0ac;line-height:1.65;">${escapeHtml(welcomeExpect1)}</p>` +
|
||||||
`<p style="margin:0 0 12px;font-family:Georgia,serif;font-size:17px;font-weight:400;color:#c8c0ac;line-height:1.65;"><strong style="color:#f0ead8;font-weight:400;">Greek word studies</strong> - the kind that open up meaning without being a lecture.</p>` +
|
`<p style="margin:0 0 12px;font-family:Georgia,serif;font-size:17px;font-weight:400;color:#c8c0ac;line-height:1.65;">${escapeHtml(welcomeExpect2)}</p>` +
|
||||||
`<p style="margin:0;font-family:Georgia,serif;font-size:17px;font-weight:400;color:#c8c0ac;line-height:1.65;"><strong style="color:#f0ead8;font-weight:400;">New episodes + study notes</strong> delivered right to your inbox.</p>` +
|
`<p style="margin:0;font-family:Georgia,serif;font-size:17px;font-weight:400;color:#c8c0ac;line-height:1.65;">${escapeHtml(welcomeExpect3)}</p>` +
|
||||||
`</td></tr>` +
|
`</td></tr>` +
|
||||||
`<tr><td style="padding:0 40px;"><div style="height:1px;background-color:#2a2518;margin-bottom:32px;"></div></td></tr>` +
|
`<tr><td style="padding:0 40px;"><div style="height:1px;background-color:#2a2518;margin-bottom:32px;"></div></td></tr>` +
|
||||||
`<tr><td style="padding:0 40px 40px;">` +
|
`<tr><td style="padding:0 40px 40px;">` +
|
||||||
`<table cellpadding="0" cellspacing="0" border="0" role="presentation" style="width:100%;border-left:2px solid #c9a84c;"><tr><td style="padding:4px 0 4px 20px;">` +
|
`<table cellpadding="0" cellspacing="0" border="0" role="presentation" style="width:100%;border-left:2px solid #c9a84c;"><tr><td style="padding:4px 0 4px 20px;">` +
|
||||||
`<p style="margin:0 0 8px;font-family:Georgia,serif;font-size:19px;font-style:italic;font-weight:400;color:#e0c070;line-height:1.6;">“For the grace of God has appeared, bringing salvation to all people.”</p>` +
|
`<p style="margin:0 0 8px;font-family:Georgia,serif;font-size:19px;font-style:italic;font-weight:400;color:#e0c070;line-height:1.6;">“${escapeHtml(welcomeScripture)}”</p>` +
|
||||||
`<p style="margin:0;font-family:Georgia,serif;font-size:13px;font-weight:300;color:#7a7060;letter-spacing:0.06em;text-transform:uppercase;">Titus 2:11 - BSB</p>` +
|
`<p style="margin:0;font-family:Georgia,serif;font-size:13px;font-weight:300;color:#7a7060;letter-spacing:0.06em;text-transform:uppercase;">${escapeHtml(welcomeScriptureRef)}</p>` +
|
||||||
`</td></tr></table>` +
|
`</td></tr></table>` +
|
||||||
`</td></tr>` +
|
`</td></tr>` +
|
||||||
`<tr><td style="background-color:#0a0a08;border-top:1px solid #2a2518;padding:28px 40px;text-align:center;">` +
|
`<tr><td style="background-color:#0a0a08;border-top:1px solid #2a2518;padding:28px 40px;text-align:center;">` +
|
||||||
@@ -1956,7 +2013,7 @@ app.post('/api/contact', contactRateLimit, async (req, res) => {
|
|||||||
`<td style="padding:0 10px;"><a href="${escapeHtml(welcomeWebsiteUrl)}" target="_blank" style="font-family:Georgia,serif;font-size:13px;font-weight:300;color:#7a7060;text-decoration:none;letter-spacing:0.04em;">Website</a></td>` +
|
`<td style="padding:0 10px;"><a href="${escapeHtml(welcomeWebsiteUrl)}" target="_blank" style="font-family:Georgia,serif;font-size:13px;font-weight:300;color:#7a7060;text-decoration:none;letter-spacing:0.04em;">Website</a></td>` +
|
||||||
`</tr></table>` +
|
`</tr></table>` +
|
||||||
`<p style="margin:0 0 6px;font-family:Georgia,serif;font-size:12px;font-weight:300;color:#4a4438;line-height:1.6;">You’re receiving this because you subscribed to <strong style="color:#5a5035;font-weight:400;">Verse by Verse with Nate</strong>.</p>` +
|
`<p style="margin:0 0 6px;font-family:Georgia,serif;font-size:12px;font-weight:300;color:#4a4438;line-height:1.6;">You’re receiving this because you subscribed to <strong style="color:#5a5035;font-weight:400;">Verse by Verse with Nate</strong>.</p>` +
|
||||||
`<p style="margin:0;font-family:Georgia,serif;font-size:13px;font-style:italic;font-weight:400;color:#3a3428;">“Your word is a lamp to my feet and a light to my path.” - Psalm 119:105</p>` +
|
`<p style="margin:10px 0 0;font-family:Georgia,serif;font-size:14px;font-weight:400;color:#c8c0ac;line-height:1.5;">${welcomeSignoffHtml}</p>` +
|
||||||
`</td></tr>` +
|
`</td></tr>` +
|
||||||
`</table>` +
|
`</table>` +
|
||||||
`</td></tr></table>` +
|
`</td></tr></table>` +
|
||||||
@@ -1966,6 +2023,11 @@ app.post('/api/contact', contactRateLimit, async (req, res) => {
|
|||||||
if (welcomeError) throw welcomeError
|
if (welcomeError) throw welcomeError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shouldSendWelcome) {
|
||||||
|
res.json({ ok: true })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const { error } = await resend.emails.send({
|
const { error } = await resend.emails.send({
|
||||||
from: process.env.RESEND_FROM ?? 'Verse by Verse with Nate <hello@versebyversewithnate.us>',
|
from: process.env.RESEND_FROM ?? 'Verse by Verse with Nate <hello@versebyversewithnate.us>',
|
||||||
to: [process.env.RESEND_TO ?? 'hello@versebyversewithnate.us'],
|
to: [process.env.RESEND_TO ?? 'hello@versebyversewithnate.us'],
|
||||||
|
|||||||
@@ -203,6 +203,24 @@ const FIELDS: Array<{ key: StringField; label: string; multiline?: boolean; sect
|
|||||||
{ key: 'platformAmazonUrl', label: 'Platform — Amazon Music URL', section: 'global' },
|
{ key: 'platformAmazonUrl', label: 'Platform — Amazon Music URL', section: 'global' },
|
||||||
{ key: 'platformFacebookUrl', label: 'Platform — Facebook URL', section: 'global' },
|
{ key: 'platformFacebookUrl', label: 'Platform — Facebook URL', section: 'global' },
|
||||||
{ key: 'platformCreatorUrl', label: 'Platform — Creator Profile URL', section: 'global' },
|
{ key: 'platformCreatorUrl', label: 'Platform — Creator Profile URL', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailSubject', label: 'Welcome Email — Subject', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailGreetingPrefix', label: 'Welcome Email — Greeting Prefix', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailIntro', label: 'Welcome Email — Intro Paragraph', multiline: true, section: 'global' },
|
||||||
|
{ key: 'welcomeEmailCurrentSeries', label: 'Welcome Email — Current Series Paragraph', multiline: true, section: 'global' },
|
||||||
|
{ key: 'welcomeEmailStartHereTitle', label: 'Welcome Email — Start Here Title', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailStartHereSummary', label: 'Welcome Email — Start Here Summary', multiline: true, section: 'global' },
|
||||||
|
{ key: 'welcomeEmailStartHereUrl', label: 'Welcome Email — Start Here URL', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailSpotifyUrl', label: 'Welcome Email — Spotify URL', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailAppleUrl', label: 'Welcome Email — Apple URL', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailAmazonUrl', label: 'Welcome Email — Amazon URL', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailWebsiteUrl', label: 'Welcome Email — Website URL', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailImageUrl', label: 'Welcome Email — Image URL', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailWhatToExpect1', label: 'Welcome Email — What to Expect 1', multiline: true, section: 'global' },
|
||||||
|
{ key: 'welcomeEmailWhatToExpect2', label: 'Welcome Email — What to Expect 2', multiline: true, section: 'global' },
|
||||||
|
{ key: 'welcomeEmailWhatToExpect3', label: 'Welcome Email — What to Expect 3', multiline: true, section: 'global' },
|
||||||
|
{ key: 'welcomeEmailScripture', label: 'Welcome Email — Scripture Text', multiline: true, section: 'global' },
|
||||||
|
{ key: 'welcomeEmailScriptureRef', label: 'Welcome Email — Scripture Reference', section: 'global' },
|
||||||
|
{ key: 'welcomeEmailSignoff', label: 'Welcome Email — Signoff HTML', multiline: true, section: 'global' },
|
||||||
]
|
]
|
||||||
|
|
||||||
export default function AdminPage({ content, onSave, onLogout }: Props) {
|
export default function AdminPage({ content, onSave, onLogout }: Props) {
|
||||||
@@ -1949,6 +1967,16 @@ export default function AdminPage({ content, onSave, onLogout }: Props) {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
<div className="admin-panel-subhead"><h3>Welcome Email</h3></div>
|
||||||
|
{FIELDS.filter(f => f.section === 'global' && f.key.startsWith('welcomeEmail')).map(({ key, label, multiline }) => (
|
||||||
|
<div className="admin-field" key={key}>
|
||||||
|
<label htmlFor={`field-${key}`}>{label}</label>
|
||||||
|
{multiline
|
||||||
|
? <textarea id={`field-${key}`} value={form[key] as string} onChange={e => handleChange(key, e.target.value)} rows={3} />
|
||||||
|
: <input id={`field-${key}`} type="text" value={form[key] as string} onChange={e => handleChange(key, e.target.value)} />}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
{renderSaveStatus()}
|
{renderSaveStatus()}
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -160,6 +160,25 @@ export interface SiteContent {
|
|||||||
platformAmazonUrl: string
|
platformAmazonUrl: string
|
||||||
platformFacebookUrl: string
|
platformFacebookUrl: string
|
||||||
platformCreatorUrl: string
|
platformCreatorUrl: string
|
||||||
|
// ── Welcome Email ──
|
||||||
|
welcomeEmailSubject: string
|
||||||
|
welcomeEmailGreetingPrefix: string
|
||||||
|
welcomeEmailIntro: string
|
||||||
|
welcomeEmailCurrentSeries: string
|
||||||
|
welcomeEmailStartHereTitle: string
|
||||||
|
welcomeEmailStartHereSummary: string
|
||||||
|
welcomeEmailStartHereUrl: string
|
||||||
|
welcomeEmailSpotifyUrl: string
|
||||||
|
welcomeEmailAppleUrl: string
|
||||||
|
welcomeEmailAmazonUrl: string
|
||||||
|
welcomeEmailWebsiteUrl: string
|
||||||
|
welcomeEmailImageUrl: string
|
||||||
|
welcomeEmailWhatToExpect1: string
|
||||||
|
welcomeEmailWhatToExpect2: string
|
||||||
|
welcomeEmailWhatToExpect3: string
|
||||||
|
welcomeEmailScripture: string
|
||||||
|
welcomeEmailScriptureRef: string
|
||||||
|
welcomeEmailSignoff: string
|
||||||
// ── Header ──
|
// ── Header ──
|
||||||
headerFollowLabel: string
|
headerFollowLabel: string
|
||||||
// ── Cookie banner ──
|
// ── Cookie banner ──
|
||||||
@@ -253,6 +272,24 @@ export const DEFAULTS: SiteContent = {
|
|||||||
platformAmazonUrl: '/amazon',
|
platformAmazonUrl: '/amazon',
|
||||||
platformFacebookUrl: 'https://facebook.com/versebyversewithnate',
|
platformFacebookUrl: 'https://facebook.com/versebyversewithnate',
|
||||||
platformCreatorUrl: 'https://creators.spotify.com/pod/profile/nmemmert/',
|
platformCreatorUrl: 'https://creators.spotify.com/pod/profile/nmemmert/',
|
||||||
|
welcomeEmailSubject: 'Welcome to Verse by Verse with Nate',
|
||||||
|
welcomeEmailGreetingPrefix: 'Glad you\'re here',
|
||||||
|
welcomeEmailIntro: 'Thanks for subscribing to Verse by Verse with Nate - a Bible teaching podcast where we slow down, dig into the text, and pull out the nuggets God has for us word by word.',
|
||||||
|
welcomeEmailCurrentSeries: 'Right now we\'re working through the book of Titus - a short letter packed with practical wisdom about grace, godliness, and what the Christian life looks like when it\'s rooted in sound doctrine.',
|
||||||
|
welcomeEmailStartHereTitle: 'Episode 1 - Introduction to Titus',
|
||||||
|
welcomeEmailStartHereSummary: 'Who wrote it, who received it, and why it still matters.',
|
||||||
|
welcomeEmailStartHereUrl: '/start-here',
|
||||||
|
welcomeEmailSpotifyUrl: '/spotify',
|
||||||
|
welcomeEmailAppleUrl: '/apple',
|
||||||
|
welcomeEmailAmazonUrl: '/amazon',
|
||||||
|
welcomeEmailWebsiteUrl: 'https://versebyversewithnate.us',
|
||||||
|
welcomeEmailImageUrl: '/images/podcast-art.jpeg',
|
||||||
|
welcomeEmailWhatToExpect1: 'Verse-by-verse teaching - we go slow and let the text speak for itself.',
|
||||||
|
welcomeEmailWhatToExpect2: 'Greek word studies - the kind that open up meaning without being a lecture.',
|
||||||
|
welcomeEmailWhatToExpect3: 'New episodes + study notes delivered right to your inbox.',
|
||||||
|
welcomeEmailScripture: 'For the grace of God has appeared, bringing salvation to all people.',
|
||||||
|
welcomeEmailScriptureRef: 'Titus 2:11 - BSB',
|
||||||
|
welcomeEmailSignoff: 'Grace and peace,\nNate',
|
||||||
headerFollowLabel: 'Follow on Spotify',
|
headerFollowLabel: 'Follow on Spotify',
|
||||||
cookieBannerText: 'We use optional analytics cookies to measure visits and location trends for site improvement.',
|
cookieBannerText: 'We use optional analytics cookies to measure visits and location trends for site improvement.',
|
||||||
customLinks: [],
|
customLinks: [],
|
||||||
|
|||||||
Reference in New Issue
Block a user