Torres 8367e2b7c8 deploy/Dockerfile (python:3.13-slim app contract) + README run/develop section
- Dockerfile: 3.13-slim, pip install requirements.txt, copy app/, EXPOSE
  8000, serves /data/bike-tinder.sqlite3 + /data/img on 0.0.0.0:8000
  (compose/systemd/tailscale stay with the parent)
- README: status line now reflects Phase 2; added Run & develop (venv,
  importer, imgfetch incl. --limit, serve, selfcheck, deck CLI, route map)
2026-11-10 21:23:48 -04:00

Bike-Tinder

A private, Tinder-style web app for browsing the motorcycle market: swipe real listings (like / nope / maybe), see everything on one editable list, and let the deck learn your taste. Built for Glenn; runs on the Rotarran, published to the tailnet only.

Status: Phase 2 (production build) — FastAPI backend + no-build PWA shipped on dev (2026-11-10): migrations, API with cursor-paginated deck, swipe persistence, real list/matches screens, image mirror, PWA shell. Deployment (podman stack) is Phase 4 — not started.

How it works

[single-source crawler] → [nightly importer] → [app DB] → [API + PWA deck] → Glenn's thumb
                                                                  ↓
                                                        [swipe history] → [ranking]
  • Crawl — Kijiji (NS + NB; decided 2026-11-10 — see docs/SOURCES.md) is swept nightly by the existing hunt crawler; a script-only importer folds the results in. No LLM involved, zero token cost.
  • Import — the importer upserts the source's catalog into the app database: new listings appear, changes update, vanished listings retire after repeated misses (never a blocked page, never a guess).
  • Deck — a Tinder-like PWA: card stack, drag to swipe, big buttons. Like / Nope / Maybe. "It's a match" moment when you like something.
  • List & edit — every entry in one table; re-file any call later (a nope can become a like).
  • Ranking — cold start uses the hunt's rubric score; a cheap, fully explainable swipe-boost lands first (v1.x), then a small learned model (Phase 3, retrained nightly) orders the deck by your taste. "Because you liked X" chips, never a black box.

Docs

Branches

  • main — stable trunk (docs + verified code); the default branch.
  • dev — active development; build work lands here first.
  • release — deployable cuts; the Rotarran stack tracks this branch.

Run & develop

Everything runs from the repo root (Python 3.13+, stdlib where possible).

# one-time setup
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt   # fastapi + uvicorn (+ httpx for tests)

# import the hunt state into the DB (idempotent; safe to re-run any time)
python3 -m app.importer --state-dir ~/.hermes/scripts/motorcycle-hunt.d --db data/bike-tinder.sqlite3

# mirror card images into data/img/ (polite: ~1 req/s, skip-existing, resumable)
.venv/bin/python -m app.imgfetch --db data/bike-tinder.sqlite3
.venv/bin/python -m app.imgfetch --limit 15   # small test runs

# serve the app (127.0.0.1:9453 by default)
.venv/bin/python -m app.serve --db data/bike-tinder.sqlite3 --port 9453

# self-check: 8 P1 spine checks + 6 P2 API checks (on a temp DB copy)
.venv/bin/python -m app.selfcheck

# proof CLI: ranked deck + counts (read-only)
python3 -m app.deck --db data/bike-tinder.sqlite3 --top 15

Key routes: / (PWA), /api/health, /api/stats, /api/deck?limit=&cursor=, POST /api/swipe / DELETE /api/swipe/{id}, /api/list?decision=&sort=&q=&limit=&offset=, /api/listing/{id}, POST /api/import, POST /api/badge/seen, /img/{id} (cached file → 302 source CDN → 404 placeholder). Full contract: docs/UI-SPEC.md + the task brief.

data/ and .venv/ are gitignored — the DB, image mirror and venv are local state.

Deployment (planned)

A small podman compose stack on the Rotarran under /var/mnt/DATA/podman-stacks/bike-tinder/, its own systemd user unit (Delegate=yes), SQLite database. The stack ships its own Tailscale node (sidecar container — no host-tailnet coupling) and serves the app privately at https://biketinder.tailf35a34.ts.net. Single user; reachable only from Glenn's own devices.

Crew

  • Glenn — owner; the thumb that swipes.
  • Alex — resident agent; architecture, orchestration, docs.
  • Torres — engineer; builds and maintains this repo.
Description
Tinder. For motorcycles.
Readme 1 MiB
2026-11-13 14:29:08 -04:00
Languages
Python 74.7%
HTML 24.6%
JavaScript 0.5%
Dockerfile 0.2%