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:
@@ -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) => (
|
||||
|
||||
@@ -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: “mirror that peer’s FLAC
|
||||
folder”, “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
@@ -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 “find the 1998 pressing, lossless only”
|
||||
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: “find the 1998 pressing, lossless only” 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’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’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’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’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’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
|
||||
|
||||
@@ -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’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>
|
||||
|
||||
Reference in New Issue
Block a user