From 2cb81bd246e80bb293b817be33e22bc9e2cb0875 Mon Sep 17 00:00:00 2001 From: claude Date: Mon, 1 Jun 2026 15:49:21 +0000 Subject: [PATCH] Serve published decks from a trailing-slash URL so assets load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../PublishedPresentationController.mjs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/services/web/app/src/Features/PublishedPresentation/PublishedPresentationController.mjs b/services/web/app/src/Features/PublishedPresentation/PublishedPresentationController.mjs index 8df698cd8d..3ae499bdac 100644 --- a/services/web/app/src/Features/PublishedPresentation/PublishedPresentationController.mjs +++ b/services/web/app/src/Features/PublishedPresentation/PublishedPresentationController.mjs @@ -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)