- TypeScript 79%
- Svelte 17%
- Nix 2%
- JavaScript <1%
- CSS <1%
- 3 more languages <1%
Kinklist v3 #
Rate kinks privately, then share the result as a short link or an image. No accounts, no backend, no uploads: your list is saved in your browser and never leaves your device unless you share it.
A ground-up rewrite of Goctionni/kinklist-v2. Old v2
links (#<imgurId>) and v2 images still open. The specification is docs/spec.md;
deviations and non-obvious choices are in docs/decisions.md. Coding agents:
see AGENTS.md.
Features #
- Rate every kink per role (Self / Partner, Giving / Receiving, …) with an accessible color picker: mouse, touch (44 px targets) or keyboard (arrows, number keys). Comments per kink.
- Find with diacritic-insensitive search; Unrated dims what's done without hiding it; Has comment; collapse or expand categories.
- Edit the list: rename inline, add and delete (with undo), reorder by dragging or with the keyboard, edit roles, customize ratings with warnings for colors that colorblind people can't tell apart.
- Share from ⋯ → Share…:
- a link (
<site>#<data>): the whole list in compressed binary, ~40–180 characters for the default list. It lives in the URL fragment, which browsers never send to servers; - a PNG (light or dark, optional comment footnotes) with the list embedded, so the image can be imported again;
kinklist.json, or a Markdown summary for chats.
- a link (
- Import a link, a PNG or JSON (from the menu, or drop the file anywhere), including v2 data.
- Autosave on every change, undo/redo (Ctrl/Cmd+Z), light/dark/system theme without flashing, print stylesheet, and no network requests (except fetching the image of an old Imgur link).
Development #
Every tool comes from the Nix flake. You need Nix (with flakes) and direnv.
git clone https://git.hanna.lol/kinklist && cd kinklist
direnv allow # enters the dev shell, installs git hooks and node_modules
dev # Vite dev server on http://localhost:5173
Without direnv, use nix develop instead.
Commands (on PATH in the dev shell) #
| Command | What it does |
|---|---|
check |
Runs every quality gate (below). Run before each commit, and from CI. |
fmt |
Formats all files (Prettier + nixfmt). |
dev |
Vite dev server (extra args are passed to Vite). |
Finer-grained pnpm scripts: lint, typecheck, format:check, test, test:coverage, build,
budget, e2e.
Quality gates #
check fails on the first failing gate:
@playwright/testversion equals nixpkgs'playwright-driver(the browsers come from Nix).- Formatting: Prettier, nixfmt.
- Lint: ESLint (type-checked, zero warnings), statix, deadnix.
- Types:
svelte-check --fail-on-warnings. - Unit + component tests (Vitest) with coverage thresholds (
src/lib/**≥ 95% lines, statements, functions and ≥ 90% branches;src/**≥ 85% lines). - Production build and the initial-JS budget (≤ 80 kB gzip).
- End-to-end tests (Playwright: Chromium, Firefox, WebKit, Pixel 7, iPhone 14) against the build.
For CI: nix flake check and nix develop -c check cover everything; scripts/commit-msg.sh <file>
validates a commit message. nix flake check runs the sandboxable subset: js (format, lint, typecheck and unit tests in one
derivation), build, nix-lint, pre-commit (Nix hooks) and playwright-version. nix build produces the static site in result/.
After changing dependencies, update pnpmDeps.hash in nix/package.nix:
nix build fails with the new hash in its got: line.
Git hooks #
Installed automatically by the dev shell (via git-hooks.nix):
- pre-commit: Prettier, ESLint, svelte-check, nixfmt, statix, deadnix, and
vitest relatedon staged files. - commit-msg: the message must be exactly one line in
Conventional Commits format, with no body and no trailers,
e.g.
feat(ratings): add keyboard shortcuts. Seescripts/commit-msg.sh. - pre-push: the full
check.
Never bypass hooks with --no-verify.
Visual baselines #
tests/e2e/visual.spec.ts compares the main view and exported images (Chromium) against
committed screenshots in tests/e2e/__screenshots__/<platform>/. Fonts differ between operating
systems, so a platform without baselines skips these tests; create or refresh them deliberately
with pnpm exec playwright test tests/e2e/visual.spec.ts --update-snapshots.
Tests #
| Layer | Location | Runner |
|---|---|---|
| Unit | tests/unit/ |
Vitest (Node) |
| Component | tests/component/ |
Vitest + Testing Library |
| E2E | tests/e2e/ |
Playwright (needs build) |
| Fixtures | tests/fixtures/ |
shared test data |
All functionality needs a test that fails without it.
License #
MIT. Default content and the legacy image codec derive from kinklist-v2 by Goctionni; see
LICENSE.