- Add _pendingLoginRedirect flag in router.js to handle auth:expired
events that fire during active navigation (isNavigating=true).
Previously the navigate('/login') call was silently dropped, leaving
the user stuck on the dashboard with an error toast.
- Bump SHELL_CACHE v33→v34 and PAGES_CACHE v28→v29 to force cache
invalidation on iOS devices still running the pre-CSRF-fix code.
- Add err.status to dashboard error log for easier diagnostics.
iOS Safari in PWA standalone mode unreliably handles cookies, causing
CSRF token desync between client and server after app resume. Previous
fixes (response body token in /auth/me and /auth/login) still left a
window where the token could go stale.
Now the server sends X-CSRF-Token response header on every API response
(via csrfMiddleware), including 403 error responses. The client reads
this header from every response, enabling instant self-healing: a 403
extracts the correct token from the error response itself and retries
without needing an extra /auth/me round-trip.
SW cache bumped to v33 to ensure existing iOS PWA installs pick up the
new client code.
In iOS WebKit standalone (home screen) mode, position:fixed elements
move with the page when the body itself becomes scrollable - unlike
regular Safari where fixed elements stay pinned. The root cause was
body having min-height: 100dvh without overflow: hidden, which allowed
body scroll to occur when content overflowed.
Fix: html and body are now overflow: hidden with fixed height (100% / 100dvh)
so all scrolling is confined to .app-content. Service worker bumped to
shell-v30 to force re-download of reset.css on installed PWAs.
- Added user-scalable=no, maximum-scale=1 to viewport meta tag to prevent
pinch-to-zoom in standalone PWA mode
- Added overflow: hidden to html, body so any minimal content overflow
cannot make the body scrollable (belt-and-suspenders alongside
overscroll-behavior: none)
- Service worker cache bumped to v28/v27
Root cause 1 (scroll bleed): padding-top was applied to body in standalone
mode. Since .app-shell has height: 100dvh, body-padding shifted the shell
beyond the viewport bottom - enabling body-level scrolling.
Fix: moved padding-top from body to .app-shell in the standalone media query.
Root cause 2 (content overflow): fixed-height page containers
(Calendar, Shopping, Meals, Notes, Budget, Contacts) calculated height as
100dvh - nav-bottom - safe-area-inset-bottom, but never subtracted the top
safe area. This caused each page to overflow .app-content by exactly
env(safe-area-inset-top) pixels in standalone mode.
Fix: added --safe-area-inset-top token and subtracted it in all 6 height
calculations.
Service worker cache bumped to v27/v26.
Users can now toggle which meal types (breakfast, lunch, dinner, snack)
are displayed in the meal planner via a new Settings section. Preference
is stored household-wide in sync_config and applied as a filter on the
meals page. Includes preferences API, i18n (DE/EN/IT), and Settings UI.
View mode (list/kanban) is now saved to localStorage and restored on
page load. URL parameter ?view=kanban takes precedence, enabling tablet
kiosk setups to default to Kanban view. Toggle buttons reflect the
active view correctly on initial render.
Closes#17
New tasks default to "none" priority instead of "medium". Tasks with no
priority hide the badge in list and dashboard views, reducing visual noise
for routine items. Includes DB migration v4 and i18n keys (de, en, it).
Closes#15
Three root causes fixed:
1. Double safe-area padding: pwa.css set padding-top/bottom on body
globally, but page containers already account for safe-area-inset
in their height calculations. Removed body vertical padding (kept
only in standalone media query for padding-top).
2. Wrong nav token: all page containers used --nav-height-mobile (56px)
instead of --nav-bottom-height (68px = 56px scroll + 12px dots),
causing 12px of content to render behind the bottom nav.
3. Scroll bleed: fixed-height page containers lacked overflow:hidden,
allowing scroll events to propagate to the body. Added
overscroll-behavior-y:contain on app-content globally.
Fixes#16
Replace all — with - in all source files (JS, CSS, HTML, JSON,
Markdown) for consistency and readability.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add id field and display_override to manifest.json for reliable
Chrome Android PWA recognition
- Serve manifest.json with application/manifest+json MIME type
- Add /i18n.js and locale files to SW app shell cache (were missing)
- Bump SW cache version to v21
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Configure manifest.json with scope, maskable icons, and categories. Add iOS/Android
meta tags for standalone behavior. Create pwa.css for native touch/scroll handling
and safe area insets. Add oikos-install-prompt Web Component with Chrome install
flow and iOS guidance. Optimize service worker with network-first navigation and
expanded precache (v19). Add dynamic theme-color per route and modal overlay dimming
in standalone mode. Generate placeholder icons via sharp script.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Kontrastproblem: Titel, Inhalt und Footer-Elemente der Notizkarten
überschrieben die Inline-Textfarbe mit festen Token-Werten. Jetzt
erben alle Elemente die adaptiv berechnete Farbe (dunkel auf hellen
Karten, hell auf dunklen).
Formatierungs-Toolbar: Fett, Kursiv und Liste als Buttons über dem
Textfeld im Editor. Fügt Markdown-Syntax ein, unterstützt Selektion
und Tastaturkürzel (Strg+B, Strg+I). Markdown-Rendering bleibt
unverändert.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Aufgaben-Widget zeigte nur high/urgent Tasks mit Fälligkeit ≤48h,
Pinnwand-Widget nur explizit gepinnte Notizen. Neue Einträge waren
dadurch im Dashboard unsichtbar.
- Aufgaben: alle offenen Tasks (sortiert nach Priorität), Limit 5
- Notizen: neueste 3 (gepinnte zuerst, dann nach Aktualisierung)
- Greeting-Chip zählt weiterhin nur high/urgent Tasks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dashboard-Widgets aktualisierten nicht, weil der Service Worker die
alte router.js aus dem Cache servierte (stale-while-revalidate).
Cache-Version v15→v16 erzwingt Invalidierung aller gecachten Dateien.
Zusätzlich fetch cache:no-store auf allen API-Aufrufen als Absicherung.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- notes-empty: column-span:all für korrekte Zentrierung im Multicolumn-Layout
- Inline-Style grid-column entfernt (wirkte nicht bei CSS columns)
- FAB jetzt auch auf Desktop sichtbar (48px, unten rechts)
- Toolbar-"Neu"-Buttons auf allen Breakpoints versteckt — FAB ist einziger
Erstellen-Button, kein Design-Bruch mehr zwischen Mobile und Desktop
- Service Worker Cache v15
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Blauer Plus-FAB unten rechts auf Mobile
- Fokussiert das Quick-Add-Eingabefeld und scrollt es ins Sichtfeld
- Erstellt eine neue Liste, wenn noch keine vorhanden ist
- Service Worker Cache v14
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Einheitlicher blauer Plus-Button unten rechts auf Mobile (tasks, calendar,
notes, contacts, budget) — konsistent mit Dashboard-FAB
- Toolbar-"Neu"-Buttons auf Mobile versteckt, auf Desktop weiterhin sichtbar
- Wiederverwendbare .page-fab CSS-Klasse in layout.css
- Dashboard-FAB Position an neue Nav-Höhe angepasst
- Service Worker Cache v13
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Alle 9 Menüpunkte jetzt auf Mobile erreichbar (2 Seiten)
- Horizontaler Scroll-Snap für seitenweises Swipen
- Dezente Dot-Indikatoren zeigen aktive Seite an
- Automatischer Scroll zur richtigen Seite bei Navigation zu Seite-2-Items
- Service Worker Cache v12
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dark Mode: Manueller Theme-Switch (System/Hell/Dunkel) in Einstellungen
mit localStorage-Persistenz und Flash-Prevention via data-theme Attribut.
RRULE UI: Wiederholungs-Formular in Aufgaben- und Kalender-Modals mit
Frequenz (Täglich/Wöchentlich/Monatlich), Intervall, Wochentag-Auswahl
und optionalem Enddatum. Backend-Routen für is_recurring/recurrence_rule
in POST/PUT erweitert. Repeat-Icon auf wiederkehrenden Einträgen.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- helmet: upgrade-insecure-requests und HSTS nur bei SESSION_SECURE=true
- Service Worker Cache-Version auf v10 hochgezählt
- Debug-Code aus router.js entfernt
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wenn weder Cache noch Netzwerk verfügbar sind gab die Funktion undefined zurück,
was event.respondWith() als Promise-Rejection wertet und einen Network Error
im Browser erzeugt. Letzter Ausweg ist jetzt eine 503-Antwort.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- connect-sqlite3 durch eigenen BetterSQLiteStore ersetzt (sessions-Tabelle
in der bestehenden DB, keine native Kompilierung nötig)
- db.init() vor require('./auth') gezogen damit BetterSQLiteStore-Konstruktor
db.get() erfolgreich aufrufen kann
- router.js: App-Shell und pageWrapper vor module.render() in DOM einfügen
damit document.getElementById() in Seiten-Modulen funktioniert
- Seiten-Module (meals, notes, contacts, calendar, budget): _container-Referenz
eingeführt, alle document.getElementById() auf _container.querySelector() bzw.
document.querySelector() für body-Elemente umgestellt
- login.js: User-Objekt nach erfolgreichem Login an navigate() übergeben
damit auth.me()-Roundtrip entfällt
- calendar.js: /users → /auth/users korrigiert (404-Fix)
- SW-Cache v8 (erzwingt Reload aller gecachten Seiten-Module)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- lucide.min.js v0.469.0 lokal gecacht (kein unpkg-Request mehr)
- Source-Map-Referenz aus Bundle entfernt (behebt NetworkError in DevTools)
- unpkg.com aus CSP entfernt (nicht mehr benötigt)
- preconnect zu unpkg.com aus index.html entfernt
- lucide.min.js zum SW-App-Shell-Cache hinzugefügt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Das Inline-Script in index.html für die Service-Worker-Registrierung
wurde von der Content-Security-Policy blockiert (kein 'unsafe-inline'
in script-src). Ausgelagert nach /sw-register.js ('self' erlaubt).
Außerdem: rel="preload" → rel="modulepreload" für ES-Module (korrekte
Browser-Semantik, behebt die Preload-Warnungen in der Console).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>