Nupplo

# 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* [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-ffdd00?logo=buymeacoffee&logoColor=black)](https://buymeacoffee.com/melle79) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](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 | |:---:|:---:| | Scan-Treffer mit Kaestchen fuer das eigene Foto | Sammlung | | **Statistik** | **Einkaufsliste (Flohmarkt-Modus)** | | Statistik | Einkaufsliste | | **Eigene Fotos in der Galerie** | **Sicherung samt Bildern** | | Galerie mit eigenen Fotos | Sicherung mit eigenen 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** | [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](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 ☕ Buy Me a Coffee ## 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).