Vorher: nur Treffer ohne SearXNG-Thumbnail wurden mit dem Seiten-Bild
angereichert. Treffer mit Thumbnail behielten das kleine 150-200 px-
Bildchen aus dem Such-Engine-Index.
Jetzt: Alle Treffer durchlaufen die Enrichment-Pipeline. Wenn die Seite
ein og:image/JSON-LD/Content-Bild hat (und das hat sie bei Rezept-Seiten
praktisch immer), wird das kleine SearXNG-Thumbnail damit überschrieben.
Wenn die Seite kein Bild liefert, bleibt das SearXNG-Thumbnail als
Fallback erhalten.
Das ist das gleiche Bild, das auch die Vorschau anzeigt — Suchergebnis
und Vorschau sind jetzt visuell konsistent.
Performance: Pro erster Suche bis zu ~6 Sekunden zusätzliche Latenz
(max 6 parallel, je 4 s Timeout). Der 30-min In-Memory-Cache macht
Wiederholsuchen instant.
Tests (98/98):
- Neu: SearXNG-Thumbnail wird durch og:image ersetzt.
- Neu: SearXNG-Thumbnail bleibt erhalten, wenn Seite kein Bild hat.
- Alt ("leaves existing thumbnails untouched") entfernt — Verhalten
hat sich bewusst umgekehrt.
Startseite:
- Enter/Return löst die Suche jetzt sofort aus (cancelt den Debounce),
navigiert aber NICHT mehr auf /search. Der Anwender bleibt auf der
gleichen Seite mit Inline-Ergebnissen.
Thumbnail-Enrichment (searxng.ts):
- Regex-basierte og:image-Extraktion durch linkedom-parseHTML ersetzt.
- Neue Fallback-Kette (in dieser Reihenfolge):
1. <meta property/name = og:image | og:image:url | og:image:secure_url
| twitter:image | twitter:image:src>
2. <link rel="image_src" href="...">
3. JSON-LD image (auch tief in @graph; "image" als String, Array,
Objekt-mit-url)
4. Erstes <img> in article/main/.entry-content/.post-content/figure
- Relative URLs werden gegen die Seiten-URL zu absoluten aufgelöst
(z.B. /uploads/foo.jpg → http://host/uploads/foo.jpg).
- maxBytes von 256 KB auf 512 KB angehoben, damit JSON-LD-lastige
Recipe-Seiten nicht mitten im Script abgeschnitten werden.
Tests (97/97):
- Neu: JSON-LD-Image-Fallback-Test.
- Neu: Content-<img>-Fallback-Test mit relativer URL, die zur
absoluten aufgelöst wird.
SearXNG liefert je nach Seite mal ein thumbnail/img_src mit, mal nicht —
bei Chefkoch-Treffern hatten deshalb zufällig die Hälfte der Kacheln
einen Platzhalter, obwohl die Vorschau dann sehr wohl ein Bild fand.
searchWeb() holt jetzt für jeden Treffer ohne Thumbnail parallel
(max. 6 gleichzeitig, 4 s Timeout pro Request) die Seite und extrahiert
das og:image- oder twitter:image-Meta-Tag. Ergebnis wird 30 min
in-memory gecacht, damit wiederholte Suchen nicht wieder die gleichen
Seiten laden.
Tests:
- Neuer Test: Treffer ohne Thumbnail wird via og:image angereichert.
- Neuer Test: Treffer mit Thumbnail bleibt unverändert (keine Fetch).
- Bestehende Tests deaktivieren Enrichment via enrichThumbnails:false,
damit sie keine echten Chefkoch-URLs aufrufen.
Each recipe appears at most once on the wishlist. Any profile can add,
remove, like, and unlike. Ratings and cooking log stay independent.
Data model: wishlist(recipe_id PK, added_by_profile_id, added_at)
wishlist_like(recipe_id, profile_id, created_at)
Why: 'das will ich essen' — family members pick candidates, everyone
can +1 to signal agreement, cook decides based on popularity.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Blocks common non-recipe paths like /forum/, /magazin/, /suche/, /themen/,
Chefkoch's /rs/s\d+/ search URLs and /Rezepte.html listings.
Before: 'ravioli' search returned forum threads and listing pages that
triggered 'No schema.org/Recipe JSON-LD' on preview.
After: only real recipe URLs pass through.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>