diff --git a/public/salvation/index.html b/public/salvation/index.html
new file mode 100644
index 0000000..ff48184
--- /dev/null
+++ b/public/salvation/index.html
@@ -0,0 +1,899 @@
+
+
+
+
+
+Gospel Harmony — The Trial & Crucifixion
+
+
+
+
+
+
+
+
diff --git a/server/routes/public.js b/server/routes/public.js
index 3b6ab9e..15fc0be 100644
--- a/server/routes/public.js
+++ b/server/routes/public.js
@@ -1,4 +1,5 @@
import express from 'express'
+import path from 'node:path'
import { readFile } from 'node:fs/promises'
import { escapeHtml, escapeXml, injectSeoIntoHtml, normalizeSitemapPath } from '../helpers.js'
import {
@@ -15,6 +16,8 @@ import { DATA_FILE } from '../config.js'
import { sanitizeRedirectRules } from '../study-helpers.js'
export function register(app) {
+ const SALVATION_INDEX_FILE = path.join(DIST_DIR, 'salvation', 'index.html')
+
app.get('/robots.txt', async (_req, res) => {
let content = state.cachedSiteContent
if (!content) {
@@ -77,6 +80,13 @@ export function register(app) {
app.use('/images', express.static(PUBLIC_IMAGES_DIR))
app.use('/uploads', express.static(UPLOADS_DIR))
+ // Explicitly serve salvation page on both paths without relying on slash redirects.
+ app.get(['/salvation', '/salvation/'], (_req, res, next) => {
+ res.sendFile(SALVATION_INDEX_FILE, err => {
+ if (err) next()
+ })
+ })
+
// Social share stub for questions
app.get('/questions/share/:id', (req, res) => {
const id = req.params.id
diff --git a/src/main.tsx b/src/main.tsx
index ade9d64..2ba50d8 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -4,6 +4,12 @@ import { BrowserRouter } from 'react-router-dom'
import './index.css'
import App from './App.tsx'
+const SERVER_ONLY_PATHS = ['/salvation']
+if (SERVER_ONLY_PATHS.some(p => location.pathname === p || location.pathname === p + '/')) {
+ location.replace(location.href)
+ throw new Error('redirecting')
+}
+
createRoot(document.getElementById('root')!).render(