Pick one option together.
Rank options (homes, cars, holiday spots, anything) when several people need to agree. Everyone says how much each point matters to them and rates every option. should-we weights each person's ratings by their own priorities and combines everyone into one ranking.
- No accounts. Start a decision, share its link. Whoever has the link picks a name and takes part.
- Phone first. Installable as an app ("Add to Home Screen"), saves as you tap, refreshes every few seconds.
- Self-hosted. One small Docker image with no settings, run the same way as Splitwiz.
Version 2 is a rebuild. The Python version is release v1.0.0; see CHANGELOG.md.
On any machine with Docker (a NAS, a mini PC, your laptop):
mkdir -p should-we/pb_data && cd should-we
curl -O https://raw.githubusercontent.com/selfhostit/should-we/main/docker-compose.yml
docker compose up -dIf port 8091 is taken ("port is already allocated"), put a free port in a
.env file next to docker-compose.yml, for example SHOULD_WE_PORT=8095,
and your time zone too (TZ=Europe/Athens; the default is Europe/Brussels).
Open http://127.0.0.1:8091, type what you're deciding and what matters, then tap Share and send the link. Everyone picks a name, taps how much each point matters, and rates the options. Results shows the ranking.
To let friends join from their phones anywhere, put it behind HTTPS (see On a Synology NAS).
- Start a decision: what you're deciding, what matters (price, location, …) and your name. Or pick an example.
- Share the link. People who open it see who invited them and what they'll be asked to do, then pick a name.
- Say what matters: Don't care, A little, Important or Must-have, per point.
- Add and rate options, 0 (bad) to 5 (great) on each point.
- Results: each person's score for an option is their ratings averaged by their priorities; the option's score is the average over everyone who rated it. Big disagreements are marked "opinions split".
Anyone in the decision can edit the list of what matters later. For a choice
that comes back (job hunting, holidays), use Start a new decision like this
one at the bottom of a decision: it copies the points and your priorities.
Everything is saved in pb_data on your server.
The Quickstart commands are all it takes. Put it behind your reverse proxy with HTTPS (Caddy, nginx, DSM, …) to
share links outside your home. Data lives in pb_data/ next to the compose
file.
- Container Manager: install it from Package Center if it is missing.
- Folder: in File Station, create
docker/should-we/pb_data. - Project: Container Manager > Project > Create, name
should-we, path/volume1/docker/should-we, and pastedocker-compose.yml. Start it. - Certificate: Control Panel > Security > Certificate > Add > Let's
Encrypt, for
should-we.<your-name>.synology.me(your Synology DDNS name withshould-we.in front). If you already have a certificate for<your-name>.synology.mewith "Include wildcard" ticked, it covers this too. No router changes are needed when port 443 already reaches the NAS (for example for Splitwiz). - Reverse proxy: Control Panel > Login Portal > Advanced > Reverse
Proxy > Create. Source: HTTPS,
should-we.<your-name>.synology.me, port 443. Destination: HTTP,localhost, port 8091. Then assign the certificate to it under Certificate > Settings. - Open
https://should-we.<your-name>.synology.meand start a decision.
Pull the new image and recreate the container (Container Manager: Image >
Update, then Project > Action > Build; anywhere else:
docker compose pull && docker compose up -d). Or build on your computer
and push straight to the NAS:
scripts/deploy-to-nas.sh you@your-nas-addressImages: :2 follows the newest 2.x release, :2.1.0 is that exact release and :edge
follows main. Every image has a signed attestation of the workflow and commit that built
it; check one with the GitHub CLI:
gh attestation verify oci://ghcr.io/selfhostit/should-we:2 --repo selfhostit/should-we.
Copy the pb_data folder (on a Synology: add /volume1/docker/should-we
to a Hyper Backup task). Optional: create an admin with
docker exec -it should-we /app/should-we superuser upsert you@example.com 'password' --dir=/app/pb_data
to browse the data at /_/ and schedule PocketBase's own backups.
# backend (needs Go 1.27+)
cd backend
go run . serve # http://127.0.0.1:8090
# web app with hot reload (needs Node 22+), in another terminal
cd web
npm install
npm run dev # proxies /api to :8090Tests: cd backend && go test ./... and cd web && npm test && npm run check.
Bump version in web/package.json, add a CHANGELOG entry, merge, then
publish a GitHub release tagged vX.Y.Z. CI publishes the matching image
tags (and moves :2 and :latest), and attests them.
| Part | Choice |
|---|---|
| Backend | PocketBase used as a Go framework (backend/), SQLite database |
| Rules and scoring | backend/decide, unit tested |
| API | backend/app/routes.go: a decision's id is its share link; your browser keeps a token proving which person you are |
| Web app | Svelte 5 + Vite + Tailwind (web/), installable PWA |
| Packaging | One Docker image (Dockerfile), published to ghcr.io/selfhostit/should-we by GitHub Actions |
- Not on the internet: the container listens on
127.0.0.1only; reach it through Tailscale or your own reverse proxy with HTTPS. - Locked-down container: it drops every Linux capability and can't gain new ones.
- Sign-ins and new decisions are rate limited, and the web app sends a Content Security Policy
(
backend/app/headers.go). - Versioned releases with a changelog; the compose file follows the
2major version, which only moves on a release, so an update never jumps to a breaking one or to unreleased work. Every image has a signed attestation of the commit that built it. - Tested on every change in CI, with Actions pinned to commit hashes and every push scanned for committed secrets (gitleaks).
- No analytics or tracking. The data stays in
pb_dataon your machine.
Found a security problem? Please write to kalfasyan@pm.me rather than opening an issue (security policy). Security and privacy covers every selfhostit app: what protects an install, what you are trusting and what is not done yet.
If should-we helps you decide, you can buy me a coffee ☕

