No description
  • Go 95.1%
  • Dockerfile 4.9%
Find a file
Jann Pächnatz 9164ab1f22
All checks were successful
CI / test (push) Successful in 23s
M1: in-memory + SQLite stores, migrator, Open wiring
Implement the store.Store root (Users / Books(ownerID) / Close) and the two
  backends behind it:

  - memory: fully implemented, per-user nested maps
  - sqlite: struct layout and navigation done; CRUD methods stubbed (panic TODO)
  - migrations.Apply: embed .up.sql, track schema_migrations, apply in order
  - internal/db.OpenSQLite: open connection, run migrations, return store.Store

  Also move the User domain type to internal/user, add the modernc.org/sqlite
  driver, and update docs/store-konzept.md to the built layout (Option A
  navigation root; import cycle resolved via internal/db; single opener).
2026-07-11 19:50:01 +02:00
.forgejo/workflows CI/Release: switch to native runner with setup-go 2026-07-10 18:16:14 +02:00
cmd Initial scaffolding: domain model, store skeleton, and concept docs 2026-07-10 17:33:17 +02:00
deploy Initial scaffolding: domain model, store skeleton, and concept docs 2026-07-10 17:33:17 +02:00
docs M1: in-memory + SQLite stores, migrator, Open wiring 2026-07-11 19:50:01 +02:00
internal M1: in-memory + SQLite stores, migrator, Open wiring 2026-07-11 19:50:01 +02:00
migrations M1: in-memory + SQLite stores, migrator, Open wiring 2026-07-11 19:50:01 +02:00
.gitignore Initial scaffolding: domain model, store skeleton, and concept docs 2026-07-10 17:33:17 +02:00
go.mod M1: in-memory + SQLite stores, migrator, Open wiring 2026-07-11 19:50:01 +02:00
go.sum M1: in-memory + SQLite stores, migrator, Open wiring 2026-07-11 19:50:01 +02:00
README.md docs: finalize store, ownership and accounts concepts; close M0 2026-07-11 12:49:53 +02:00

shelf

Eine CLI-App zum Tracken deiner Bücher — mit optionaler Synchronisierung über einen selbst-gehosteten Server.

  • shelf — die CLI/TUI, läuft lokal. Schnelle Commands (shelf add "...") und eine optionale interaktive Oberfläche (Bubble Tea).
  • shelfd — der Sync-Server, läuft als Docker-Container und hält den zentralen Stand.

Hinweis zur KI-Nutzung: KI wird bei diesem Projekt nicht zur Entwicklung eingesetzt, sondern ausschließlich zur Strukturierung (Projektaufbau, Konzeption, Dokumentation). Der Anwendungscode wird von Hand geschrieben.

Architektur

Der Server ist die Quelle der Wahrheit (REST-API + DB). Die CLI arbeitet gegen einen lokalen SQLite-Cache und gleicht per shelf sync mit dem Server ab.

shelf (CLI, lokaler SQLite-Cache)  ⇄  HTTP  ⇄  shelfd (Server, SQLite auf Volume)

Projektstruktur

shelf/
├── cmd/
│   ├── shelf/            # main() der CLI
│   └── shelfd/           # main() des Servers
├── internal/
│   ├── book/             # Domänenmodell: Book, Status, Shelf, Rating
│   ├── cli/              # Cobra-Commands
│   │   └── tui/          # Bubble-Tea-Modelle
│   ├── server/           # net/http-Handler, Router, Middleware
│   ├── store/            # Persistenz-Interface
│   │   ├── sqlite/       #   SQLite-Impl
│   │   └── postgres/     #   Postgres-Impl
│   ├── sync/             # Sync-Client (CLI-Seite)
│   └── config/           # Config laden (~/.config/shelf/config.toml)
├── api/                  # geteilte Request/Response-Typen
├── migrations/           # DB-Schema-Migrationen
├── deploy/               # Dockerfile, compose.yaml
├── docs/                 # api.md u.a.
└── .forgejo/workflows/   # CI + Release

Prinzip: internal/book hängt von nichts ab, alles andere hängt von ihr. cmd/* sind nur dünne main()-Wrapper.

Tech-Stack

Bereich Wahl
Sprache Go
CLI Cobra (Commands) + Bubble Tea (TUI)
Server net/http (Stdlib, Methoden-Routing ab 1.22)
DB Server: SQLite oder Postgres (wählbar); CLI: SQLite-Cache
Deployment Docker (multi-stage, scratch/distroless)
CI/CD Forgejo Actions (git.jann.dev)

Datenbank: SQLite oder Postgres (wählbar)

Der Server unterstützt beide Backends. Der Betreiber wählt per Konfiguration, welches genutzt wird — kein Rebuild nötig:

Backend Wofür
SQLite Einzelperson / kleine Runde, minimaler Betrieb (eine Datei, kein extra Container). Mit WAL-Modus blockieren sich Leser/Schreiber nicht.
Postgres Mehrere Nutzer mit vielen Notizen / hohem Schreibaufkommen — echte Nebenläufigkeit statt SQLites Single-Writer-Serialisierung.

Umschalten über Config/Env, z. B.:

SHELF_DB_DRIVER=sqlite     SHELF_DB_DSN=/data/shelf.db
# oder
SHELF_DB_DRIVER=postgres   SHELF_DB_DSN=postgres://user:pw@db:5432/shelf?sslmode=disable

Umsetzung: Das store-Paket ist ein Interface mit zwei Implementierungen (store/sqlite, store/postgres). Die Migrationen in migrations/ werden für beide Backends gepflegt. Der Server wählt beim Start anhand SHELF_DB_DRIVER.

Release & Deployment

Ein Git-Release triggert .forgejo/workflows/release.yaml:

  1. Baut das Server-Image und pusht nach git.jann.dev/jann/shelf:<version> + :latest.
  2. Cross-kompiliert die CLI und hängt die Binaries als Release-Assets an.

Server starten:

docker run -p 8080:8080 -v shelf-data:/data git.jann.dev/jann/shelf:latest

Roadmap

  • M0 — Gerüst: Repo-Layout, Docs, CI/CD, Dockerfile
  • M1 — Domäne + lokaler Store: book-Modell, SQLite-Store, Migrationen (hier)
  • M2 — CLI (offline): add, list, rm, status, rate gegen lokalen Store
  • M3 — Server: shelfd mit REST-API + Auth-Token, SQLite auf Volume
  • M4 — Sync: shelf sync (push/pull), Konfliktbehandlung
  • M5 — TUI: Bubble-Tea-Ansichten (Liste, Detail, Add-Form)
  • M6 — Politur: Konfig, shelf login, Import/Export
  • M7 — SSH-Zugang (ganz später): Wish-Server, der die Bubble-Tea-TUI über SSH serviert (ssh <host>) — andere können ausprobieren, ohne zu installieren. Baut auf der TUI aus M5 auf.
  • M8 — Accounts & Social (optional): invite-only Accounts (shelfd user add, keine Selbst-Registrierung), Sichtbarkeits-Feld (private/shared/public) und Stufe A — öffentliche Profile / teilbare Regal-Links (read-only). Spätere Stufen additiv: B Folgen+Feed, C Rezensionen/Kommentare, D ActivityPub (ausgehend, nur öffentliche Posts, keine DMs). Konzept: docs/accounts-and-social.md.