Serve published decks from a trailing-slash URL so assets load
Build and Deploy Verso / deploy (push) Successful in 7m29s

A deck served at /p/:token (no trailing slash) made the browser resolve its
relative asset references (main_files/... CSS+JS) against /p/, 404ing them —
so the deck rendered as unstyled HTML with no reveal.js. Publish links now end
in a slash, and the bare /p/:token URL 301-redirects to /p/:token/, so relative
assets resolve under /p/:token/ and load correctly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
claude
2026-06-01 15:49:21 +00:00
parent eae5a0ebc7
commit 2cb81bd246
@@ -6,7 +6,9 @@ import SessionManager from '../Authentication/SessionManager.mjs'
import PublishedPresentationManager from './PublishedPresentationManager.mjs'
function _publicUrl(token) {
return `${Settings.siteUrl}/p/${token}`
// Trailing slash so the deck's relative asset paths (e.g. main_files/...)
// resolve under /p/:token/ rather than /p/.
return `${Settings.siteUrl}/p/${token}/`
}
function _serialize(record) {
@@ -63,6 +65,12 @@ async function serve(req, res) {
const record = await PublishedPresentationManager.promises.getByToken(token)
if (!record) return res.status(404).send('Presentation not found')
// Normalise the bare token URL to a trailing slash so the deck's relative
// asset references resolve under /p/:token/ instead of /p/.
if (!req.params.file && !req.path.endsWith('/')) {
return res.redirect(301, `/p/${encodeURIComponent(token)}/`)
}
if (
record.visibility === 'private' &&
!SessionManager.getLoggedInUserId(req.session)