Bit Tuppi

Bit Tuppi is a minimal filesystem library indexer for PDF, EPUB, MOBI, and MP3 files. It treats directory structure as the category hierarchy, stores metadata in SQLite with FTS5 full-text search, and serves a small web UI for browsing and searching the collection. Currently limited to a directory depth of '3'.

The only dependency beyond the Go standard library is modernc.org/sqlite, a pure-Go SQLite driver. No CGO required, which makes cross-compilation to OpenBSD (and other targets) straightforward.

Table of Contents

Requirements

  • Go 1.22 or later

No other dependencies need to be installed. The SQLite driver is compiled from pure Go.

Build

go build -o bittuppi ./cmd/bittuppi

Usage

Point the binary at a directory tree containing your files:

./bittuppi -root /srv/library

Then open http://127.0.0.1:8080 in a browser.

Flags

Flag Default Description
-root (required) Library root directory to index
-db ./bittuppi.sqlite Path to the SQLite database file
-listen 127.0.0.1:8080 HTTP listen address
-rescan 60s Periodic rescan interval; set to 0 to disable

Example

go run ./cmd/bittuppi -root ~/Documents/Library -db ./bittuppi.sqlite -listen 127.0.0.1:8080 -rescan 120s

Example directory layout

/srv/library/
  Indo-European/
    Slavic/
      Russian/
        grammar_textbook.pdf
    Germanic/
      English/
        pronunciation_guide.mp3
  Mathematics/
    linear_algebra_done_right.epub

Files are indexed with the directory path as the category. The filename (minus extension, with underscores and dots replaced by spaces) becomes the title. In the example above, Indo-European/Slavic/Russian/grammar_textbook.pdf gets category Indo-European/Slavic/Russian and title grammar textbook.

API

GET /api/search?q=...&category=... returns up to 200 matching documents as JSON. When q is provided, FTS5 full-text search is used with BM25 ranking. When q is empty, the newest files in the given category (or all categories) are returned.

GET /api/categories returns a JSON array of {"category": "...", "count": N} objects.

GET /f/<path> serves the underlying file. The path must exist in the database; arbitrary filesystem access is not possible.

OpenBSD Notes

Cross-compile from Linux:

GOOS=openbsd GOARCH=amd64 CGO_ENABLED=0 go build -o bittuppi ./cmd/bittuppi

Since there is no CGO involved, the resulting binary runs without any shared library dependencies.

To expose the service on a public interface, you can place it behind httpd(8) or relayd(8) as a reverse proxy. A minimal relayd.conf snippet:

relay "bittuppi" {
    listen on egress port 443 tls
    protocol https
    forward to 127.0.0.1 port 8080
}

No systemd or rc scripts are strictly necessary. Running the binary directly (or from a tmux/screen session, or via an /etc/rc.local entry) works fine.

Description
This could be a library.
Readme ISC 38 KiB
Languages
Go 60.8%
JavaScript 17.9%
CSS 17.4%
HTML 3.9%