feat(website): serve an install script that picks brew or the release binary

curl -fsSL https://re-invention.nl/soulseek-rs/install.sh | sh replaces the
brew one-liner as the front-page command: it works on Linux without Homebrew
by downloading the latest release archive for the platform, verifying its
sha256 and installing to /usr/local/bin or ~/.local/bin. Windows still gets
pointed at the msvc zip. scripts/test-install.sh covers target detection,
the brew fast path, checksum failure and real installs over curl and wget.
This commit is contained in:
Michel de Graaf
2026-07-29 16:22:05 +02:00
parent d2d1558708
commit 78a608c4c3
5 changed files with 272 additions and 9 deletions
+2
View File
@@ -18,3 +18,5 @@ export const LINKS = {
export const VERSION = __APP_VERSION__
export const SITE_URL = 'https://re-invention.nl/soulseek-rs/'
export const INSTALL_CMD = `curl -fsSL ${SITE_URL}install.sh | sh`
+6 -5
View File
@@ -10,12 +10,12 @@ import { Cols, Eyebrow, Prose, Section, SectionHead, Wrap } from '@/components/u
import { OsIcon, type OsName } from '@/components/ui/os-icon'
import { Callout } from '@/components/ui/panel'
import { Terminal } from '@/components/ui/terminal'
import { LINKS } from '@/lib/links'
import { INSTALL_CMD, LINKS } from '@/lib/links'
import { cn } from '@/lib/utils'
const PLATFORMS: readonly { name: OsName; note: string; anchor: string }[] = [
{ name: 'macOS', note: 'brew or cargo', anchor: 'macos' },
{ name: 'Linux', note: 'cargo install', anchor: 'linux' },
{ name: 'macOS', note: 'script or brew', anchor: 'macos' },
{ name: 'Linux', note: 'script or cargo', anchor: 'linux' },
{ name: 'Windows', note: 'cargo or .exe', anchor: 'windows' },
]
@@ -154,7 +154,7 @@ const Hero = () => (
<Button href="/docs">Read the docs</Button>
<Button href={LINKS.gh}>GitHub</Button>
</div>
<CommandPill text="brew install michel/tap/soulseek-rs" />
<CommandPill text={INSTALL_CMD} />
</div>
</div>
@@ -327,9 +327,10 @@ const GetStarted = () => (
<Terminal
label="quick start"
lines={[
{ t: 'cmd', text: 'brew install michel/tap/soulseek-rs' },
{ t: 'cmd', text: INSTALL_CMD },
{ t: 'cmd', text: 'soulseek-rs' },
]}
wrap
/>
</Cols>
</Section>
+17 -4
View File
@@ -6,7 +6,7 @@ import { Cols, PageHead, Prose, Section, SectionHead } from '@/components/ui/lay
import { OsIcon, type OsName } from '@/components/ui/os-icon'
import { Callout } from '@/components/ui/panel'
import { Terminal, type TermLine } from '@/components/ui/terminal'
import { LINKS } from '@/lib/links'
import { INSTALL_CMD, LINKS, SITE_URL } from '@/lib/links'
const LIB_SRC = `use soulseek_rs::Client;
use std::time::Duration;
@@ -266,7 +266,18 @@ const Steps = () => (
<div className="flex flex-col gap-9">
<Step n={1} title="Install the client">
<p className="text-secondary">
One command per platform. Cargo needs a Rust toolchain from{' '}
One command on macOS and Linux. The script installs through Homebrew when you
have it; otherwise it downloads the latest release binary for your platform,
checks its sha256, and puts it on your PATH.
</p>
<Terminal lines={[{ t: 'cmd', text: INSTALL_CMD }]} wrap />
<p className="text-[13px] text-muted">
No curl? <Code>{`wget -qO- ${SITE_URL}install.sh | sh`}</Code> does the same.
Piping to a shell asks for trust; read the script first at{' '}
<ExtLink href={`${SITE_URL}install.sh`}>{`${SITE_URL}install.sh`}</ExtLink>.
</p>
<p className="text-secondary">
Or pick a route per platform. Cargo needs a Rust toolchain from{' '}
<ExtLink href={LINKS.rustup}>rustup.rs</ExtLink>; the other routes don&rsquo;t.
</p>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-3">
@@ -520,6 +531,8 @@ const Uninstall = () => (
{ t: 'cm', text: '# whichever way you installed it' },
{ t: 'cmd', text: 'brew uninstall soulseek-rs' },
{ t: 'cmd', text: 'cargo uninstall soulseek-rs' },
{ t: 'cm', text: '# script install without brew: the binary itself' },
{ t: 'cmd', text: 'rm -f /usr/local/bin/soulseek-rs ~/.local/bin/soulseek-rs' },
{ t: 'cm', text: '# brew only: drop the tap it came from' },
{ t: 'cmd', text: 'brew untap michel/tap' },
{ t: 'cm', text: '# config and state: searches, downloads, rooms,' },
@@ -560,8 +573,8 @@ const Uninstall = () => (
export const Install = () => (
<>
<PageHead eyebrow="install" title="Three ways in.">
One command with Homebrew or cargo. Build from source if you&rsquo;d rather. Or depend
on the library and write your own client.
One command with the install script, Homebrew or cargo. Build from source if
you&rsquo;d rather. Or depend on the library and write your own client.
</PageHead>
<Steps />
<Reachable />