From 3967544de7207ea7dfe6aa3bad86c1945fcdfa45 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 12 May 2026 19:24:19 +0200 Subject: [PATCH 1/6] =?UTF-8?q?Fix:=20routes.js=20SyntaxError=20=E2=80=94?= =?UTF-8?q?=20=5FstartRecInOvl=20als=20async=20deklariert=20(SW=20by-v886)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit await _recAcquireWakeLock() in nicht-async Funktion → SyntaxError → ganzes Modul crashte → Fallback "Seite in Entwicklung" auf Production. --- backend/main.py | 2 +- backend/static/js/app.js | 2 +- backend/static/js/pages/routes.js | 2 +- backend/static/sw.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/main.py b/backend/main.py index 456dc43..6bb7070 100644 --- a/backend/main.py +++ b/backend/main.py @@ -406,7 +406,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "885" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "886" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 9c1a424..987ac82 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '885'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '886'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/js/pages/routes.js b/backend/static/js/pages/routes.js index 21e5d6e..32186f9 100644 --- a/backend/static/js/pages/routes.js +++ b/backend/static/js/pages/routes.js @@ -700,7 +700,7 @@ window.Page_routes = (() => { ovl.querySelector('#rk-rec-startbtn').addEventListener('click', _startRecInOvl); } - function _startRecInOvl() { + async function _startRecInOvl() { if (!navigator.geolocation) { UI.toast.error('GPS nicht verfügbar.'); return; } _recActive = true; _recTrack = []; _recDistKm = 0; _recStartTime = Date.now(); diff --git a/backend/static/sw.js b/backend/static/sw.js index 4bb5047..61187c5 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v885'; +const CACHE_VERSION = 'by-v886'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache From b8f70eb2cdc7466b1d97c6937ef4261d0f0acc9f Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 12 May 2026 19:29:04 +0200 Subject: [PATCH 2/6] =?UTF-8?q?Fix:=20SW-Update=20doppelter=20Reload=20nac?= =?UTF-8?q?h=20force-update=20=E2=80=94=20controllerchange=20konsumiert=20?= =?UTF-8?q?by=5Fskip=5Fsw=5Freload=20Flag=20(SW=20by-v887)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit statechange-activated und controllerchange feuern beide beim SW-Update. statechange konsumierte den Flag und controllerchange reloadete trotzdem. Jetzt prüft statechange nur, controllerchange konsumiert. --- backend/main.py | 2 +- backend/static/index.html | 12 +++++++----- backend/static/js/app.js | 2 +- backend/static/sw.js | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/main.py b/backend/main.py index 6bb7070..e02d63d 100644 --- a/backend/main.py +++ b/backend/main.py @@ -406,7 +406,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "886" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "887" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/static/index.html b/backend/static/index.html index cc215cf..557467a 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -637,11 +637,8 @@ if (!sw) return; sw.addEventListener('statechange', () => { if (sw.state === 'activated') { - // Kein zweiter Reload nach force-update - if (sessionStorage.getItem('by_skip_sw_reload')) { - sessionStorage.removeItem('by_skip_sw_reload'); - return; - } + // Flag nur prüfen, nicht konsumieren — controllerchange konsumiert ihn + if (sessionStorage.getItem('by_skip_sw_reload')) return; window.location.replace('/?_t=' + Date.now()); } }); @@ -663,7 +660,12 @@ }); // Backup: controllerchange (falls updatefound nicht feuert) + // Konsumiert auch den by_skip_sw_reload-Flag (statechange prüft ihn nur) navigator.serviceWorker.addEventListener('controllerchange', () => { + if (sessionStorage.getItem('by_skip_sw_reload')) { + sessionStorage.removeItem('by_skip_sw_reload'); + return; + } window.location.replace('/?_t=' + Date.now()); }); diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 987ac82..fc381d6 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '886'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '887'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/sw.js b/backend/static/sw.js index 61187c5..501b993 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v886'; +const CACHE_VERSION = 'by-v887'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache From 7257c9e04f7ac91cb4c9d65f9480db6710aa14b9 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 12 May 2026 19:35:42 +0200 Subject: [PATCH 3/6] =?UTF-8?q?Fix:=20SW-Update=20Dauerschleife=20?= =?UTF-8?q?=E2=80=94=20controllerchange=20nicht=20auf=20Reload-Seiten=20re?= =?UTF-8?q?gistrieren=20(SW=20by-v888)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit clients.claim() feuert asynchron nach Seitenstart → controllerchange auf der neu geladenen Seite → Reload → clients.claim() → loop. Fix: controllerchange nur registrieren wenn _t= NICHT im URL steht. --- backend/main.py | 2 +- backend/static/index.html | 19 +++++++++++-------- backend/static/js/app.js | 2 +- backend/static/sw.js | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/backend/main.py b/backend/main.py index e02d63d..f3955d6 100644 --- a/backend/main.py +++ b/backend/main.py @@ -406,7 +406,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "887" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "888" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/static/index.html b/backend/static/index.html index 557467a..2cbf257 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -660,14 +660,17 @@ }); // Backup: controllerchange (falls updatefound nicht feuert) - // Konsumiert auch den by_skip_sw_reload-Flag (statechange prüft ihn nur) - navigator.serviceWorker.addEventListener('controllerchange', () => { - if (sessionStorage.getItem('by_skip_sw_reload')) { - sessionStorage.removeItem('by_skip_sw_reload'); - return; - } - window.location.replace('/?_t=' + Date.now()); - }); + // NICHT registrieren wenn diese Seite selbst durch einen SW-Reload entstand (_t= im URL) + // — verhindert Dauerschleife wenn clients.claim() erst nach Seitenstart feuert + if (!location.search.includes('_t=')) { + navigator.serviceWorker.addEventListener('controllerchange', () => { + if (sessionStorage.getItem('by_skip_sw_reload')) { + sessionStorage.removeItem('by_skip_sw_reload'); + return; + } + window.location.replace('/?_t=' + Date.now()); + }); + } navigator.serviceWorker.addEventListener('message', e => { if (e.data?.type === 'QUEUE_PROCESSED') { diff --git a/backend/static/js/app.js b/backend/static/js/app.js index fc381d6..cae6c71 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '887'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '888'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/sw.js b/backend/static/sw.js index 501b993..06d0d08 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v887'; +const CACHE_VERSION = 'by-v888'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache From 437901b8e226f586a133cf96ec9e09f3898444b8 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 12 May 2026 19:40:50 +0200 Subject: [PATCH 4/6] =?UTF-8?q?Fix:=20Update-Loop=20=E2=80=94=20index.html?= =?UTF-8?q?=20Script-Tags=20auf=20APP=5FVER=20synchronisiert=20(SW=20by-v8?= =?UTF-8?q?89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: ?v=885 in Script-Tags → Browser cached app.js immutable für 1 Jahr. Nach force-update (löscht nur SW-Cache, nicht Browser-HTTP-Cache) lädt Browser alte app.js mit APP_VER=885 → X-App-Version: 889 Mismatch → Endlosschleife. Ab jetzt: ?v= in index.html IMMER mit APP_VER synchron halten. --- backend/main.py | 2 +- backend/static/index.html | 8 ++++---- backend/static/js/app.js | 2 +- backend/static/sw.js | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/main.py b/backend/main.py index f3955d6..5e78c9a 100644 --- a/backend/main.py +++ b/backend/main.py @@ -406,7 +406,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "888" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "889" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/static/index.html b/backend/static/index.html index 2cbf257..0fd8c6e 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -583,10 +583,10 @@ - - - - + + + + diff --git a/backend/static/js/app.js b/backend/static/js/app.js index cae6c71..0c24103 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '888'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '889'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/sw.js b/backend/static/sw.js index 06d0d08..1941d2a 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v888'; +const CACHE_VERSION = 'by-v889'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache From a5b81745661633c707de5980cd4016fff529bc02 Mon Sep 17 00:00:00 2001 From: rene Date: Tue, 12 May 2026 19:41:26 +0200 Subject: [PATCH 5/6] =?UTF-8?q?Fix=20permanent:=20JS/CSS=20nie=20immutable?= =?UTF-8?q?=20cachen=20=E2=80=94=20verhindert=20Update-Loop=20(SW=20by-v89?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Browser-HTTP-Cache mit immutable lässt sich nach force-update nicht leeren. Veraltete app.js (APP_VER alt) führt zu X-App-Version Mismatch → Dauerschleife. SW übernimmt Caching sowieso → no-cache für alle JS/CSS ist sicher. --- backend/main.py | 12 +++++------- backend/static/index.html | 8 ++++---- backend/static/js/app.js | 2 +- backend/static/sw.js | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/backend/main.py b/backend/main.py index 5e78c9a..4498809 100644 --- a/backend/main.py +++ b/backend/main.py @@ -156,17 +156,15 @@ app.add_middleware(_AppVersionMiddleware) class _CacheControlMiddleware(BaseHTTPMiddleware): """Setzt Cache-Control-Header für statische Assets. - CSS/JS: no-cache (ETag-Validierung) — iOS cached sonst ewig ohne Ablaufdatum. - Versioned Assets (?v=…): immutable — URL ändert sich bei Updates. + JS/CSS: immer no-cache — SW übernimmt Caching. Immutable wäre gefährlich, + weil Browser-HTTP-Cache nach force-update nicht geleert wird und veraltete + app.js mit falschem APP_VER eine Update-Dauerschleife verursacht. """ async def dispatch(self, request: Request, call_next): response = await call_next(request) path = request.url.path if path.startswith(("/css/", "/js/", "/icons/phosphor.svg")): - if "v=" in str(request.url.query): - response.headers["Cache-Control"] = "public, max-age=31536000, immutable" - else: - response.headers["Cache-Control"] = "no-cache, must-revalidate" + response.headers["Cache-Control"] = "no-cache, must-revalidate" return response app.add_middleware(_CacheControlMiddleware) @@ -406,7 +404,7 @@ async def serve_media(path: str, request: _Request): raise _HE(404, "Nicht gefunden.") return _media_response(filepath) -APP_VER = "889" # muss mit APP_VER in app.js übereinstimmen +APP_VER = "890" # muss mit APP_VER in app.js übereinstimmen @app.get("/.well-known/assetlinks.json") async def assetlinks(): diff --git a/backend/static/index.html b/backend/static/index.html index 0fd8c6e..39016d0 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -583,10 +583,10 @@ - - - - + + + + diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 0c24103..d701647 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '889'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '890'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt const IS_STAGING = location.hostname === 'staging.banyaro.app'; // Cache-Bust-Parameter nach Update-Reload sofort entfernen diff --git a/backend/static/sw.js b/backend/static/sw.js index 1941d2a..250e7b2 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -3,7 +3,7 @@ Offline-Cache + Push Notifications + Tile-Cache ============================================================ */ -const CACHE_VERSION = 'by-v889'; +const CACHE_VERSION = 'by-v890'; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache From e8c2d5b940420274d3864cd589102117a729a7ec Mon Sep 17 00:00:00 2001 From: rene Date: Wed, 13 May 2026 16:26:19 +0200 Subject: [PATCH 6/6] =?UTF-8?q?Feature:=20Z=C3=BCchter-Landing-Page=20/zue?= =?UTF-8?q?chter=20=E2=80=94=20SEO,=20Vergleich,=20Features,=20CTA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/main.py | 5 + backend/static/zuechter.html | 572 +++++++++++++++++++++++++++++++++++ 2 files changed, 577 insertions(+) create mode 100644 backend/static/zuechter.html diff --git a/backend/main.py b/backend/main.py index 4498809..f819647 100644 --- a/backend/main.py +++ b/backend/main.py @@ -521,6 +521,11 @@ async def info_page(): return FileResponse(f"{STATIC_DIR}/landing.html", headers={"Cache-Control": "max-age=3600"}) +@app.get("/zuechter") +async def zuechter_landing(): + return FileResponse(f"{STATIC_DIR}/zuechter.html", headers={"Cache-Control": "max-age=3600"}) + + # ------------------------------------------------------------------ # SEO: Server-gerenderete Wiki-Rassen-Übersicht /wiki/rassen # ------------------------------------------------------------------ diff --git a/backend/static/zuechter.html b/backend/static/zuechter.html new file mode 100644 index 0000000..88f5b74 --- /dev/null +++ b/backend/static/zuechter.html @@ -0,0 +1,572 @@ + + + + + + Ban Yaro für Züchter — Zucht-Management für seriöse Hundezüchter + + + + + + + + + + + + + + + + + + +
+
+ +

Für Züchter

+

Zucht-Management für
seriöse Hundezüchter

+

Stammbaum, IK-Berechnung, Gesundheitstests, Wurfverwaltung, Kaufvertrag, KI-Assistent — alles in einer App. Kostenlos. In Deutschland.

+
+ Kostenlos starten + Server in Deutschland + DSGVO-konform + VDH-kompatibel + Kein App Store nötig +
+ Jetzt als Züchter registrieren + Alle Features ansehen ↓ +
+
+ + + + +
+
+ Das kennen alle Züchter +

Züchten ist ein Vollzeitjob.
Die Verwaltung dazu auch.

+

Gesundheitstests in einer Tabelle, Wurfgewichte in einer anderen, Käufer in WhatsApp, Kaufvertrag in Word. Nichts ist verknüpft. Das kostet Zeit — die du besser mit deinen Hunden verbringst.

+
+
+
📊
+

Excel-Chaos

+

Welpengewichte in einer Datei, Gesundheitstests in einer anderen, Kosten irgendwo sonst. Nichts hängt zusammen.

+
+
+
🧮
+

IK manuell berechnen

+

Inzuchtkoeffizient vor der Verpaarung prüfen? Drei Websites, manuelles Eintippen der Ahnentafel, Kopfrechnen.

+
+
+
📱
+

Warteliste in WhatsApp

+

Wer wollte ein Mädchen? Wer hat wann angefragt? Wer steht wo auf der Liste? Alles in Chatverläufen vergraben.

+
+
+
📝
+

Kaufvertrag kopieren

+

Altes Word-Dokument öffnen, Namen ändern, vergessen zwei Felder anzupassen, ausdrucken, faxen.

+
+
+
+

ECVO vergessen

+

Der Augentest muss jährlich erneuert werden. Wann war der letzte? Irgendwo auf einem Zettel steht das Datum.

+
+
+
💸
+

Was hat der Wurf gekostet?

+

Deckgebühr, Progesterontests, Tierarzt, Futter, Material — kein Züchter kann das am Ende wirklich sagen.

+
+
+
+
+ + +
+
+ Features +

Alles was seriöse Züchter brauchen.
In einer App.

+

Von der Zuchtzulassung bis zur Welpenabgabe — Ban Yaro begleitet jeden Schritt. Kostenlos, ohne Installation, von jedem Gerät.

+ + +

Zuchtkartei & Genetik

+
+
+ +
+

Stammbaum bis 4 Generationen

+

Grafische Darstellung aller Vorfahren — Vater, Mutter, Großeltern, Urgroßeltern. Sofort sichtbar welche Linien sich kreuzen.

+
+
+
+ +
+

Inzuchtkoeffizient nach Wright

+

Automatische IK-Berechnung über 8 Generationen. Ampel-Bewertung: optimal · akzeptabel · erhöht · kritisch. Keine Website, kein Kopfrechnen.

+ Einzigartig +
+
+
+ +
+

Probeverpaarung

+

IK simulieren bevor du den Deckrüden anfragst. Welche Kombination ist genetisch am besten? Sofort sichtbar.

+ Einzigartig +
+
+
+ +
+

Gesundheitstests

+

HD, ED, OCD, Augen (ECVO), Herz, Patella, ZTP — mit Datum, Gutachter, Zertifikatsnummer, Gültigkeitsdatum und automatischen Erinnerungen.

+
+
+
+ +
+

Gentests & Risikoanalyse

+

MDR1, PRA, DM, vWD und weitere Marker. Automatische Risikoanalyse für die Kombination: klar × Träger × betroffen — welche Nachkommen sind zu erwarten?

+
+
+
+ +
+

Titel & Auszeichnungen

+

Ausstellungs-, Arbeits-, Sport-, Zucht- und Champion-Titel dokumentieren — mit Datum, Richter, Formwert. Für den öffentlichen Steckbrief des Hundes.

+
+
+
+ + +

Wurfverwaltung & Welpen

+
+
+ +
+

Wurfverwaltung

+

Jeden Wurf anlegen mit geplanten und tatsächlichem Geburtsdatum, Elterntieren, Anzahl Welpen und Verfügbarkeitsstatus.

+
+
+
+ +
+

Welpengewichte & Entwicklung

+

Tägliche Gewichtserfassung für jeden Welpen einzeln. Wachstumskurve auf einen Blick — aus dem Smartphone heraus am Wurfplatz.

+
+
+
+ +
+

Fotos für jeden Welpen

+

Fotos hochladen und je Welpe zuordnen — mit Sichtbarkeitssteuerung: öffentlich, nur auf Anfrage oder privat.

+
+
+
+ +
+

Kaufvertrag-Generator

+

Rechtssicherer Kaufvertrag automatisch befüllt — Züchter, Käufer, Welpe, Chip, Gesundheitsstatus, Impfungen. Zum Ausdrucken oder digital unterschreiben.

+ Automatisch +
+
+
+ +
+

Tierschutz-Check

+

Automatische Bewertung jeder Verpaarung auf Basis von IK und Gentests. Bei kritischen Werten: Warnung und Admin-Meldung. Verantwortungsvolle Zucht by Default.

+ Einzigartig +
+
+
+ +
+

Datenexport

+

Kompletten Zuchtbericht als HTML (druckbereit, mit Stammbaum) oder ODS-Spreadsheet (für Excel/LibreOffice) exportieren. Deine Daten gehören dir.

+
+
+
+ + +

KI-Assistent & Präsenz

+
+
+ +
+

KI-Wurfankündigung

+

Professioneller Ankündigungstext für deinen Wurf — aus den Elterndaten, Gesundheitstests und Linienbeschreibung. In Sekunden, anpassbar.

+ KI +
+
+
+ +
+

KI-Paarungsanalyse

+

KI bewertet die geplante Verpaarung: IK, Gesundheitsprofil beider Eltern, genetische Risiken — mit klarer Empfehlung: empfohlen / bedingt / nicht empfohlen.

+ KI +
+
+
+ +
+

Öffentliche Wurfbörse

+

Deine verfügbaren Würfe erscheinen automatisch in der Banyaro-Wurfbörse — für über tausend Hundebesitzer sichtbar, filterbar nach Rasse.

+
+
+
+ +
+

Öffentliches Züchter-Profil

+

Dein Zwingername, deine Rassen, deine verifizierten Zuchthunde — öffentlich einsehbar für Käufer die aktiv nach deiner Linie suchen.

+
+
+
+ +
+

KI-Jahresbericht

+

Automatischer Jahresrückblick für deinen Zuchtstätte: Würfe, Gesundheitstrends, Auszeichnungen — als professionelles Dokument.

+ KI +
+
+
+ +
+

Genetik-Erklärung für Käufer

+

Komplizierte Gentestergebnisse in verständlichem Deutsch für Käufer erklärt — automatisch, auf Knopfdruck.

+ KI +
+
+
+
+
+ + +
+
+ Marktvergleich +

Was andere können.
Was nur Ban Yaro kann.

+

Der deutsche Markt für Züchter-Software ist dünn. Hier ein ehrlicher Vergleich mit den relevantesten Alternativen.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
FeatureBan YaroWebreedPuppy CenterHundescout
Stammbaum grafisch
IK-Berechnung (Wright)✓ 8 Gen.
Probeverpaarung mit IK
Gesundheitstests (HD, ED, …)✓ 7 Typen
Gentests + Risikoanalyse
Tierschutz-Check automatisch
Wurfverwaltung + Welpen
Kaufvertrag-Generator
KI-Assistent (Texte, Analyse)✓ 5 Features
Käufer nutzen dieselbe App
Native Mobile App✓ iOS + AndroidWebWindows only
Deutschsprachig
Server in DeutschlandFrankreich
Kostenlos starten✓ (mit Werbung)✓ (1 Hündin)ab 99 €
+
+
+
+ + +
+
+ Der entscheidende Unterschied +

Züchter und Käufer.
In einer App.

+

Kein anderes Züchter-Tool kann das: Webreed, Hundescout, Breedera — sie alle enden bei der Welpenabgabe. Was danach kommt, passiert woanders.

+ +
+

Der Welpe geht mit.

+

+ Ein Käufer der Ban Yaro nutzt kann deinen Wurf direkt in der App entdecken, anfragen und den Welpen reservieren. + Bei der Abgabe überträgst du das komplette Profil — Gewichtsverlauf, alle Impfungen, Gesundheitsstatus, Stammbaum — + direkt in die App des Käufers. Kein PDF, kein Papierstapel, kein vergessener Impfausweis. + Der Käufer hat alles. Und bleibt mit dir verbunden. +

+
+ +
+
+ +
+

Community die dich findet

+

Über tausend aktive Hundehalter nutzen Ban Yaro — die deinen Wurf in der Wurfbörse sehen, ohne dass du Werbung schalten musst.

+
+
+
+ +
+

Nachsorge ohne Aufwand

+

Käufer können dich direkt in der App kontaktieren. Wie entwickelt sich der Welpe? Hat er Fragen? Du bist erreichbar — ohne WhatsApp-Chaos.

+
+
+
+ +
+

Verifizierter Züchter-Badge

+

Nach Prüfung durch unser Team bekommst du den Verifiziert-Badge. Das schafft Vertrauen — und unterscheidet dich klar von Vermehrern.

+
+
+
+
+
+ + +
+
+ So einfach geht's +

In 10 Minuten startklar.

+

Kein App Store, keine Installation. Ban Yaro läuft im Browser — auf dem Smartphone genauso wie am Laptop.

+
+
+

Registrieren

+

Konto anlegen und Züchter-Antrag stellen — dauert 2 Minuten. E-Mail + Zwingername reicht für den Anfang.

+
+
+

Verifiziert werden

+

Wir prüfen deinen Antrag und schalten deinen Züchter-Bereich frei — meist innerhalb von 24 Stunden.

+
+
+

Zuchthunde anlegen

+

Deine Zuchthündinnen und -rüden mit Gesundheitstests, Gentests und Titeln erfassen. Der Stammbaum baut sich automatisch auf.

+
+
+

Ersten Wurf eintragen

+

Wurf anlegen, Welpen erfassen, Gewichte tracken, Fotos hochladen — und direkt in der Wurfbörse veröffentlichen.

+
+
+
+
+ + +
+
+ Vertrauen & Datenschutz +

Deine Zuchtdaten. Dein Eigentum.

+

Genealogiedaten, Gesundheitszertifikate, Kaufverträge — das sind sensible Informationen. Sie gehören dir, nicht uns.

+
+
+ +
+

Server in Deutschland

+

Alle Daten liegen auf unserem Server in Deutschland. Kein US-Anbieter, kein Drittland-Transfer. DSGVO-konform by Default.

+
+
+
+ +
+

Vollständiger Datenexport

+

Alle deine Daten jederzeit als HTML oder ODS exportieren. Du bist nie eingesperrt — deine Zuchtdaten gehören dir.

+
+
+
+ +
+

Sichtbarkeit selbst steuern

+

Gesundheitstests, Fotos, Welpen-Status — für jeden Eintrag bestimmst du: öffentlich, nur auf Anfrage, oder privat.

+
+
+
+ +
+

Echter Ansprechpartner

+

hallo@banyaro.app — kein Ticket-System, kein Bot. René antwortet persönlich.

+
+
+
+
+
+ + +
+
+

Jetzt kostenlos starten.

+

Züchter-Antrag stellen, Zuchthunde anlegen, ersten Wurf veröffentlichen — alles kostenlos, kein App Store, keine Kreditkarte.

+ Als Züchter registrieren +

Fragen? hallo@banyaro.app

+
+
+ + + + +