Bookshelf

Alles wat in de screenshots te zien is, kan worden gereproduceerd met npm run demo — een gegenereerde collectie van publiek domein-titels, zodat de functionaliteit getest kan worden zonder dat je eerst zelf boeken hoeft te zoeken.

Aan de slag

Vereisten:

  • Node 24 of nieuwer.
  • Een Unix-achtig systeem: de synchronisatietool vindt zijn image-tools via dit systeem, waardoor Windows niet wordt ondersteund.
  • Voor optimale omslagen worden cwebp en pdftoppm aanbevolen (zie 'Publiceren' of gebruik Docker, waarin beide standaard zijn inbegrepen).

Installatie:

git clone https://github.com/murerkinn/bookshelf.git
cd bookshelf
npm install

Plaats vervolgens EPUB- of PDF-bestanden in de map books/ en bepaal waar de bibliotheek moet worden opgeslagen.

Met Docker

Dit is de kortste route. Het image bevat eigen cwebp en pdftoppm, zodat omslagen correct worden gegenereerd zonder dat je iets op de hostmachine hoeft te installeren.

mkdir books && cp ~/Downloads/*.epub books/
docker compose run --rm sync --create
docker compose up -d

De bibliotheek is vervolgens bereikbaar via http://localhost:3000. Vlaggen worden doorgegeven, dus docker compose run --rm sync --force en --dry-run werken hetzelfde als bij lokaal gebruik.

Een named volume, library, bevat de gepubliceerde boeken en alle gegevens die de app schrijft (zoals profielen en leesposities); dit is het enige onderdeel dat gebackupt moet worden.

Het image is gebouwd voor de filesystem provider (Node-server); Cloudflare heeft geen container nodig. De app draait als een non-root gebruiker en maakt /data aan, eigendom van die gebruiker, zodat een named volume de juiste schrijfrechten erft. Indien je liever een host-directory bind-mount, wijzig dan eerst de eigenaar:

chown -R 1000:1000 /srv/bookshelf

Op een eigen machine, zonder Docker

Zonder externe accounts. Richt bookshelf.config.json op een directory, publiceer daarin en start de app:

// bookshelf.config.json
{ "storage": { "provider": "fs", "directory": "shelf-data" } }
npm run sync -- --create   # bouwt library/, en publiceert dit naar shelf-data/
npm run build
npm start -w @bookshelf/app

library/ is de mappenstructuur die de synchronisatietool bouwt; directory is de plek waarheen het wordt gepubliceerd en waar de boeken worden geserveerd. Houd library/ buiten de repository; shelf-data/ is hier al uitgesloten.

Op Cloudflare

Hiervoor is een Cloudflare-account en npx wrangler login vereist. Twee bestanden in het project bevatten de eigen bucket- en Worker-naam en zijn bedoeld om te worden bewerkt (zie de R2-provider).

npm run sync -- --create   # maakt de bucket aan en uploadt de bestanden
npm run deploy

Beide configuraties moeten overeenstemmen wat betreft de bucket die de bibliotheek bevat, anders dient de app een lege bibliotheek. Er vindt een controle plaats voordat er iets wordt geüpload; bij een mismatch wordt er een melding gegeven in plaats van dat er gepubliceerd wordt.

Een demobibliotheek

Heb je geen boeken bij de hand of wil je iets dat geschikt is voor screenshots? Je kunt negen gegenereerde publiek domein-titels (acht EPUB's en één PDF) toevoegen zonder iets te downloaden:

npm run demo                 # schrijft de boeken naar books/

Publiceer en serveer deze vervolgens via een van de bovenstaande methoden. De titels en auteurs zijn echte werken waarvan het auteursrecht is verlopen, maar de tekst binnenin is placeholder-tekst. Let op: de configuratie in deze repository wijst standaard naar R2, dus npm run sync zal daarheen uploaden tenzij je dit wijzigt.

Een publieke instantie

Elke instantie die bereikbaar is voor vreemden, moet zodanig worden geconfigureerd dat wijzigingen worden geweigerd: BOOKSHELFREADONLY=1

In deze modus blijft de storage bestanden serveren, maar accepteert geen wijzigingen meer. Profielen kunnen niet worden toegevoegd, hernoemd of verwijderd, en leesposities worden lokaal in de browser opgeslagen. Dit is dezelfde degradatie als bij een provider die niet kan schrijven. Het wisselen tussen bestaande profielen blijft mogelijk, aangezien dit via een cookie verloopt en geen wijziging in de storage vereist.

Deze beperking wordt afgedwongen op het punt waar de schrijfactie plaatsvindt, niet door formulieren te verbergen; het direct versturen van acties (via API) zal resulteren in dezelfde weigering.

Er is geen authenticatie. Iedereen die de app kan bereiken, kan de volledige bibliotheek lezen en downloaden. Plaats de applicatie daarom in een vertrouwenswaardig netwerk of achter een beveiligingslaag. Zie ook 'Nog niet gerealiseerd'.

Commando's

Alle commando's worden uitgevoerd vanuit de root van de repository. Turborepo bouwt eerst de afhankelijkheden die nodig zijn voor de taak.

  • npm run dev: lokale dev server, gericht op de lokale R2 bucket.
  • npm run sync: bouwt de bibliotheek en uploadt deze naar de bucket.
  • npm run build: bouwt elke workspace.
  • npm run check-types: voert typechecking uit voor elke workspace.
  • npm run preview: bouwt en draait de Worker lokaal.
  • npm run deploy: bouwt en deployt naar Cloudflare Workers.
  • npm test: voert de testsuite uit.
  • npm run lint: voert biome uit over de gehele repo.
  • npm run cf-typegen -w @bookshelf/app: genereert cloudflare-env.d.ts opnieuw na het bewerken van wrangler.jsonc.

Documentatie

De volgende onderwerpen worden gedetailleerd behandeld in de documentatie:

  • Het publiceren van een bibliotheek: de synchronisatietool, vlaggen en omslagen.
  • Het bibliotheekformaat: wat er in de bucket terechtkomt en waarom dit opnieuw genereerbaar is.
  • Storage providers: het contract en de mogelijkheden van de twee meegeleverde providers.
  • Cloudflare R2: configuratie, deployment en lokaal publiceren.
  • Filesystem: draaien op een eigen machine of VPS.
  • Profielen: wie er leest en waar zij zijn gebleven.
  • Lezen in de browser: hoe een hoofdstuk op de pagina terechtkomt.
  • Architectuur: ports, adapters en de composition root.
  • De demobibliotheek: hoe de publieke bibliotheek is gebouwd en hoe deze opnieuw gebouwd kan worden.

Nog niet gerealiseerd

Er is geen authenticatie. Iedereen met de URL kan de hele bibliotheek lezen en downloaden, en elk profiel kiezen. Profielen zijn bedoeld om bladwijzers van huisgenoten gescheiden te houden, niet om onbevoegden buiten te sluiten.

Wanneer twee apparaten tegelijkertijd lezen onder één profiel, geldt het principe van 'last-write-wins'.

Bijdragen

Zie CONTRIBUTING.md. De korte versie: Node 24, npm install, en voer npm run lint, npm run check-types en npm test uit voordat je pusht. De tests dekken de packages en de service layer van de app, maar niet de pagina's; geef daarom aan welke tests je hebt gedraaid.

Storage providers zijn het uitbreidingspunt en hoeven niet in dit project te leven: een door anderen gepubliceerd package kan worden geïnstalleerd en in de configuratie worden benoemd.

Licentie

MIT — zie LICENSE.

Dit geldt voor de code. Er wordt niets gezegd over de boeken die je in een bibliotheek plaatst; het auteursrecht daarvan ligt tussen jou en de uitgevers.