Files
paseo/packages/website/src/server-entry.ts
T
Mohamed Boudra ed4fc08f78 feat(website): replace the Cloud page with Paseo Hub
The Cloud page pitched a hosted multi-user product and collected emails
through a signup form. The Hub is a self-hosted service in private beta
and the only way in is a Discord DM, so the signup server function and
its webhook are deleted rather than repointed. /cloud now 301s to /hub
from the worker entry, which already owns the site's permanent path
redirects, so old links and search results keep working.

The homepage also drops split panels, service proxy, voice, and keyboard
shortcuts. They had turned the page into a feature list; it should show
what Paseo enables at a high level.

Brand and provider icons move into shared modules so the Hub page, the
site header, and the landing page each use one copy instead of three.
2026-08-03 14:08:59 +02:00

81 lines
2.4 KiB
TypeScript

import startEntry from "@tanstack/react-start/server-entry";
import { getAndroidVersionCode } from "~/android-version";
import { getDoc } from "~/docs";
import { getLatestAndroidVersion } from "~/latest-release";
import { buildLlmsTxt } from "~/llms";
const CANONICAL_HOST = "paseo.sh";
interface WebsiteEnv {
WEBSITE_CACHE?: KVNamespace;
}
function markdownResponse(body: string): Response {
return new Response(body, {
headers: {
"content-type": "text/markdown; charset=utf-8",
"cache-control": "public, max-age=300, s-maxage=300",
},
});
}
function plainTextResponse(body: string): Response {
return new Response(body, {
headers: {
"content-type": "text/plain; charset=utf-8",
"cache-control": "public, max-age=300, s-maxage=300",
},
});
}
function docSlugFromMarkdownPath(pathname: string): string | null {
if (pathname === "/docs.md") return "";
const match = pathname.match(/^\/docs\/(.+)\.md$/);
return match ? match[1] : null;
}
export default {
async fetch(request: Request, env: WebsiteEnv, context: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const isLocal = url.hostname === "localhost" || url.hostname === "127.0.0.1";
if (!isLocal && (url.hostname !== CANONICAL_HOST || url.protocol !== "https:")) {
url.protocol = "https:";
url.hostname = CANONICAL_HOST;
return Response.redirect(url.toString(), 301);
}
if (url.pathname === "/cloud" || url.pathname === "/cloud/") {
url.pathname = "/hub";
return Response.redirect(url.toString(), 301);
}
const altRedirectMatch = url.pathname.match(/^\/docs\/alternatives\/(.+?)\/?$/);
if (altRedirectMatch) {
url.pathname = `/alternatives/${altRedirectMatch[1]}`;
return Response.redirect(url.toString(), 301);
}
if (url.pathname === "/llms.txt") {
return markdownResponse(buildLlmsTxt());
}
if (url.pathname === "/android-version.txt") {
const version = await getLatestAndroidVersion({
cache: env.WEBSITE_CACHE ?? null,
waitUntil: (promise) => context.waitUntil(promise),
});
return plainTextResponse(`${getAndroidVersionCode(version)}\n`);
}
const slug = docSlugFromMarkdownPath(url.pathname);
if (slug !== null) {
const doc = getDoc(slug);
if (!doc) return new Response("Not found", { status: 404 });
return markdownResponse(doc.content);
}
return startEntry.fetch(request);
},
};