A project to filter content visually from stashdb.org, using multiple tags and performers.
  • TypeScript 66.1%
  • Go 21.8%
  • CSS 8.4%
  • Shell 1.7%
  • HTML 1%
  • Other 1%
Find a file
2026-03-31 16:59:56 -07:00
backend Initial commit 2026-03-31 16:59:56 -07:00
frontend Initial commit 2026-03-31 16:59:56 -07:00
stashbrowse Initial commit 2026-03-31 16:59:56 -07:00
.gitignore Initial commit 2026-03-31 16:59:56 -07:00
build.sh Initial commit 2026-03-31 16:59:56 -07:00
deploy.sh Initial commit 2026-03-31 16:59:56 -07:00
README.md Initial commit 2026-03-31 16:59:56 -07:00
stashbrowse.service Initial commit 2026-03-31 16:59:56 -07:00

stashbrowse

Browse StashDB by combining tags, performers, and studios to discover scenes and send them to Whisparr in one click.

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

  • A StashDB account and API key (Settings → API Key)
  • A running Whisparr instance with an API key

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 ..