feat(share): a link's address says what it opens

A video stays on /watch/, anything else is given out on /file/ and a folder on /folder/. The token
is the whole key, so every path opens every link and the links already sent keep working. The new
paths are kept out of search indexes like /watch/, boot the player alone, and the unfurl card calls a
file a file.
This commit is contained in:
2026-11-04 19:10:09 +01:00
parent 2bdf1ec76f
commit 4c09a22add
12 changed files with 233 additions and 26 deletions
+3 -3
View File
@@ -32,18 +32,18 @@ const proxy = {
"/healthz": proxyOpts,
};
// Two HTML entries: the app (index.html) and a public /watch/<token> link (watch.html), which loads
// Two HTML entries: the app (index.html) and a public share link (watch.html), which loads
// only the player page. In a build the backend picks the file by path (`main.py`); this does the
// same for `vite dev`, whose history fallback would otherwise hand /watch/… the app.
const watchEntry = (): Plugin => ({
name: "siftlode-watch-entry",
configureServer(server) {
server.middlewares.use((req, _res, next) => {
if (req.url?.startsWith("/watch/")) req.url = "/watch.html";
if (req.url && /^\/(?:watch|file|folder)\//.test(req.url)) req.url = "/watch.html";
next();
});
},
// The server answers every /watch/ link with the built watch.html, so a build without it would
// The server answers every share link with the built watch.html, so a build without it would
// ship a 500 for each one, and nothing downstream reads `dist` before prod does. Fail it here —
// after Vite's own HTML plugin has emitted the pages (`enforce: "post"`), or none is there yet.
enforce: "post",