import type { ReactNode } from "react"; import { createFileRoute, Link } from "@tanstack/react-router"; import { changelogLink } from "~/changelog"; import { CodeBlock } from "~/components/code-block"; import { SiteShell } from "~/components/site-shell"; import { pageMeta } from "~/meta"; import { downloadUrls, appStoreUrl, playStoreUrl, webAppUrl, AppleIcon, AndroidIcon, WindowsIcon, LinuxIcon, TerminalIcon, GlobeIcon, } from "~/downloads"; import { useBetaRelease, useRelease } from "~/routes/__root"; import "~/styles.css"; interface DownloadSearch { channel?: "beta"; } const STABLE_SEARCH: DownloadSearch = {}; const BETA_SEARCH: DownloadSearch = { channel: "beta" }; export const Route = createFileRoute("/download")({ validateSearch: (search: Record): DownloadSearch => search.channel === "beta" ? { channel: "beta" } : {}, head: () => pageMeta( "Download Paseo for macOS, Windows, Linux, iOS, and Android", "Install Paseo on every platform. Native desktop apps for macOS, Windows, and Linux. Mobile apps for iOS and Android. Self-hosted, open source, free to download.", "/download", ), component: Download, }); function Download() { const stable = useRelease(); const beta = useBetaRelease(); const { channel } = Route.useSearch(); // A ?channel=beta link outlives the beta it was shared for, so the release // decides the channel, not the URL. const activeBeta = channel === "beta" ? beta : null; const onBeta = activeBeta !== null; const release = activeBeta ?? stable; const { version } = release; const urls = downloadUrls(release); return (

Download

v{version} · What's new

{beta && }
{onBeta && } {/* Desktop */}

Desktop

Recommended, bundles everything you need

{!onBeta && ( brew install --cask paseo )} {urls.windowsExeArm64 && }
{/* Mobile */}

Mobile

{!onBeta && } {!onBeta && ( )}
{/* Web */} {!onBeta && (

Web

Connect to a server from any browser

)} {/* Server */}

Server

Run the Paseo server anywhere, connect from any client

{onBeta ? "npm install -g @getpaseo/cli@beta && paseo" : "npm install -g @getpaseo/cli && paseo"} {onBeta ? `nix run github:getpaseo/paseo/v${version}` : "nix run github:getpaseo/paseo"}

All releases are available on{" "} GitHub .

); } function ChannelSwitch({ onBeta }: { onBeta: boolean }) { return (
); } function ChannelOption({ label, active, search, }: { label: string; active: boolean; search: DownloadSearch; }) { return ( {label} ); } function BetaNotice() { return (

Beta builds ship ahead of stable and can break.

Already running the desktop app? Set{" "} Settings → Release channel → Beta and it updates itself from here on.

); } function PlatformRow({ icon: Icon, label, children, }: { icon: (props: React.SVGProps) => ReactNode; label: string; children: ReactNode; }) { return (
{label}
{children}
); } function PillGroup({ children }: { children: ReactNode }) { return
{children}
; } function DownloadPill({ href, label, external, }: { href: string; label: string; external?: boolean; }) { return ( {label} {external && ( )} ); } function MonitorIcon(props: React.SVGProps) { return ( ); } function PhoneIcon(props: React.SVGProps) { return ( ); }