style(website): cut the padding from the page copy

Remove three cross-page duplications: the "what --help cannot say" list
appeared on both home and docs, the config precedence rule twice on
install, and the soulfind link twice in adjacent community paragraphs.

Drop the em dashes, the adverbs, and the rhetorical triads while there.
This commit is contained in:
Michel de Graaf
2026-07-26 11:41:48 +02:00
parent d2f3dd13d7
commit abf83fa30a
4 changed files with 57 additions and 78 deletions
+6 -17
View File
@@ -50,7 +50,7 @@ const CITIZENSHIP = [
title: 'Share, and share real files', title: 'Share, and share real files',
body: ( body: (
<> <>
Point <code>shares add</code> at the collection you actually listen to. Full albums, Point <code>shares add</code> at the collection you listen to. Full albums,
honest bitrates, nothing transcoded up from a lossy source and relabelled. honest bitrates, nothing transcoded up from a lossy source and relabelled.
</> </>
), ),
@@ -146,20 +146,10 @@ export const Community = () => {
> >
soulfind soulfind
</a>{' '} </a>{' '}
run in CI, so a green checkmark means it genuinely built and talked to a run in CI, so a green checkmark means it built and talked to a server.
server.
</p> </p>
<p> <p>
That server is{' '} soulfind is an open-source Soulseek server. Run it locally and you develop
<a
href={LINKS.soulfind}
target="_blank"
rel="noopener noreferrer"
className="text-link hover:text-link-hover"
>
soulfind-dev/soulfind
</a>
, an open-source Soulseek server. Run it locally and you can develop and test
against a real protocol implementation without touching the public network. against a real protocol implementation without touching the public network.
</p> </p>
<div className="mt-1 flex flex-wrap gap-2 sm:gap-3"> <div className="mt-1 flex flex-wrap gap-2 sm:gap-3">
@@ -187,10 +177,9 @@ export const Community = () => {
eyebrow="being a good member" eyebrow="being a good member"
title="The network is other people's hard drives." title="The network is other people's hard drives."
> >
Soulseek is a gem for music enthusiasts. Decades of records, live sets, and Decades of records, live sets, and pressings that never made it anywhere else,
pressings that never made it anywhere else, kept online by people who care about kept online by people who care about them. None of this is enforced. It is just
them. It works because someone left their collection up for you. None of this is how the network stays worth using.
enforced. It is just how the network stays worth using.
</SectionHead> </SectionHead>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2"> <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
{CITIZENSHIP.map((item) => ( {CITIZENSHIP.map((item) => (
+9 -11
View File
@@ -97,13 +97,13 @@ export const Docs = () => {
/> />
<Prose> <Prose>
<p> <p>
On first run soulseek-rs shows a login screen: sign in with an existing On first run you get a login screen: sign in with an existing Soulseek
Soulseek account or register a new one, right in the TUI. Your password is account or register a new one. Your password goes to the OS keychain, not a
stored in the OS keychain, not in plain text. plain-text file.
</p> </p>
<p> <p>
Downloads land in a conventional folder by default, and your TUI state Downloads land in a conventional folder, and TUI state (searches, downloads,
(searches, downloads, rooms) is saved and restored across restarts. rooms) is restored across restarts.
</p> </p>
</Prose> </Prose>
</Cols> </Cols>
@@ -202,7 +202,7 @@ export const Docs = () => {
<Callout title="give it to your agent"> <Callout title="give it to your agent">
<p> <p>
<Code>soulseek-rs skills install</Code> writes a <Code>SKILL.md</Code> into <Code>soulseek-rs skills install</Code> writes a <Code>SKILL.md</Code> into
every coding agent on the machine — Claude Code and opencode today,{' '} every coding agent on the machine: Claude Code and opencode today,{' '}
<Code>--dir</Code> for anything else. After it lands you describe the <Code>--dir</Code> for anything else. After it lands you describe the
outcome instead of the pipeline: &ldquo;mirror that peer&rsquo;s FLAC outcome instead of the pipeline: &ldquo;mirror that peer&rsquo;s FLAC
folder&rdquo;, &ldquo;watch this room for an hour and save anything folder&rdquo;, &ldquo;watch this room for an hour and save anything
@@ -210,9 +210,7 @@ export const Docs = () => {
</p> </p>
<p> <p>
It carries what <Code>--help</Code> cannot: the JSON keys of every record, It carries what <Code>--help</Code> cannot: the JSON keys of every record,
that exit 4 means widen the query rather than retry it, that remote paths go and what each exit code means. Rerun it after an upgrade;{' '}
back byte-identical, and that <Code>--follow</Code> never returns so an agent
passes <Code>--duration</Code>. Run it again after an upgrade to update it;{' '}
<Code>skills uninstall</Code> takes it back out. <Code>skills uninstall</Code> takes it back out.
</p> </p>
</Callout> </Callout>
@@ -233,8 +231,8 @@ export const Docs = () => {
<Cols center className="gap-6"> <Cols center className="gap-6">
<Prose> <Prose>
<p> <p>
Deeper docs live where they stay current: the full README on GitHub, and the The README on GitHub and the library API reference on docs.rs stay current
generated API reference for the library on docs.rs. with the code.
</p> </p>
</Prose> </Prose>
<div className="flex flex-wrap gap-2 sm:gap-3"> <div className="flex flex-wrap gap-2 sm:gap-3">
+17 -22
View File
@@ -27,10 +27,10 @@ const FEATURES = [
cmd: 'soulseek-rs skills install', cmd: 'soulseek-rs skills install',
body: ( body: (
<> <>
Run it once and asking beats scripting: your agent knows the record shapes, the Run it once and your agent knows the record shapes, the exit codes, and the
exit codes, and the filters, so &ldquo;find the 1998 pressing, lossless only&rdquo; filters: &ldquo;find the 1998 pressing, lossless only&rdquo; becomes a pipeline it
becomes a pipeline it writes itself. No MCP server, no wrapper — the skill ships writes itself. No MCP server, no wrapper. The skill ships in the binary and finds
inside the binary and finds Claude Code and opencode on its own. Claude Code and opencode on its own.
</> </>
), ),
}, },
@@ -205,16 +205,15 @@ export const Home = () => {
</p> </p>
<p> <p>
soulseek-rs speaks that protocol. It&rsquo;s a third-party client, not the soulseek-rs speaks that protocol. It&rsquo;s a third-party client, not the
official app, and not affiliated with the Soulseek project. It shares, official app. It shares, browses, and does rooms and private messages,
browses, and does rooms and private messages, because a client that only because a client that only downloads takes without giving anything back.
downloads takes from the network without giving anything back.
</p> </p>
</Prose> </Prose>
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
<Callout title="build your own"> <Callout title="build your own">
<p> <p>
Reach for <Code>soulseek-rs-lib</Code> to build a custom client or an agent Reach for <Code>soulseek-rs-lib</Code> to build a custom client or an agent
on the protocol directly.{' '} on the protocol.{' '}
<Link to="/install" className="text-link hover:text-link-hover"> <Link to="/install" className="text-link hover:text-link-hover">
Use the library Use the library
</Link> </Link>
@@ -224,8 +223,8 @@ export const Home = () => {
<p> <p>
Every command runs as a one-off from the shell. Point cron, a script, or an Every command runs as a one-off from the shell. Point cron, a script, or an
agent at them and read JSON records back off stdout. No daemon, no API to agent at them and read JSON records back off stdout. No daemon, no API to
stand up — and <Code>skills install</Code> teaches the agent the surface stand up. <Code>skills install</Code> teaches the agent the surface for
for you.{' '} you.{' '}
<Link to="/docs" className="text-link hover:text-link-hover"> <Link to="/docs" className="text-link hover:text-link-hover">
See the commands See the commands
</Link> </Link>
@@ -238,8 +237,7 @@ export const Home = () => {
<Section id="features"> <Section id="features">
<SectionHead eyebrow="features" title="What it does."> <SectionHead eyebrow="features" title="What it does.">
Everything happens in the TUI, and every command also runs as a one-off from the Everything happens in the TUI, and every command also runs as a one-off from the
shell, so the same client works for scripting, cron jobs, and agents driving it shell.
programmatically.
</SectionHead> </SectionHead>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3"> <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{FEATURES.map((feature, i) => ( {FEATURES.map((feature, i) => (
@@ -259,8 +257,8 @@ export const Home = () => {
<Section id="agents"> <Section id="agents">
<SectionHead eyebrow="agent native" title="Ask for the record. Skip the pipeline."> <SectionHead eyebrow="agent native" title="Ask for the record. Skip the pipeline.">
A CLI an agent can drive is not the same as a CLI an agent knows how to drive. An agent can run any CLI. <Code>skills install</Code> teaches it to run this one
<Code>skills install</Code> closes that gap in one command. well.
</SectionHead> </SectionHead>
<img <img
src={`${import.meta.env.BASE_URL}agent-demo.svg`} src={`${import.meta.env.BASE_URL}agent-demo.svg`}
@@ -270,17 +268,14 @@ export const Home = () => {
<Prose className="mt-11 max-w-[660px]"> <Prose className="mt-11 max-w-[660px]">
<p> <p>
<Code>--help</Code> lists flags. It cannot say which JSON keys a record <Code>--help</Code> lists flags. It cannot say which JSON keys a record
carries, that exit 4 means widen the query rather than retry it, that a carries, or that exit 4 means widen the query rather than retry it. An agent
remote path is backslash-separated and has to go back byte-identical, or without that guesses, and guessing against a stranger&rsquo;s file server
that <Code>--follow</Code> never returns so an agent passes{' '} hangs the job.
<Code>--duration</Code>. An agent without that guesses, and guessing against
a stranger&rsquo;s file server hangs the job.
</p> </p>
<p> <p>
<Code>skills install</Code> fills that in. The requests stop being pipelines <Code>skills install</Code> fills that in. The requests stop being pipelines
you write: mirror a peer&rsquo;s FLAC folder overnight, watch a room and save you write: mirror a peer&rsquo;s FLAC folder overnight, or check whether a
anything that mentions a label, check whether a user is worth queueing behind user is worth queueing behind before a 2 GB transfer.
before a 2 GB transfer.
</p> </p>
<p> <p>
It stays a CLI: no daemon, no MCP server, no API key. Upgrading the binary It stays a CLI: no daemon, no MCP server, no API key. Upgrading the binary
+25 -28
View File
@@ -58,8 +58,8 @@ const INSTALLS: readonly InstallRoute[] = [
], ],
alt: ( alt: (
<> <>
A prebuilt binary for both Apple silicon and Intel, so no Rust toolchain. With one A prebuilt binary for Apple silicon and Intel, no Rust toolchain needed. With a
installed, <Code>cargo install soulseek-rs</Code> builds it from crates.io instead. toolchain, <Code>cargo install soulseek-rs</Code> builds from crates.io instead.
</> </>
), ),
}, },
@@ -116,7 +116,7 @@ const PLATFORMS: readonly PlatformNote[] = [
config: '~/.config/soulseek-rs/config.toml', config: '~/.config/soulseek-rs/config.toml',
state: '~/.local/share/soulseek-rs/state', state: '~/.local/share/soulseek-rs/state',
downloads: '~/Downloads/Soulseek', downloads: '~/Downloads/Soulseek',
note: 'macOS deliberately follows the XDG layout rather than Application Support, so config sits beside your other dotfile config.', note: 'Follows the XDG layout rather than Application Support.',
}, },
{ {
id: 'linux', id: 'linux',
@@ -185,9 +185,9 @@ const SETTINGS: readonly Setting[] = [
fallback: 'the download folder', fallback: 'the download folder',
body: ( body: (
<> <>
Folders offered to the network, as a list. An explicitly empty list shares Folders offered to the network. An empty list shares nothing.{' '}
nothing. <code>shared_dir</code> is the older single-folder spelling and still <code>shares add</code> writes this; the older <code>shared_dir</code> spelling
reads; <code>shares add</code> writes the list form. still reads.
</> </>
), ),
}, },
@@ -388,9 +388,10 @@ export const Install = () => {
</p> </p>
<p> <p>
The port is your <Code>--listener-port</Code> (env{' '} The port is your <Code>--listener-port</Code> (env{' '}
<Code>SOULSEEK_LISTENER_PORT</Code>, default <Code>2234</Code>); it&rsquo;s <Code>SOULSEEK_LISTENER_PORT</Code>, default <Code>2234</Code>); soulseek-rs
renewed automatically and removed on exit. Pass <Code>--no-listener</Code> to renews it while it runs and removes it on exit. Pass{' '}
turn it off. Check your own network without launching the client: <Code>--no-listener</Code> to turn it off. Check your own network without
launching the client:
</p> </p>
<div className="mt-4"> <div className="mt-4">
<Terminal <Terminal
@@ -460,27 +461,24 @@ export const Install = () => {
<Cols start className="mt-7"> <Cols start className="mt-7">
<FeatureCard title="Secrets"> <FeatureCard title="Secrets">
Your password goes to the OS keychain, never a plain-text file. If you would Your password goes to the OS keychain, never a plain-text file. Point{' '}
rather it never be stored at all, have <code>password_cmd</code> shell out to <code>password_cmd</code> at your own password manager and it is never stored
your own password manager and print it on demand. For CI and containers,{' '} at all. For CI and containers,{' '}
<code>--password-stdin</code> reads it off a pipe so it never reaches{' '} <code>--password-stdin</code> reads it off a pipe so it never reaches{' '}
<code>ps</code> or the environment. <code>ps</code> or the environment.
</FeatureCard> </FeatureCard>
<FeatureCard title="Settings and state"> <FeatureCard title="Settings and state">
<code>config.toml</code> is layered: flags beat environment variables, which <code>config.toml</code> is layered: flags beat environment variables, which
beat the file, which beats the defaults. <code>config get</code> and{' '} beat the file, which beats the defaults. State (searches, downloads, rooms) is
<code>config set</code> read and write that file without opening an editor. versioned JSON and restores on restart; soulseek-rs sets anything unreadable
State (searches, downloads, rooms) is versioned JSON and restores on restart; aside as <code>.bak</code> rather than overwriting it.
anything unreadable is set aside as <code>.bak</code> instead of being
overwritten.
</FeatureCard> </FeatureCard>
</Cols> </Cols>
</Section> </Section>
<Section id="config"> <Section id="config">
<SectionHead eyebrow="config.toml" title="Nine settings, all optional."> <SectionHead eyebrow="config.toml" title="Nine settings, all optional.">
Every one has a working default, so an empty file — or no file — is valid. Flags Every one has a working default, so an empty file, or no file at all, is valid.{' '}
beat environment variables, which beat this file, which beats the defaults.{' '}
<Code>config list</Code> prints the effective value of each. <Code>config list</Code> prints the effective value of each.
</SectionHead> </SectionHead>
<Cols start> <Cols start>
@@ -509,10 +507,10 @@ export const Install = () => {
<Callout title="editing it without an editor"> <Callout title="editing it without an editor">
<p> <p>
<Code>config path</Code> prints the file in use, <Code>config get</Code>{' '} <Code>config path</Code> prints the file in use, <Code>config get</Code>{' '}
reads one setting and <Code>config set</Code> writes one. Unknown keys are reads one setting and <Code>config set</Code> writes one. It rejects
rejected rather than silently ignored, so a typo fails loudly instead of unknown keys, so a typo fails instead of doing nothing.{' '}
quietly doing nothing. <Code>--no-config</Code> ignores the file entirely <Code>--no-config</Code> ignores the file entirely and{' '}
and <Code>--config FILE</Code> points at another one. <Code>--config FILE</Code> points at another one.
</p> </p>
</Callout> </Callout>
</div> </div>
@@ -521,9 +519,8 @@ export const Install = () => {
<Section band> <Section band>
<SectionHead eyebrow="uninstall" title="Removing it completely."> <SectionHead eyebrow="uninstall" title="Removing it completely.">
Three things exist on disk: the binary, the config, and the state. Nothing else is Three things exist on disk: the binary, the config, and the state. Nothing else,
written unless you pointed <Code>--log-file</Code> at a file, and there is no unless you point <Code>--log-file</Code> somewhere. No telemetry to opt out of.
telemetry to opt out of.
</SectionHead> </SectionHead>
<Cols start> <Cols start>
<Terminal <Terminal
@@ -555,8 +552,8 @@ export const Install = () => {
<div className="mt-5"> <div className="mt-5">
<Callout className="bg-raised" title="two things it will not touch"> <Callout className="bg-raised" title="two things it will not touch">
<p> <p>
Your downloads and your shared directories are yours: they stay exactly where Your downloads and your shared directories are yours: they stay where they
they are. On macOS, delete the keychain entry for <code>soulseek-rs</code> in are. On macOS, delete the keychain entry for <code>soulseek-rs</code> in
Keychain Access if you saved a password. Keychain Access if you saved a password.
</p> </p>
</Callout> </Callout>