Releases: TomSchmidtDev/visualizer-lite
Release list
v1.17.0
What's new
Added
- Pre-commit i18n validation:
scripts/check-i18n.mjs+ husky v9 pre-commit hook validates all statict('...')calls against bothde.jsonanden.json, and checks that both files have identical key sets. Dynamic keys (template literals) emit a warning but do not block the commit. Calls with extra arguments (t('key', { count })) are also validated.
Fixed
- Missing translation keys:
shots.profileTitleandshots.grinderModelwere used inSearchBar.tsxfilter chips but were absent from bothde.jsonanden.json(discovered by the new validation script).
See CHANGELOG.md for the full history.
v1.16.0
What's new
Fixed
- i18n — complete DE/EN separation: All remaining hardcoded German/English strings in UI components replaced with
t()calls: context window labels in AnalysisPanel (7 T,30 T,Alle→ translated), Roaster tab label, theme toggle, filter chips (Röster:,Profil:,Mühle:), shot title and error fallbacks in ShotCard, ShotDetail, ShotCompare, Stats - Password change form: New password must now be entered twice for confirmation; mismatch is caught client-side before the API request
Added
- Synology NAS installation guides: Step-by-step guides in English (docs/synology-installation.md) and German (docs/synology-installation.de.md) — Task Scheduler method (no SSH, with screenshots) and SSH method
Changed
- README screenshot gallery: Updated with new high-quality screenshots covering shot list, extraction curves, statistics dashboard, shot comparison (overlaid + split), AI analysis (Barista + Roaster perspectives), and all settings tabs
- Architecture section: Added link to AI analysis documentation (
docs/ai-analysis.md)
v1.15.0 — AI Analysis: Context Transparency, Timing, i18n
What's new in v1.15.0
New Features
- Historical context visible: New first metadata row shows how many shots were passed to the AI as a comparison baseline (avg pressure, avg flow, avg temperature, matching tier)
- Collapsible details: Timing + tokens/cost behind a ▸ toggle; row 1 (timestamp + context) always visible
- Configurable context window: 7d / 30d / 90d / All in Settings → AI Analysis
- Configurable matching thresholds: Tier-1 minimum and minimum shot count are adjustable
- Full i18n: All AI analysis strings translated in DE + EN
Fixes
- AI now responds in the configured language (explicit language instruction added to all system prompts)
- Accept-Language header is now parsed correctly (including German as secondary language)
- Timing fields now correctly returned from cache path
- Tier-1 threshold raised to ≥ 10 shots (prevents misleading small-sample results)
- Stale "Analyst" instruction removed from default prompt
Upgrade
Standard Docker Compose update — no manual DB migrations required (run automatically on startup).
v1.13.2
Bug Fix
AI analysis crash: React Error #31 when model returns objects instead of strings
The optimised analysis mode occasionally made the model return structured objects like {"phase": "Extraction", "finding": "...", "action": "..."} instead of plain strings in the barista/roaster arrays. React then crashed with Error #31 ("Objects are not valid as a React child").
Root cause: The optimised system prompt showed {"barista":[...],...} without an explicit string example — the model interpreted the instruction to "reference phase names" as a reason to build structured objects.
Fix (three layers):
- All four system prompts (standard/optimised × DE/EN) now show string examples and explicitly state: "Each entry must be a plain text string — NOT an object, NOT nested JSON."
- New
normalizeAnalysisArray()function converts any object entries to readable strings (phase — finding — action) at the API boundary — runs on both fresh responses and cached results, so already-stored bad analyses are fixed on next view without regenerating. AnalysisPanelrenders defensively as a last-resort fallback.
v1.13.1
Bug Fix
AI analysis: profile- and bean-scoped historical baseline
Previously the historical context (avg pressure, flow, temperature shown at the bottom of the analysis prompt) was computed from all shots in the time window — mixing completely different profiles. A Turbo shot and a Blooming Flow shot have fundamentally different extraction characteristics, making cross-profile averages meaningless.
New behaviour (tiered matching):
- Same profile & bean —
profileTitle+beanBrand+beanTypemust all match (most accurate baseline) - Fallback: same profile — if fewer than 2 shots match on profile+bean, match by profile only
- No context — if no
profileTitleis set, or fewer than 2 matching shots exist
The prompt now labels which tier matched, e.g.:
History (14 shots, same profile & bean): pres=9.1bar · flow=1.9ml/s · temp=93.2°C
v1.13.0
What's New
Settings tabbed navigation — The Settings page is now organized into 4 labeled tabs with icons:
- 🎨 Ansicht — Language, Theme, Statistics
- 💾 Daten — DE1 Direct Import, Export, Database Info
- 🔒 Sicherheit — Password
- 🤖 KI Analyse — AI Analysis settings
The active tab is remembered across sessions.
v1.11.0 — AI Analysis Cost Tracking
What's new
AI analysis cost tracking
Each shot analysis now records the USD cost of input and output tokens at the time the analysis runs. Costs are displayed inline alongside the existing metadata:
04.06.2026, 14:23 • claude-haiku-4-5-20251001 • ↑ 1.234 / ↓ 567 Tokens • ↑ $0.000309 / ↓ $0.000071 = $0.000380
Why store costs explicitly? Prices change over time — storing costs at analysis time means the historical record stays accurate.
How pricing works: Live prices are fetched from the OpenRouter API and cached in-memory for 24 hours. If the API is unreachable, a hardcoded fallback table is used. If pricing is completely unavailable, the analysis runs normally and costs are stored as null — the cost display is simply omitted.
Supported models: claude-haiku-4-5, claude-sonnet-4-6, claude-opus-4-8, gpt-4o-mini, gpt-4o (and any OpenRouter-listed model via direct ID).
Full Changelog: https://github.com/TomSchmidtDev/visualizer-lite/blob/main/CHANGELOG.md
v1.10.0
What's new
AI analysis metadata
Creation date, model name, and token counts (input / output) are now shown above the "Regenerate" button on the shot detail page — so you can see when an analysis was generated and what it cost.
README overhaul (EN + DE)
Both READMEs have been significantly improved:
- New "Why Visualizer Lite?" section explaining the motivation behind the project
- Expanded Quick Start with plain-language explanations of key parameters (data path, session secret, password, certificates)
- New "Importing Shots" section describing all three import methods (auto-push, direct import, manual upload) — including a note on running alongside the official Visualizer in parallel
- Expanded DE1 Plugins section describing both plugins and why the Upload to Visualizer plugin was extended to support custom targets over HTTP and HTTPS
- New Related Links section
- Disclaimer clarifying the hobby-project nature and BUSL-1.1 terms
- Architecture diagrams updated to reflect the AI analysis route, external AI API, and ShotAnalysis data model
v1.9.2 — Security fix (Docker CVEs)
Fixed
- Docker runtime image: upgrade npm from 10.9.8 to v11.x to resolve CVEs in npm's bundled packages
- picomatch 4.0.3 → removed (CVE-2026-33671, CVE-2026-33672, GHSA-c2c7-rcm5-vvqj, GHSA-3v7f-55p6-f55p)
- brace-expansion 2.0.2 → 5.0.6 (CVE-2026-33750, GHSA-f886-m6hf-6m8v)
- ip-address 10.1.0 → 10.2.0 (CVE-2026-42338, GHSA-v2v4-37r5-5v8g)
Note: The busybox CVEs (CVE-2025-60876) have no Alpine fix available yet and remain open.
v1.9.1 — Gitleaks fix
Fixed
- Suppressed gitleaks false positive on test fixture API key (
sk-invalid-key-12345inanalysisService.test.ts) via.gitleaksignoreand inline# gitleaks:allowcomment — no real credentials were ever committed