diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..f01a6db --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ +## What and why + + + +## Checklist + +- [ ] `npm run typecheck` is clean +- [ ] `npm test` passes +- [ ] New logic has a test (vitest; mock node built-ins for platform code) +- [ ] If I added a key, I updated both `HELP_GROUPS` and `footerHints` in `src/ui/keymap.ts` +- [ ] If I added a `Store` field, I updated `makeStore` in `scripts/render-previews-impl.tsx` +- [ ] OS-touching code works on Windows, macOS, and Linux +- [ ] One concern, with a Conventional Commits title (`feat:` / `fix:` / `docs:` / `chore:`) + +New here? [CONTRIBUTING.md](../CONTRIBUTING.md) explains each of these with examples from real merged PRs. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..cec7ad2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Contributing to torlink + +torlink stays small on purpose. The best way in is to read the code you're about to touch, match how it already works, and keep your change tight. Three recent pull requests set the bar, and this guide points back at them throughout: + +- [#4](https://github.com/baairon/torlink/pull/4) gave the arrow keys spatial pane navigation without breaking a single existing shortcut. +- [#5](https://github.com/baairon/torlink/pull/5) turned a cryptic crash on old Node into a one-line "upgrade me" message. +- [#6](https://github.com/baairon/torlink/pull/6) added copy-magnet, cross-platform, with tests. + +None of them were big. All of them fit the grain. That's the whole idea. + +## Set up + +```sh +git clone https://github.com/baairon/torlink +cd torlink +npm install +npm run dev +``` + +`npm run dev` runs the live TUI through tsx, no build step. The README's [Contributing](README.md#contributing) section has the build variant if you want it. + +## Before you open a PR + +Run these and make sure they're clean: + +```sh +npm run typecheck # tsc --noEmit, zero errors +npm test # vitest, all green +``` + +Then check your change against the standards below. The pull request template walks you through the same list. + +## The standards + +### Match the existing grain + +Reuse what's there before you write something new. Cursor movement goes through `wrapStep` (`src/ui/move.ts`). Key hints live in the `Hint` / `HELP_GROUPS` / `footerHints` system (`src/ui/keymap.ts`). Shared app state is the `Store` interface (`src/ui/store.ts`). + +#4 is the model here: it added a whole navigation mode and still introduced no new state, it leaned on the existing `region` and `captureMode` flags and reused `wrapStep`. If you catch yourself adding a parallel way to do something the codebase already does, stop and use the one that's already there. + +### Stay additive, never break muscle memory + +People already have the current keys in their fingers. New behavior should layer on, not overwrite. #4 lit up the arrow keys (which did nothing before) while leaving tab, enter, esc, and every letter command exactly where they were. If your change retrains an existing key, it needs a real reason and a clear note in the PR. + +### Cross-platform or it doesn't ship + +torlink runs on Windows, macOS, and Linux, so anything that touches the OS branches all three. Look at `writeClipboard` in `src/util/clipboard.ts` from #6: powershell on win32, pbcopy on darwin, then wl-copy, xclip, xsel on linux. #5's `scripts/cli-entry.cjs` is the same instinct aimed at the Node runtime. "Works on my machine" is not the bar. + +### Fail soft, never crash + +When something the user can't control goes wrong, degrade gracefully and say so. #5 prints a friendly upgrade message and exits cleanly instead of letting old Node spit out a parse error. #6's `writeClipboard` returns `false` and surfaces a notice when no clipboard tool exists, it never throws. Reach for a clear message and a fallback before you reach for an exception. + +### Test the logic + +Non-trivial logic gets a vitest test. Pure functions are easy, see `src/util/format.test.ts`. For code that shells out or leans on a platform, mock the node built-in, see `src/util/clipboard.test.ts` from #6 mocking `node:child_process`. Run the suite with `npm test`. + +### Wire the UI surface, and keep it minimal + +torlink shows one contextual footer plus a `?` cheatsheet, never a wall of commands. Two rules when you add to it: + +- A new key means updating both halves of `src/ui/keymap.ts`: `HELP_GROUPS` (the `?` sheet) and `footerHints` (the footer). #6 did both for `y`. +- A new `Store` field means adding a matching entry to `makeStore` in `scripts/render-previews-impl.tsx`, or `npm run previews` (the README screenshots) breaks. #6's `copyMagnet` sits in there as a noop for exactly this reason. + +### Respect the calm theme + +torlink is pastel-violet and quiet. There is exactly one gradient, the wordmark sheen. Everything else is solid color. Please don't add a second gradient. + +## Commits and pull requests + +- Use [Conventional Commits](https://www.conventionalcommits.org) prefixes: `feat:`, `fix:`, `docs:`, `chore:`, `refactor:`. +- Say why, not just what. The diff already shows the what. +- One concern per pull request. Two unrelated ideas are two PRs. + +Thanks for helping keep torlink sharp. diff --git a/README.md b/README.md index b07e5d3..408dd51 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ A short, hand-picked list of trusted sources: Games are the only category that can run code, so they come from FitGirl alone, a repacker with a long, trusted track record; everything else is plain video and subtitles. If a source is down, the search carries on without it, and torlink tells you which one is offline. -## Local Development +## Contributing To run or work on torlink locally: @@ -66,6 +66,8 @@ To run or work on torlink locally: npx torlnk ``` +Before opening a PR, skim [CONTRIBUTING.md](CONTRIBUTING.md); it lays out the bar with examples from real merged PRs. + ## Privacy Your files stay on your disk, and nothing routes through a central server; torlink only talks to the torrent network directly. Once a download finishes it keeps seeding by default, sharing it back so the next person can find it just as easily. The network only works because people pass things along, and even a few minutes makes a real difference. If you'd rather not, opt out anytime: open the Seeding tab, press `p` to pause or stop any item, and press it again to pick it back up. Always your call.