# Nupplo SE đ§±
> **FrĂŒher Brickfolio.** Seit 3.0.0 heiĂt die App **Nupplo SE** â SE steht
> fĂŒr *Server Edition*, die Fassung, die du selbst betreibst. Gleiche App,
> neuer Name; bestehende Installationen laufen ohne Umstellung weiter.
*[đŹđ§ English](README.en.md) · đ©đȘ Deutsch*
[](https://buymeacoffee.com/melle79)
[](LICENSE)
Selbstgehostete PWA zum Scannen, Verwalten und Bewerten einer LEGOÂź-Sammlung â
gebaut fĂŒr die ganze Familie auf einer gemeinsamen Datenbank, mit optionalem
**Sammlerprofi-Modus** fĂŒr alle, die auf FlohmĂ€rkten kaufen und verkaufen.
**Foto â Erkennung â Sammlung.** Die Erkennung lĂ€uft ĂŒber die kostenlose
[Brickognize-API](https://brickognize.com); Preise, Set-Inhalte und Metadaten
kommen von [BrickLink](https://www.bricklink.com) und
[Rebrickable](https://rebrickable.com) (eigene API-Keys nötig, siehe unten).
> đ Das ausfĂŒhrliche **Benutzerhandbuch** liegt unter
> [`docs/HANDBUCH.md`](docs/HANDBUCH.md) · [đŹđ§ English manual](docs/MANUAL.md).
## Funktionen
**Erfassen & Verwalten**
- đ· Figuren und Sets direkt mit der Handykamera scannen (Kandidatenliste mit
Trefferscore) oder per Name/Nummer suchen â reine Nummern werden automatisch
als Set *und* Figur nachgeschlagen
- đŠ Mengen, Zustand (neu/gebraucht), Notizen, Bildergalerie, Volltextsuche
(mit đ-Symbol und â zum Leeren), Sortierung und Typ-Filter
- đ Katalogsuche ab drei Zeichen, **10 Treffer pro Seite** mit âWeitere
Ergebnisse laden" â alle Treffer sind erreichbar
- đ©đȘ **Deutsch suchen, ohne KI**: Die Katalognamen sind englisch, gesucht
wird auf Deutsch. Die App bringt dafĂŒr ein Wörterbuch mit (rund 1.400
Stichwörter), streift Endungen ab und zerlegt zusammengesetzte Wörter â
âProtokolldroide" wird zu `protocol droid`. Teil und Farbe lassen sich
kombinieren: âFigur mit blauem Hut, roten Beinen und grĂŒnem Torso". Eine
lokale KI ist weiterhin nĂŒtzlich, aber nicht mehr nötig
- đ„ **Figuren beim Set ĂŒbernehmen**: Beim HinzufĂŒgen eines Sets fragt die App,
welche der enthaltenen Minifiguren dabei sind (alle, keine oder eine Auswahl,
inklusive Zustand) â ohne den Gesamtwert doppelt zu zĂ€hlen
- đ„ Set-Vernetzung: Sets kennen ihre Figuren (âđ„ 3/4 â"-VollstĂ€ndigkeit),
Figuren zeigen, in welchen euren Sets sie stecken; fehlende Set-Figuren
landen mit einem Tipp gesammelt auf der Wunschliste
- đŒ **Bild nachladen** je Eintrag, falls es fehlt oder nicht passt
- đ· **Eigene Fotos am Artikel** â so wie die Bilder, die KĂ€ufer bei BrickLink
beisteuern. Ein KĂ€stchen ĂŒber den Scan-Treffern hĂ€ngt das Scan-Foto an alles,
was ihr daraus anlegt; bei mehreren Figuren auf einem Bild bekommt **jede
ihren eigenen Ausschnitt**. Das Katalogbild bleibt, euer Foto kommt in der
Galerie daneben. Steht die Figur lĂ€ngst in der Sammlung, genĂŒgt **âđ· Nur
Foto dazu"** â ohne eine zweite Zeile anzulegen
- đ **Detailansicht ĂŒberall**: Ein Tipp auf einen Such- oder Scan-Treffer
öffnet ein Popup mit Jahr, Thema, Preisen und â bei Minifiguren â den
**enthaltenen Teilen samt Farbnamen**
- đš **Eigene Figuren (Custom)**: Eigenbauten mit selbst vergebener Nummer
(die App zĂ€hlt `custom-001`, `-002` ⊠weiter) und eigenem Bild â wahlweise
direkt das Foto aus dem Scan. Sie stehen in der Sammlung unter âCustom"
- đïž **Themenkarten**: Sortiert nach Thema zeigt die Sammlung aufklappbare
Karten (Star Wars, City, Custom âŠ) mit Anzahl und Wert je Thema. Die zuletzt
gewÀhlte Sortierung merkt sich das Profil
- đ **Den Katalog durchblĂ€ttern** (Listen â Katalog): alle Figuren eines
Themas in Nummernfolge, mit dem eigenen Besitzstand daneben. **â** legt sie
in die Sammlung, **â„** auf die Wunschliste; Filter fĂŒr *Alle · Fehlt mir ·
Hab ich · Gemerkt*. Am Rand ein Sprungbalken mit den Hunderterblöcken â bei
1.663 Star-Wars-Figuren der Unterschied zwischen Suchen und Finden.
Ausgehakt wird nur, was nichts wert ist: HĂ€ngt eine StĂŒckzahl ĂŒber eins oder
eine Notiz daran, rĂŒhrt die App den Eintrag nicht an
- â **Themen aussuchen** (Mehr â Katalog-Themen): Der Index kennt ĂŒber 200
Themen. Ein **â
** hebt eines nach oben, ein **â** bestimmt, ob es ĂŒberhaupt
in der Auswahl erscheint â âNur Favoriten" rĂ€umt den Rest in einem Zug weg.
Gilt je Benutzer, nicht fĂŒr die ganze Instanz
- đ **Jedipedia-Verweis** (Mehr, ausgeschaltet voreingestellt): ein kleines
**â** neben Star-Wars-Figuren, das sie im deutschen Star-Wars-Wiki
nachschlĂ€gt â in aller Regel direkt im Artikel. âBespin Guard" heiĂt
dort *Bespin-SicherheitskrĂ€fte*, und bei âClone Trooper Commander,
187th Legion" fĂŒhrt der Verweis zur *187. Legion*
**Preise & Wert**
- đ¶ BrickLink-Ă-Preise (neu/gebraucht) automatisch im Hintergrund, mit
eigener **Preisverlaufs-Aufzeichnung** und Chart pro Artikel
- đ **Preisgebiet wĂ€hlbar** (Mehr â Preisgebiet): weltweit, Deutschland,
Ăsterreich, Schweiz oder Europa â ohne VerkĂ€ufe im gewĂ€hlten Gebiet weitet die
App zweistufig aus (erst Europa, dann weltweit). Bestehende Preise lassen sich
schrittweise umrechnen, preislose Artikel per Knopfdruck neu abrufen. Im
Steckbrief zeigt eine kleine **Flagge** (đ©đȘ/đȘđș/đ) an jeder Preiszeile,
woher der Preis kommt
- đ· **Angebotspreise** (zuschaltbar): zusĂ€tzlich zum Ă-Verkaufspreis, *ab wie
viel* eine Figur gerade zu haben ist â im Steckbrief und als Marke in
Wunsch- und Einkaufslisten
- đ **Statistik-Tab**: Kennzahlen, Wertentwicklung der Gesamtsammlung,
Aufteilung nach Typ/Zustand, Wert nach Erscheinungsjahr, Top 10
**Wunschliste**
- â Merken aus jedem Scan/Suchergebnis, Ă-Preis-Widgets, âGekauft"-Ăbernahme
in die Sammlung inkl. Zustandswahl
- đ§© Figuren, die zu einem eurer Sets gehören und noch fehlen, sind mit âfehlt
zu eurem Set" gekennzeichnet â ein Tipp springt direkt zum Set
**Tausch-Netzwerk** (optional, nur mit Einladung)
> **Von Haus aus ist es aus, und es wird nichts geteilt.** Deine Sammlung
> bleibt auf deinem Server. Erst wenn du mit einem Einladungscode beitrittst,
> gibt es das Netzwerk fĂŒr dich â und auch dann geht nur hinaus, was du
> ausdrĂŒcklich auswĂ€hlst: die Artikel, die du anbietest, dein Profil und,
> wenn du es einschaltest, deine Wunschliste. Abmelden nimmt alles wieder
> heraus.
- đ€ Mehrere Nupplo-Instanzen verbinden sich ĂŒber einen kleinen
**Tausch-Hub**: Jeder bietet die Artikel an, die er abgeben möchte, **zum
Tausch, zum Verkauf oder beides**, und sieht die Angebote der anderen
- đą **Selbst auswĂ€hlen, was hineinkommt**, samt Menge: Von drei gleichen
Figuren lÀsst sich auch nur eine anbieten
- đ§ **Entdecken**: wer hat, was du suchst, wer sucht, was du ĂŒbrig hast,
und wer dieselben Themen sammelt â verglichen auf deiner eigenen Instanz
- đ€ **Profile**: Ăber mich, Gegend, Lieblingsthemen, Tauschbilanz â alles
freiwillig, die SammlungsgröĂe nur gerundet und nur auf Wunsch
- đŠ **Tausch mit Anfang und Ende**: angenommen â verschickt â angekommen â
gebucht â abgeschlossen. Ăbernehmen und Austragen buchen gleich in die
Sammlung, samt Kaufbuch
- đŹ **Nachrichten Ende-zu-Ende verschlĂŒsselt** (X25519 + AES-256-GCM). Der
Hub kann sie nicht lesen und löscht sie, sobald sie zugestellt sind; der
lesbare Verlauf bleibt auf den beteiligten Instanzen
- âïž **Einladungen mit Kontingent**: Jeder darf drei Freunde einladen und
kann mehr anfragen. Ohne Einladung kommt niemand hinein
- ➠**Pause bei InaktivitÀt**: Wer lÀnger nicht da war, dessen Angebote
blendet der Hub aus, bis er wiederkommt
- â **Melden mit Verlauf**: Die Meldung bleibt fĂŒr den Meldenden sichtbar,
der Hub-Admin kann nachfragen und eine MaĂnahme aussprechen (Hinweis,
Verwarnung, Sperre), die der Betroffene in seiner App sieht â ohne zu
erfahren, wer gemeldet hat
- đŒïž Eigene Figuren reisen mit **verkleinertem Vorschaubild**, damit beim
GegenĂŒber kein Platzhalter steht
**Sammlerprofi-Modus** (Rolle, die der Admin pro Benutzer vergibt)
- đ° Kaufpreis je Eintrag â automatisch mit dem BrickLink-Ă vom Erfassungstag
vorbelegt (âïž) oder manuell (âïž), mit Gewinn-/Verlust-Anzeige
- đ **Einkaufslisten** fĂŒr den Flohmarkt: befĂŒllen per Scan, Marktwert live,
Einkaufspreis je Artikel, **Gesamtangebot** mit anteiliger Verteilung nach
Marktwert und 60-%-Preisvorschlag
- đ **Verkaufsliste**: alle Doppelten mit abgebbarer Menge und Verkaufswert â
fĂŒr eigene Sets gebrauchte Figuren bleiben reserviert, von allem anderen
bleibt ein Behalte-Exemplar
- đ§© **Fehlende Set-Figuren**: ĂŒber alle eigenen Sets hinweg, welche Figuren
noch fehlen (mit Anzahl, Sets, Nachkaufpreis) â einzeln oder alle auf die
Wunschliste, als CSV oder Druckliste
- đ Beim Verbuchen von einer Einkaufsliste landet der **Listenname in den
Notizen** des Sammlungs-Eintrags (Herkunft bleibt nachvollziehbar)
- đ ZusĂ€tzliche Statistik: bezahlt gesamt, Gewinn, beste Wertsteigerungen
**Familie & Betrieb**
- đ Mehrbenutzer mit Token-Login (PBKDF2-gehashte Passwörter), Admin- und
Profi-Rollen (Admins können weitere Admins ernennen), eigene
Passwort-/NamensÀnderung
- đŸ Komplett-**Sicherung** als JSON (herunterladen & wieder einspielen) â
auf Wunsch **samt eurer eigenen Bilder**, damit nach einem Umzug nichts ins
Leere zeigt. CSV-Export und druckfertige Listen gibt es dazu
- đ· Konfigurierbarer **Anzeigename** in Logo und Titel (standardmĂ€Ăig leer);
ideal, wenn mehrere Familienmitglieder je eine eigene Instanz betreiben
- đ Drei **Designs** zur Auswahl (Mehr â Design): âKlassisch" hell,
âGalaxie" dunkel mit Sternenhimmel und âNova" â ein modernes Glas-Design
mit blauem Akzent; die Wahl gilt pro GerÀt
- đ **Hinweise auf dem Startbildschirm**: Ăndert oder löscht BrickLink eine
Nummer aus eurer Sammlung, steht das im Scannen-Tab â und bleibt dort, bis es
jemand wegklickt. Die neue Nummer sucht die App im BrickLink Catalog Change
Log und trĂ€gt sie auf Knopfdruck ĂŒberall ein
- đ **Externer Zugriff per Assistent** (Mehr â Externer Zugriff, Admin): baut
aus deinem Cloudflare-Tunnel-Token den fertigen `docker-compose`-Block â Zugriff
von unterwegs ohne Portfreigabe. Die App startet den Tunnel nicht selbst (kein
Docker-Zugriff), der Token bleibt im Browser
- đ **Fehlerbericht** (Mehr â Fehlerbericht, Admin): Fehler aus allen GerĂ€ten
melden sich automatisch am eigenen Server und werden gleichartig
zusammengefasst. Mit hinterlegtem GitHub-Token legt ein Klick daraus ein
Issue an; API-SchlĂŒssel und Token werden vorher aus dem Text entfernt
- đ„ **Reagiert auf die Bildschirmbreite**: auf dem Handy Tab-Leiste unten, am
Rechner Seitenleiste links mit breiterem Raster (vier bis fĂŒnf Karten pro
Reihe) â dieselbe App, nur besser auf die FlĂ€che verteilt
- ⚠**Moderne Darstellung**: Artikel öffnen sich als Fenster, das mit dem
**Bild ĂŒber die volle Breite** aufmacht; darunter Name, Marken und â fĂŒr
HĂ€ndler â drei Kacheln (Bezahlt, Wert, Gewinn). Der Rest liegt auf drei
Reitern (Exemplar, Preise, Mehr), statt untereinander zu stehen. In der
Sammlung schimmert das Produktbild als dezenter Kartenhintergrund
- đČ Als PWA installierbar â auf dem Handy bietet die Scan-Seite das Ablegen
**auf dem Startbildschirm** an (auf Android per Knopf, auf dem iPhone mit
Anleitung) und blendet den Hinweis aus, sobald es liegt. Offline-Shell,
keine Cloud â alles liegt auf eurem Server, **auch die Katalogbilder**:
Die holt die Instanz einmal und liefert sie danach selbst, der Browser
fragt also nie bei BrickLink, Rebrickable oder Brickognize an
## Screenshots
| Scannen | Sammlung |
|:---:|:---:|
|
|
|
| **Statistik** | **Einkaufsliste (Flohmarkt-Modus)** |
|
|
|
| **Eigene Fotos in der Galerie** | **Sicherung samt Bildern** |
|
|
|
*(Screenshots mit Demo-Daten. Statt Katalogbildern steht ĂŒberall der
Platzhalter der App â fremdes Bildmaterial gehört nicht ins Repository. Die
Fotos in der Galerie sind selbst erzeugte Beispielbilder.)*
## Schnellstart (Docker)
Kein Quellcode, kein Bauen â zwei Befehle:
```bash
mkdir nupplo && cd nupplo
curl -sLo docker-compose.yml https://raw.githubusercontent.com/Melle79/nupplo/main/docker-compose.example.yml
docker compose up -d
```
Aufrufen: `http://:8300` â beim ersten Besuch fĂŒhrt der
**Einrichtungsassistent** durch alles Nötige: Admin-Konto, Anzeigename,
API-SchlĂŒssel (mit PrĂŒfen-Knopf) und, falls vorhanden, die Einladung ins
Tausch-Netzwerk. Ăberspringen geht ĂŒberall; nachholen lĂ€sst sich alles unter
*Mehr*. Die Datenbank liegt persistent unter `./data/brickfolio.db`.
**Umzug von einer anderen Instanz?** Dann leg hier kein Konto an â im
Willkommens-Bogen steht **âđ„ Sicherung einspielen"**. Der alte Stand kommt
samt Konten herĂŒber; danach meldest du dich mit deinen bisherigen
Zugangsdaten an.
Das Image gibt es fĂŒr **amd64** â das ist **x86-64**, also jeder gewöhnliche
Intel- *oder* AMD-Rechner (PC, Intel-NAS, Synology) â und **arm64**
(Raspberry Pi, ARM-NAS), auf zwei Registries â derselbe Build, nur zwei
Adressen:
| Registry | Name |
|---|---|
| GitHub Container Registry | `ghcr.io/melle79/nupplo:latest` |
| Docker Hub | `melle79/nupplo:latest` |
Die YAML oben nimmt `ghcr.io`. Docker Hub braucht ihr, wenn eure NAS-OberflÀche
eine **Suchmaske** fĂŒr Images hat â die durchsucht meist nur Docker Hub.
### Synology NAS
Ganz ohne Konsole: **Container Manager â Projekt â Erstellen**, YAML einfĂŒgen,
fertig. Schritt fĂŒr Schritt in [`docs/SYNOLOGY.md`](docs/SYNOLOGY.md).
Per SSH geht es genauso â Ordner unter `/volume1/docker/nupplo` anlegen
und die Befehle oben mit `sudo` ausfĂŒhren.
### Andere NAS-Systeme und Rechner
Es ist ein gewöhnliches OCI-Image auf zwei öffentlichen Registries â ĂŒberall
dort, wo Container laufen, lÀuft auch Nupplo. Dasselbe YAML wie oben,
nur an anderer Stelle eingefĂŒgt:
| System | Wo das YAML hingehört |
|---|---|
| **QNAP** | Container Station â *Anwendungen* â Erstellen |
| **UGREEN** | Docker â *Projekt* â Erstellen |
| **TerraMaster** | Docker Manager â *Compose* |
| **Asustor** | Portainer (aus App Central) â *Stacks* |
| **Unraid** | Docker-Reiter, oder *Compose Manager* aus den Community Apps |
| **TrueNAS SCALE** | Apps â *Custom App* (YAML) |
| **OpenMediaVault** | omv-extras â Compose â *Files* |
| **Linux / Raspberry Pi / Mac / Windows** | Ordner anlegen, `docker compose up -d` |
Gebaut wird fĂŒr **amd64** und **arm64**. Sehr alte 32-Bit-ARM-GerĂ€te
(`armv7`, z. B. Ă€ltere Einsteiger-NAS) werden nicht unterstĂŒtzt.
**Unraid** hat es bequemer: Unter *Docker â Einstellungen â
Template Repositories* diese Adresse eintragen â
```
https://github.com/Melle79/unraid-templates
```
â danach steht Nupplo unter *Docker â Add Container* in der
Vorlagen-Auswahl, mit vorbelegtem Port, `/data`-Pfad und den optionalen
SchlĂŒsseln. Die Vorlage pflegen wir in
[Melle79/unraid-templates](https://github.com/Melle79/unraid-templates);
eine Kopie liegt hier unter [`unraid/brickfolio.xml`](unraid/brickfolio.xml).
### Bei einem Anbieter statt zu Hause
Wer keine eigene Hardware laufen lassen will, mietet die Instanz. **Sie
gehört dann dem, der sie anlegt** â Daten, Kosten und Zugang. Es gibt
weiterhin keinen Nupplo-Dienst dazwischen.
| Anbieter | Weg | Anmerkung |
|---|---|---|
| **Render** | [](https://render.com/deploy?repo=https://github.com/Melle79/nupplo) | Liest [`render.yaml`](render.yaml). Braucht den kleinsten **bezahlten** Tarif: Nupplo benötigt eine dauerhafte Platte fĂŒr `/data`, und die gibt es im kostenlosen Tarif nicht |
| **Railway** | Neues Projekt â *Deploy from GitHub* â dieses Repo, dann unter *Settings â Config-as-Code* `deploy/railway/railway.json` eintragen | Danach eine **Volume** auf `/data` legen, sonst ist die Sammlung nach jedem Neustart weg |
| **Coolify / Dokploy** | `docker-compose.example.yml` einfĂŒgen | Auf dem eigenen v-Server, volle Kontrolle |
> **Warum kein kostenloser Tarif?** Ohne dauerhafte Platte liegt die
> Datenbank im Container â bei jedem Neustart wĂ€re die Sammlung weg. Lieber
> ein ehrlicher Hinweis als eine Bereitstellung, die still Daten verliert.
Wer keine Compose-OberflÀche hat, kommt auch so ans Ziel:
```bash
docker run -d --name nupplo --restart unless-stopped \
-p 8300:8300 -v /pfad/zu/data:/data \
ghcr.io/melle79/nupplo:latest
```
### Selbst bauen (statt fertiges Image)
Nur nötig, wenn du eigene Ănderungen einspielen willst:
```bash
mkdir nupplo && cd nupplo
curl -sL https://github.com/Melle79/nupplo/archive/refs/heads/main.tar.gz | tar xz --strip-components=1
cp docker-compose.example.yml docker-compose.yml
sed -i 's|image: ghcr.io/melle79/nupplo:latest|build: .|' docker-compose.yml
docker compose up -d --build
```
(Auf Synology lÀuft die curl-Zeile mit Rechten am besten als
`sudo sh -c 'curl ⊠| tar âŠ'`, damit die ganze Pipe erfasst ist.)
## Konfiguration
| Variable | Pflicht | Beschreibung |
|---|---|---|
| `ADMIN_USER` / `ADMIN_PASSWORD` | nein | Optional: Admin automatisch anlegen (sonst Ersteinrichtung im Browser) |
| `DB_PATH` | nein | Pfad zur SQLite-Datei (Default im Container: `/data/brickfolio.db`) |
| `BL_CONSUMER_KEY` / `BL_CONSUMER_SECRET` / `BL_TOKEN` / `BL_TOKEN_SECRET` | nein | BrickLink-Store-API fĂŒr Preise & Set-Inhalte ([Key beantragen](https://www.bricklink.com/v2/api/register_consumer.page)) |
| `BACKUP_KEEP` | nein | Automatische tÀgliche Sicherungen aufbewahren (Standard 14, 0 = aus) |
| `REBRICKABLE_KEY` | nein | Rebrickable-API fĂŒr die Namenssuche ([Key erstellen](https://rebrickable.com/api/)) |
| `GITHUB_REPO` | nein | Ziel-Repository fĂŒr Issues aus dem Fehlerbericht (Default `Melle79/nupplo`) |
Alle API-Keys lassen sich alternativ **in der App** hinterlegen
(Mehr â API-SchlĂŒssel, nur Admin) â ENV-Variablen dienen als Fallback.
## Rechte-Ăbersicht
| Aktion | Standard | Sammlerprofi | Admin |
|---|:-:|:-:|:-:|
| Scannen, Sammlung, WĂŒnsche, Statistik | â | â | â |
| Einkaufslisten sehen & Artikel âist da" verbuchen | âÂč | â | âÂč |
| Listen anlegen/befĂŒllen/archivieren, Gesamtangebot, Verkaufsliste | â | â | â |
| Kaufpreise & Gewinn sehen | â | â | â |
| Benutzer, Rollen, API-Keys, Sicherung | â | â | â |
Âč Tab erscheint nur, wenn mindestens eine aktive Liste existiert.
Rollen sind kombinierbar (der Admin kann sich selbst zum Profi machen).
## Updates & Backup
**Die App sagt Bescheid.** Unter *Mehr â Version & Updates* vergleicht sie die
laufende Version mit dem neuesten Release â unabhĂ€ngig davon, wie du
installiert hast.
**Mit fertigem Image** (der Schnellstart oben) genĂŒgen zwei Befehle im
Projektordner:
```bash
docker compose pull && docker compose up -d
```
Auf einer Synology geht dasselbe ohne Konsole: *Container Manager â Projekt â
nupplo â Aktion â Erstellen neu starten*.
> **Ohne Projekt, also von Hand aus der *Registrierung* geklickt?** Dann gibt
> es diesen Knopf nicht â ein Container kann sein Image nicht wechseln, und
> ohne YAML muss man ihn löschen und neu anlegen. Der Ablauf steht in
> [`docs/SYNOLOGY.md`](docs/SYNOLOGY.md). Wichtig dabei: Liegt kein Ordner auf
> `/data`, steckt die Datenbank in einem anonymen Volume und der neue
> Container bekommt ein leeres â **vorher sichern**.
Der Ordner `data/` bleibt dabei unberĂŒhrt, Datenbank-Migrationen laufen beim
Start automatisch und sind idempotent. **Ein Schnappschuss vorher schadet
nie** â in der App unter *Mehr â Sicherung* die JSON-Datei herunterladen.
> `update.sh` und `update-watch.sh` liegen **nicht** im Image und nicht im
> Ordner, wenn du nur die `docker-compose.yml` geholt hast. Wer sie möchte
> (Schnappschuss automatisch, Update aus der App heraus), lÀdt sie einmalig
> dazu:
>
> ```bash
> curl -sLO https://raw.githubusercontent.com/Melle79/nupplo/main/update.sh
> curl -sLO https://raw.githubusercontent.com/Melle79/nupplo/main/update-watch.sh
> ```
**Aus dem Quellcode gebaut**: `sudo bash update.sh` im Projektordner. Das
Skript legt zuerst einen Datenbank-Schnappschuss an (die letzten drei bleiben
erhalten) und erkennt selbst, ob es das Image nachziehen oder neu bauen muss.
### Update aus der App heraus (optional)
**Völlig optional** â ohne Einrichtung Ă€ndert sich nichts, Updates laufen wie
gehabt ĂŒber `update.sh` per SSH. Der Knopf in der App erscheint erst, wenn der
Helfer unten eingerichtet ist; vorher steht dort nur ein Hinweis darauf.
**Wie es funktioniert.** Die App fĂŒhrt das Update **nicht selbst** aus â sie
kann es gar nicht, denn sie lÀuft im Container. Sie legt nur die Markierung
`data/update-requested.json` ab. Ein kleines Skript auf dem Server greift die
auf und startet `update.sh`. So braucht die App **keinen Docker-Zugriff** â
den ins Container zu reichen kÀme faktisch Root auf dem Server gleich.
#### Einrichten
`update-watch.sh` regelmĂ€Ăig aufrufen lassen. **Ein Takt von einer Minute
reicht** â das Update selbst dauert ohnehin ein bis drei Minuten.
**Synology (DSM):** Systemsteuerung â Aufgabenplaner â Erstellen â
Geplante Aufgabe â Benutzerdefiniertes Skript
| Reiter | Einstellung |
| --- | --- |
| Allgemein | Benutzer: **`root`** (sonst darf das Skript kein `docker compose`) |
| Zeitplan | TĂ€glich · Start `00:00` · âWeiterhin innerhalb desselben Tages ausfĂŒhren" â · Wiederholen: **jede Minute** · Letzte AusfĂŒhrungszeit: **`23:59`** |
| Aufgabeneinstellungen | Befehl: `sh /pfad/zu/nupplo/update-watch.sh` |
> â ïž Die âLetzte AusfĂŒhrungszeit" steht anfangs auf `00:59` â dann liefe die
> Aufgabe nur in der ersten Stunde des Tages. Unbedingt auf `23:59` stellen.
**Linux mit cron:** `* * * * * sh /pfad/zu/nupplo/update-watch.sh`
#### Mehrere Instanzen
Betreibt ihr mehrere Nupplos (je eigener Ordner mit eigener
`docker-compose.yml`), legt am besten **je Instanz eine eigene Aufgabe** an.
Das ist der robusteste Weg: Jede lÀuft unabhÀngig, und im Aufgabenplaner seht
ihr pro Instanz, ob sie durchgelaufen ist.
Wollt ihr trotzdem nur **eine** Aufgabe, hÀngt an jede Zeile `|| true`:
```sh
sh /volume1/docker/nupplo/update-watch.sh || true
sh /volume1/docker/nupplo-zweit/update-watch.sh || true
```
> â ïž Ohne `|| true` kann die zweite Zeile ausfallen: Bricht die erste mit einem
> Fehler ab (etwa fehlende Rechte), beendet der Aufgabenplaner das ganze
> Skript â die zweite Instanz bekommt dann nie ein Lebenszeichen.
Die Instanzen bleiben in jedem Fall unabhĂ€ngig â jede hat ihre eigene
Markierung im eigenen `data`-Ordner, ein Update bei der einen rĂŒhrt die andere
nicht an.
#### Ablauf
Admin wĂ€hlt sofort / 1 Min / 5 Min â alle angemeldeten Browser zeigen einen
Countdown (âbitte Eingaben abschlieĂen"), danach einen Sperrbildschirm. Sobald
der Server wieder da ist, laden sich die Browser selbst neu. Solange der
Countdown lÀuft, kann der Admin abbrechen.
- Der Helfer hinterlÀsst bei jedem Lauf `data/update-watch-alive`. Daran
erkennt die App, dass er eingerichtet ist â fehlt das Lebenszeichen lĂ€nger
als fĂŒnf Minuten, wird das Update gar nicht erst angeboten.
- Protokoll jedes Laufs: `data/update-watch.log`.
- Sicherung: In-App unter Mehr â Sicherung (JSON mit allen Daten inkl.
Benutzern und PreisverlÀufen) **oder** einfach `data/brickfolio.db` kopieren.
## Technik
FastAPI + SQLite (ohne ORM) · Vanilla JS PWA (kein Build-Schritt) ·
Docker-Deployment · APIs: Brickognize, BrickLink Store API (OAuth1),
Rebrickable.
### Was in eigenen Repos liegt
Hier liegt das **Programm**. Drei Dinge daneben haben einen eigenen
Rhythmus und deshalb ein eigenes Repo â alle drei nicht öffentlich, weil
sie Zugangsdaten beschreiben oder Bildschirmfotos aus einer echten
Sammlung tragen:
| was | Repo | wozu |
|---|---|---|
| Projektseite brickfolio.cc | `brickfolio-website` | statischer Cloudflare Worker, von Hand veröffentlicht |
| Katalogdienst | `brickfolio-katalogdienst` | baut den Katalogindex und schreibt ihn verschlĂŒsselt hierher nach `katalog/index.nupplo` |
| Hub-Konsole | `brickfolio-hub-admin` | OberflÀche zur Verwaltung des Tausch-Netzwerks |
| Tausch-Hub | `brickfolio-hub` | Cloudflare Worker + D1, den die Instanzen zum Tauschen ansprechen |
Die App selbst spricht den Hub nur ĂŒber HTTP an; sie braucht seinen
Quelltext nicht.
## Rechtliches
LEGOÂź ist eine Marke der LEGO Gruppe, die dieses Projekt weder sponsert noch
autorisiert oder unterstĂŒtzt. BrickLink, Rebrickable und Brickognize sind
Marken ihrer jeweiligen Inhaber; fĂŒr deren APIs gelten die jeweiligen
Nutzungsbedingungen. Dieses Projekt ist ein privates Hobby-Projekt ohne
kommerzielle Absicht.
Daten und Bilder stammen von Rebrickable (Katalogsuche), BrickLink (Preise,
Set-Inhalte, Bilder) und Brickognize (Bilderkennung â beim Abfotografieren
wird das Foto dorthin ĂŒbertragen). Dieselben Angaben stehen in der App unter
**Mehr â Quellen & Rechtliches**.
Der optionale **Jedipedia-Verweis** (ausgeschaltet voreingestellt) öffnet
einen Artikel der [Jedipedia](https://jedipedia.net/), eines unabhÀngigen
deutschsprachigen Star-Wars-Fanwikis: Es wird nur verlinkt â keine Inhalte
abgerufen, ĂŒbernommen oder gespeichert, und solange niemand das â antippt,
geht nichts dorthin. Welcher Artikel zu welcher Figur gehört, wurde
**einmalig** ĂŒber die MediaWiki-Schnittstelle des Wikis erfragt
(`tools/jedipedia_titel.py`) und liegt als feste Liste bei; im Betrieb
fragt Nupplo dort nichts. Die Artikel stehen unter der GNU-FDL 1.3
und gehören ihren Autoren; die Jedipedia steht in keiner Verbindung zu
diesem Projekt.
### Haftung
Nupplo ist ein privates Hobby-Projekt und wird **âwie besehen"**
bereitgestellt â ohne GewĂ€hr fĂŒr Fehlerfreiheit, VerfĂŒgbarkeit oder Eignung
fĂŒr einen bestimmten Zweck. Soweit gesetzlich zulĂ€ssig, wird keine Haftung
fĂŒr SchĂ€den aus der Nutzung ĂŒbernommen. Das betrifft vor allem drei Dinge:
- **Preise sind Anhaltspunkte, keine Bewertung.** Die Ă-Werte kommen von
BrickLink und schwanken. Sie taugen nicht als Grundlage fĂŒr
Versicherungssummen, Verkaufsentscheidungen oder Angaben gegenĂŒber
Behörden.
- **Die Erkennung kann sich irren.** Was Kamera und Suche vorschlagen, ist
ein Vorschlag â die Zuordnung prĂŒft ihr.
- **Eure Daten liegen bei euch.** Die App hilft beim Sichern, aber Server,
Platte und Sicherung gehören euch. Ein Backup, das nie zurĂŒckgespielt
wurde, ist keines.
Die zwingende Haftung â Vorsatz, grobe FahrlĂ€ssigkeit, PersonenschĂ€den und
Produkthaftung â bleibt davon unberĂŒhrt. Dieselben Angaben stehen in der App
unter **Mehr â Quellen & Rechtliches**.
Die Schrift **Nunito** (SIL Open Font License 1.1, Lizenztext unter
`frontend/fonts/OFL.txt`) wird lokal ausgeliefert â es werden also keine
Besucherdaten an Schrift-CDNs ĂŒbertragen, und die OberflĂ€che sieht auch dann
richtig aus, wenn der Server keine Internetverbindung hat.
### Was ohne Internet funktioniert
Die Sammlung liegt vollstÀndig auf eurem Server, die OberflÀche ebenso. Ist
der Server im Heimnetz erreichbar, aber ohne Internet, geht weiter:
- Sammlung, Wunschliste und Einkaufslisten ansehen und bearbeiten
- manuell erfassen, eigene Figuren samt eigenem Bild
- Statistik, CSV-Export und Drucklisten
- Sicherung herunterladen und einspielen
Auf das Internet angewiesen sind dagegen alle Funktionen, die nach auĂen
fragen: **Scannen** (Brickognize), **Namenssuche** (Rebrickable), **Preise
und Set-Inhalte** (BrickLink), die **Katalogbilder** (sie liegen auf deren
Servern â selbst hochgeladene Bilder nicht), die **Update-PrĂŒfung** und das
**Tausch-Netzwerk**.
Ist gar kein Server erreichbar, lÀdt die installierte PWA zwar noch ihre
OberflĂ€che aus dem Zwischenspeicher, zeigt aber keine Daten â die kommen
immer live vom eigenen Server, nichts davon liegt im Browser.
## UnterstĂŒtzen
Nupplo ist ein privates Hobby-Projekt und kostenlos. Wenn es dir gefÀllt
und du die Entwicklung unterstĂŒtzen magst, freue ich mich ĂŒber einen Kaffee â
## Lizenz
[MIT](LICENSE) fĂŒr den Programmcode. Der Figurenkatalog in `katalog/`
ist ausgenommen: Er darf nur in Nupplo genutzt werden, siehe
[katalog/LIZENZ.md](katalog/LIZENZ.md).