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