From fd7bab3050a8947d5a0ffd0e843cd69048ba6d97 Mon Sep 17 00:00:00 2001
From: Michel de Graaf
Date: Mon, 7 Sep 2026 17:07:11 +0200
Subject: [PATCH] docs: add a contributing guide and link it from the README
and site
Nothing in the repo said that pull requests go to develop rather than master,
or that release-plz reads the commit subject to pick the next version. Both
cost a first-time contributor a round trip.
CONTRIBUTING.md covers those, the three checks CI runs, and the fact that the
e2e suites skip without a soulfind server. The README and the community page
link to it, and it joins the footer's Project column.
---
CONTRIBUTING.md | 43 ++++++++++++++++++++++++
README.md | 6 ++++
website/src/components/layout/footer.tsx | 1 +
website/src/lib/links.ts | 1 +
website/src/pages/community.tsx | 5 +++
5 files changed, 56 insertions(+)
create mode 100644 CONTRIBUTING.md
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..a16944a
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,43 @@
+# Contributing
+
+Issues and pull requests are both welcome, and so is just saying what's missing.
+No contributor agreement, no template.
+
+## Pull requests
+
+Branch off `develop` and target `develop`. `master` only moves through a release
+PR.
+
+Write the subject as a
+[conventional commit](https://www.conventionalcommits.org), like
+`fix(lib): route on the full four-byte message code`. release-plz reads these to
+pick the next version and write the changelog. One change per pull request;
+small ones land fastest.
+
+Before you push:
+
+```bash
+cargo fmt --all
+cargo clippy --workspace --all-targets --all-features -- -D warnings
+cargo test
+```
+
+CI runs those on Linux, macOS and Windows, plus an end-to-end suite against a
+real [soulfind](https://github.com/soulfind-dev/soulfind) server. The e2e suites
+skip when no server is around, so `cargo test` stays green without one.
+[Development](./README.md#development) has the setup if you want to run them.
+
+AI-assisted changes are fine, and no need to say so. Keep the trailers out of
+the commit message: no `Co-Authored-By:` for a model, no session links.
+
+## Issues
+
+The command you ran, what you expected, and what happened is plenty.
+`RUST_LOG=trace` output helps. Don't worry about polishing it.
+
+Built something on `soulseek-rs-lib`? Open a PR adding it to the README, and
+reserve a client minor version in
+[#12](https://github.com/michel/soulseek-rs/issues/12) so it's identifiable on
+the network.
+
+Contributions are under MIT, like the rest of the project.
diff --git a/README.md b/README.md
index ee80220..86ed254 100644
--- a/README.md
+++ b/README.md
@@ -647,6 +647,12 @@ soulfind instead of skipping.
points `SOULFIND_BIN` at it, and runs both the library and CLI e2e suites
with `SOULSEEK_E2E_REQUIRED=1`, so a missing server fails instead of skipping.
+## Contributing
+
+Issues and pull requests both welcome. Branch off `develop`, keep the change
+small, and see [CONTRIBUTING.md](./CONTRIBUTING.md) for the commit convention
+and the checks CI runs.
+
## License
MIT. See [LICENSE](./LICENSE).
diff --git a/website/src/components/layout/footer.tsx b/website/src/components/layout/footer.tsx
index d6a856f..a82e19f 100644
--- a/website/src/components/layout/footer.tsx
+++ b/website/src/components/layout/footer.tsx
@@ -20,6 +20,7 @@ const COLUMNS: readonly FooterColumn[] = [
links: [
{ label: "GitHub", href: LINKS.gh },
{ label: "Issues", href: LINKS.issues },
+ { label: "Contributing", href: LINKS.contributing },
{ label: "Releases", href: LINKS.releases },
{ label: "Changelog", href: LINKS.changelog },
],
diff --git a/website/src/lib/links.ts b/website/src/lib/links.ts
index be69ec3..ca09fe0 100644
--- a/website/src/lib/links.ts
+++ b/website/src/lib/links.ts
@@ -3,6 +3,7 @@ export const LINKS = {
issues: 'https://github.com/michel/soulseek-rs/issues',
releases: 'https://github.com/michel/soulseek-rs/releases',
changelog: 'https://github.com/michel/soulseek-rs/blob/master/CHANGELOG.md',
+ contributing: 'https://github.com/michel/soulseek-rs/blob/master/CONTRIBUTING.md',
license: 'https://github.com/michel/soulseek-rs/blob/master/LICENSE',
cratesClient: 'https://crates.io/crates/soulseek-rs',
cratesLib: 'https://crates.io/crates/soulseek-rs-lib',
diff --git a/website/src/pages/community.tsx b/website/src/pages/community.tsx
index a70d2bc..08964d8 100644
--- a/website/src/pages/community.tsx
+++ b/website/src/pages/community.tsx
@@ -239,10 +239,15 @@ export const Community = () => {
open-source Soulseek server; run it locally to develop against a real protocol
implementation without touching the public network.
+
+ Pull requests go to develop; master only moves on a
+ release.
+