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.
81 lines
2.4 KiB
TypeScript
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);
|
|
},
|
|
};
|