SQLite replaces Postgres, and two fixes from using the thing.
- The database is a file under ./storage instead of a second container. Ten
members never needed a database server, and the driver is pure Go, so the
build stays CGO_ENABLED=0 and the dependency count is unchanged. One bind
mount is now the whole backup: no pgdata, no healthcheck-gated depends_on,
no startup retry loop. Timestamps are UTC text, idle_ttl is seconds, the
divisive/unified boards carry their own stddev, and foreign keys are on by
pragma. Tests get a database file each and run without any setup
- Invites are copied, not clicked. An invite is something to send, and the
anchor opened the join form in the admin's own browser
- Feedback asks for more than faults: the footer reads "Ongelmia? Ideoita?
Palautetta?" and the page behind it invites ideas rather than only bugs
- Kuuntele YouTubessa opens in a new tab, so a half-typed review survives it
Lyrics, versioning, and the song page's fact line.
- Lyrics are suggested at submission and never imposed: the worker makes one
LRCLIB lookup, and Hae sanoitukset re-queries with whatever title and artist
are typed. Neither overwrites what the submitter wrote. They live on the
submission, travel to the song at publish, and stay editable after the song
locks — the lock freezes what a song claims to be, and nobody reviewed the
lyrics
- The review strip reads and writes side by side: lyrics left, review right.
Synced LRC highlights the playing line and seeks on click; plain text scrolls
continuously with a nudge knob. Following can be turned off
- CalVer YYYY.MM.DD-N, injected from the git tag with -ldflags, shown in the
footer, the startup log and /healthz
- The song page's metadata became four labelled cells instead of one flat run
of five different kinds of fact
Fixes: publishing wiped lyrics the worker had just fetched (a request that
omitted a field cleared it), lyric auto-scroll landed in the wrong place, and
the fader shifted the deck sideways at score 100.
First release of the Go rewrite: invite-only membership, the submission
pipeline for uploads and YouTube, the queue and review loop with the reveal
rule, stats, profiles, avatars and palaute.
2026-07-31 23:39:03 +03:00
9 changed files with 6 additions and 309 deletions
Writes here are unaudited and unvalidated — the schema holds the constraints, but the app's rules
(the review window, the reveal rule, the lock) are in Go. Prefer the admin panel.
### Disk
Audio is Opus at 96 kbps: roughly 2–3 MB per song, so a hundred songs is a few hundred megabytes.
`storage/tmp/` briefly holds a 50 MB upload plus its converted copy per in-flight submission,
bounded by the two conversion slots.
---
## Troubleshooting
| Symptom | Cause |
|---|---|
| Container exits immediately | `ADMIN_PASSWORD` unset. The log says so, and it is deliberate — an admin panel that silently opens is worse than one that will not boot |
| `set IMAGE in .env` | Compose has no image to run; `IMAGE` is required and unset |
| `/healthz` says `ok dev` | The image was built without `--build-arg VERSION`, so what is deployed cannot be identified |
| Login never sticks | Plain HTTP with `SECURE_COOKIES=true`. Terminate TLS, or set it `false` for a local test |
| Uploads fail near 50 MB | The reverse proxy's body limit, not the app's |
| Invite links are relative | `PUBLIC_URL` unset |
| Everything 500s after a restore | `-wal`/`-shm` sidecars from the replaced database were left in place |
| Submissions all fail at download | yt-dlp is stale; rebuild and publish the image |
| Admin panel answers from another machine | The admin port is published on all interfaces — it must be `127.0.0.1:8081:8081` |
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.