- Remove _fetch_pixabay_api_image() function entirely
- Tier 6 (Pixabay) removed from _enrich_one_item — falls through to Pexels
- Re-enrich all items across Tokyo, Kyoto, Osaka, London with Pixabay-free pipeline
- Update all docstrings and tier references
- Zero Pixabay URLs remaining in cache for these cities
Source breakdown after repair:
Tokyo: 123 Wikimedia + 4 Pexels/Unsplash
Kyoto: 120 Wikimedia + 13 Pexels/Unsplash
Osaka: 96 Wikimedia + 37 Pexels/Unsplash
London: 110 Wikimedia + 23 Pexels/Unsplash
fix: content-hash dedup with _MAX_STOCK_SHARING=4 — eliminate duplicate photos in Oslo, Osaka, Marrakech, Hanoi, Prague, Madrid caches
- After Pixabay returns an image, re-check English Wikipedia and
Wikidata tiers in case they were rate-limited on first pass
- Added multi-language Wikipedia tier (fr/de/es/it/ja) as Tier 2
- Fixed cache check to skip empty-string entries (re-try failed items)
- Cache: non-empty URLs only — empty cache entries no longer block retries
feat: fast offline translations via deep-translator with parallel HTTP
Adds _translate_items_deep() which translates attraction text fields
using Google Translate via the deep-translator library. Uses
ThreadPoolExecutor (15 workers) to parallelize HTTP calls — translates
19 items × 4 fields (76 texts) in ~3-6s instead of ~45s.
Falls back to existing LLM translation for unsupported languages.
Existing JP/TC cache is preserved.
- Consolidate 4 JSON cache files into .cache/ folder
- Update all path references in recommender.py and 3 scripts
- Update README.md with new cache paths
v0.1.21 — Remove hermes docs from repo, dark theme fix, Tokyo default
- Remove hermes-plan.md, hermes-progress-log.md, .hermes-commit-approved from git tracking
- dark_theme.py: remove CSS @media fallback + JS polling, first card auto-expand on stack
- streamlit_app.py: default city changed to Tokyo
- .gitignore: consolidate 8 log patterns into single *.log, add .repair_progress.json
- recommender.py: expand docstrings on _geocode_city and _parse_json_response
- streamlit_app.py: warn user when all results fail location verification
- setInterval every 1s checks if narrow/wide state changed
- Catches cases where resize/MutationObserver events don't propagate
through nested iframe sandbox on huggingface.co/spaces/...
- Only triggers update when state actually changes (no unnecessary work)
Add @media (max-width: 768px) fallback for HF Spaces iframe stacking
- Stacking JS uses window.parent which fails when app is embedded
in a sandboxed cross-origin iframe (HF Spaces)
- Added CSS @media fallback to stack columns + hide map at ≤768px
- JS still handles card collapsing, search controls 4-row layout,
and responsive panel heights when it can reach the parent
- Added [data-testid="stAppViewContainer"] padding/margin: 0
- Added section.main margin/padding: 0
- Increased .main > div:first-child margin-top from -8px to -20px
- This removes the ~25px gap Streamlit inserts at the page top
Fix card images showing grey bottom 1/3 on iPhone
- Removed max-height: 120px on .card-img in @media (max-width: 480px)
- The 16/9 aspect-ratio container was ~219px tall at full-width on iPhone
but the image was capped at 120px, revealing grey background below
- Images now fill the full aspect-ratio container correctly
- Separated collapseCards() from updateStack()
- MutationObserver now only calls updateStack() (layout: map hide/show,
search controls) — NEVER collapses cards
- collapseCards() only fires on load and resize, not on every DOM mutation
- This prevents the MutationObserver from instantly re-collapsing a card
the user just tapped to expand
- FLEX_PANELS_JS now checks for stack-columns class on body
- In narrow mode, cards container height set to 'auto' (no scroll cap)
- In narrow mode, max-height set to 'none' so all 6 cards are visible
- Parent LayoutWrapper height also cleared for consistency
- Changed stacking threshold from screen.width*0.50 to fixed 768px
breakpoint (old formula gave ~195px on iPhone — stacking never fired)
- Added MutationObserver to re-run stacking when Streamlit injects cards
and map via websocket after page load
- Map now hidden via inline JS style.setProperty in addition to CSS
- Card collapse retriggers on DOM mutations, not just window.load
Replace fragile md5(content-hash) key with deterministic
(city, cat_hash, language) key. Survives image enrichment,
field re-ordering, and any content-level changes. Fixes
translation spinner on any language switch (e.g. Japanese
-> Traditional Chinese).
v0.0.10b — Fix translation cache miss on sliced items
- Root cause: max_tokens=2048 truncated LLM output, dropping _local fields
- Fixed: bumped to 8192 in translate_items()
- Enhanced prompt + auto-retry with warning when _local fields missing
- All 28 Tokyo/Kyoto combos translated (14× Japanese + 14× Traditional Chinese)
- Full 4 _local fields present on every item
Added _is_media_entertainment_page() check in _fetch_wiki_image to
skip film, TV, video game, and album pages that may share names
with real attractions (e.g. 'Dishoom' Bollywood film vs Dishoom
London restaurant). Falls through to next candidate when detected.
Also cleared the cached Dishoom poster entry so it re-fetches.
Persist translation cache to disk + prewarm script
Items that can't find a specific image now get image_url='' instead
of sharing a generic city photo. Frontend already shows 🏛️ emoji
fallback for empty image_url.
Also added 10 new cities to warmup queue.
Fix Wikipedia Commons thumbnail URLs: 400px -> 500px (valid size)
- Bumped pithumbsize from 400 to 500 in REST API call
- Changed fallback Commons URL construction to use 500px-
- Rewrote 78 cached image URLs in both caches to 500px
Root cause: Wikipedia Commons restricted /Npx- thumbnail sizes;
only 500px and 1280px are accepted now (400px returns HTTP 400).
Improve image enrichment: city context in Tier 1 + smarter warmup health check
- _fetch_wiki_image() now accepts city param — tries '{name}, {city}'
and '{name} ({city})' search queries when bare name yields few candidates
- _enrich_one_item() passes city to Tier 1 (was only used by Tiers 2-6)
- check_items() in warmup: 3-pass fix (missing → fallback replace → retry),
detects city-level fallback images shared by >=3 items and replaces them
- New --fix mode: re-check existing cached images without LLM calls
(python scripts/warmup.py --fix --city Tokyo)
- Image cache cleaned: 540 → 519 entries (transients removed)
Unified warmup script + provider observability + Tokyo caches
- New scripts/warmup.py: unified warmup with per-combo checkpointing
(saves all 3 caches after every combo), per-provider logging,
health check + duplicate detection built in, resumable progress
- Added provider_log parameter to get_recommendations() and
get_recommendations_cached() — captures provider name, model,
status, timing, item count per attempt
- Added duplicate image detection to check_cache.py (fallback fix)
- Tokyo caches populated: all 7 categories (19 or 16 items each)
- LLM 44, Images 543, Geocode 142 entries
Fix map growing bug — guard flag + CSS max-height cap to prevent resize feedback loop
Add conditional extra_body parameter to disable internal reasoning
trace at the API level for Ollama Cloud model. Applied to all 3 API
call sites: _call_model, _verify_with_model, and translate_items.
Other providers (OpenRouter, Gemini) are unaffected.
feat: switch primary provider to Ollama Cloud DeepSeek V4 Flash