- TypeScript 66.1%
- Go 21.8%
- CSS 8.4%
- Shell 1.7%
- HTML 1%
- Other 1%
| backend | ||
| docs/screenshots | ||
| frontend | ||
| stashbrowse | ||
| .gitignore | ||
| build.sh | ||
| deploy.sh | ||
| LICENSE | ||
| README.md | ||
| stashbrowse.service | ||
stashbrowse
Browse StashDB by combining tags, performers, and studios to discover scenes and send them to Whisparr in one click.
License
This project is licensed under the GNU General Public License v3.0.
You are free to use, modify, and distribute this software, but any derivative works must also be released under the GPL v3. See the LICENSE file for full details.
Screenshots
Due to the NSFW nature of this project, these two screenshots are all I will publicly display.
Disclaimer
This project was primarily coded using Claude. I don't really know how to code, especially in go. However, I used Claude to bring my idea to life so others can audit and build off of it.
Features
- Search and combine include / exclude filters for tags, performers, and studios
- Paginated scene grid with thumbnails, duration, studio, and performer badges
- Add to Whisparr directly from the browse or scene detail view
- Favorites list persisted to disk
- In-memory caching — repeated queries are instant
- Single self-contained binary (frontend embedded at build time)
Prerequisites
Installation
Option A — download a release binary
Download the latest binary for your platform from the Releases page, make it executable, and place it somewhere on your PATH:
install -m 755 stashbrowse ~/.local/bin/stashbrowse
Option B — build from source
Requirements: Go 1.22+, Node.js 18+
git clone <repo-url>
cd stashbrowse
# Build frontend
cd stashbrowse
npm install
npm run build
cd ..
# Embed frontend and build binary
cd backend
cp -r ../stashbrowse/build/client/. ui/
go build -o stashbrowse .
install -m 755 stashbrowse ~/.local/bin/stashbrowse
cd ..
Configuration
Run the interactive setup wizard to create your config file:
stashbrowse init
This prompts for:
| Field | Description |
|---|---|
| Config file path | Defaults to ~/.config/stashbrowse/config.toml |
| Server port | Defaults to 8585 |
| StashDB API key | From stashdb.org user settings |
| Whisparr URL | e.g. http://localhost:6969 |
| Whisparr API key | From Whisparr → Settings → General |
| Quality profile ID | Numeric ID of the quality profile to use |
| Root folder | Where Whisparr stores media, e.g. /data/media/xxx |
The resulting config looks like:
[server]
port = 8585
[stashdb]
api_key = "your-stashdb-key"
endpoint = "https://stashdb.org/graphql"
[whisparr]
url = "http://localhost:6969"
api_key = "your-whisparr-key"
quality_profile_id = 8
root_folder = "/data/media/xxx"
To use a non-default config path:
stashbrowse init --config /path/to/config.toml
stashbrowse --config /path/to/config.toml
Running
stashbrowse # reads ~/.config/stashbrowse/config.toml
stashbrowse serve # same, explicit subcommand
stashbrowse version # print version
stashbrowse --help # show usage
Open http://localhost:8585 in your browser.
Process supervisors
stashbrowse runs in the foreground and exits cleanly on SIGTERM / SIGINT, making it compatible with any process supervisor.
systemd (user service)
A unit file is included in the repo as stashbrowse.service.
# Install
cp stashbrowse.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now stashbrowse
# Manage
systemctl --user status stashbrowse
systemctl --user restart stashbrowse
journalctl --user -u stashbrowse -f
The unit uses %h (home directory) and expects the binary at ~/.local/bin/stashbrowse and the config at ~/.config/stashbrowse/config.toml.
dinit (user service)
Create ~/.config/dinit.d/stashbrowse:
type = process
command = /home/<user>/.local/bin/stashbrowse
restart = true
logfile = /home/<user>/.local/share/stashbrowse/stashbrowse.log
dinitctl start stashbrowse
s6-overlay / s6
Create a service directory, e.g. ~/.config/s6/sv/stashbrowse/:
mkdir -p ~/.config/s6/sv/stashbrowse
cat > ~/.config/s6/sv/stashbrowse/run <<'EOF'
#!/bin/sh
exec ~/.local/bin/stashbrowse
EOF
chmod +x ~/.config/s6/sv/stashbrowse/run
Deploying to a remote host
deploy.sh builds the frontend, embeds it into the Go binary, and rsyncs the single binary to a remote host named thor (override with env vars):
./deploy.sh
# Overrides
THOR_USER=myuser THOR_HOST=myserver THOR_DEST=/opt/stashbrowse ./deploy.sh
On first deploy, SSH into the server and run stashbrowse init to create the config, then start the service.
Development
# Terminal 1 — backend API server
cd backend
go run . --config ../config.dev.toml # create this with `go run . init`
# Terminal 2 — frontend dev server with HMR
cd stashbrowse
npm run dev # http://localhost:5173 (proxies /api → :8585)
Frontend changes hot-reload instantly. Backend changes require restarting go run ..

