Release history
Oikos releases
Family planner for small households
All releases
213 shown
- Added `bike` icon to the calendar event icon selector (transport category) with translations for all 16 supported locales
Full changelog
Added
- Bike icon: added
bikeicon to the calendar event icon selector (transport category), with translations for all 16 supported locales.
- Split Expenses module with expense groups and multiple split methods (equal, percentage, exact amounts, shares)
- Settlements feature using a debt‑simplification algorithm for minimal transfer sets
- Recurring expenses with daily/weekly/monthly/yearly schedules via hourly scheduler
Full changelog
[0.51.0] - 2026-05-11
Added
- Split Expenses module: new tab inside Budget for managing shared expenses. Supports expense groups (household, couple, travel, event, shopping, general) with multiple split methods: equal, percentage, exact amounts, and shares. Balances are derived from an immutable ledger — amounts are stored as integer minor currency units (cents) to avoid floating-point errors.
- Settlements: record payments between group members with a debt-simplification algorithm that produces the minimal set of transfers to clear all balances.
- Recurring expenses: define expenses that repeat on a daily, weekly, monthly, or yearly schedule with automatic generation via an hourly scheduler.
- Guest accounts: invite people outside the family as restricted guests who can only access the Split module and see their own invited groups. Guests can be created from scratch or converted from existing contacts.
- Multi-currency support: each group has a default currency; individual expenses can use any currency with historical exchange rate snapshots for consistent balance reporting.
- Activity feed: per-group log of all expense, member, and settlement events.
- Polish locale: split-expenses strings added to the Polish (
pl) translation.
- Full Polish (pl) translation for all UI modules
Full changelog
What's New
Added
- Polish locale — full Polish (
pl) translation covering all UI modules: tasks, calendar, shopping, meals, budget, notes, contacts, birthdays, recipes, documents, housekeeping, settings, and more. Polish is now selectable in Settings → Language.
This brings Oikos to 16 supported languages: German, English, Spanish, French, Italian, Swedish, Greek, Russian, Turkish, Chinese (Simplified), Japanese, Arabic, Hindi, Portuguese, Ukrainian, and now Polish.
Full Changelog: https://github.com/ulsklyc/oikos/blob/main/CHANGELOG.md
- Housekeeping module with staff profiles, check‑in/out tracking, recurring chore tasks, supply requests, monthly visit logs and payment task integration
- Document folders for custom organization via sidebar browser
- Calendar icon picker supporting curated Lucide icons
Full changelog
What's new
Housekeeping module
A new dedicated module for managing household staff workflows:
- Staff profiles — name, daily rate, calendar color, payment schedule, avatar
- Check-in / check-out — each visit creates a calendar event; check-out records the actual end time
- Recurring chore tracking — decay tasks with configurable frequency and urgency indicators
- Supply requests — linked directly to shopping lists
- Monthly visit log — with payment summary and per-visit extras tracking
- Payment task integration — optionally creates a task on each check-in; completing it marks the visit as paid
Document folders
Documents can now be organized into custom folders with a sidebar browser.
Calendar icon picker
Calendar events now support a custom icon from a curated Lucide set.
Full changelog: https://github.com/ulsklyc/oikos/blob/main/CHANGELOG.md
- Brand accent color changed back to Violet (#6c3aed light, #a78bfa dark) across all UI elements and documentation
Full changelog
Changes
Changed
- Brand color: reverted the primary accent color from Amber back to Violet. The accent is now
#6c3aedin light mode and#a78bfain dark mode, applied consistently across all design tokens, the logo, all PWA icons (favicon, app icons, maskable icons, Apple touch icon), and the GitHub Pages documentation site. Semantic colors (warnings, notes module, meal-breakfast) remain unchanged.
Full changelog: https://github.com/ulsklyc/oikos/blob/main/CHANGELOG.md
Brand color refresh updates accent from indigo (#4F46E5) to warm amber (#92400E light / #FBBF24 dark).
Full changelog
Brand color refresh
The primary accent color has been updated from cool indigo (#4F46E5) to a rich, warm amber (#92400E in light mode, #FBBF24 in dark mode) across all design tokens, the logo, and the GitHub Pages documentation site.
Why this change? Indigo carried the aesthetic of a productivity tool — focused, corporate, digital. As Oikos has grown into a home for thousands of families, we wanted the visual identity to better reflect what the app actually is: a warm, shared space for everyday life together. Amber — deep and earthy in light environments, bright and inviting in dark ones — communicates exactly that. It evokes warmth, reliability, and the kind of unhurried intimacy that family life deserves.
From an accessibility standpoint, Amber-800 (#92400E) achieves a contrast ratio of 7.20:1 against white, exceeding the WCAG AA threshold and meeting WCAG AAA. The dark mode value (#FBBF24) maintains the same readability standard. The transition is purely cosmetic — no data, settings, or behavior has changed.
Logo: updated the gradient on docs/logo.svg and all inline SVG instances from violet (#8B5CF6 to #6C3AED) to amber (#B45309 to #92400E).
Fixed CalDAV and CardDAV "Add Account" modals so Cancel and Save buttons appear and onSave no longer triggers prematurely.
Full changelog
Fixed
- Settings: CalDAV and CardDAV "Add Account" modals now correctly display Cancel and Save buttons. Previously, the
onSavecallback ran immediately on modal open, triggering a required-fields validation error against empty fields and leaving the form with no way to submit. Fixes #128.
- API responses now include `assigned_users` array while preserving legacy fields; clients should prefer the new field.
- Filters GET /api/v1/tasks?assigned_to= and GET /api/v1/calendar?assigned_to= match any assignment list entry.
- Multi-person assignment via new task_assignments / event_assignments join table (migration v32)
- Stacked avatar display on task, Kanban, and calendar agenda cards showing up to three assigned users with a +N overflow badge
- Shared UserMultiSelect component for checkbox‑based multi‑user selection in modals
Full changelog
Added
- Multi-person assignment: tasks and calendar events can now be assigned to multiple family members simultaneously. A new task_assignments / event_assignments join table (migration v32) stores the assignments; existing single-user data is migrated automatically.
- Avatar stack: task cards, Kanban cards, and the calendar agenda view display stacked avatars for all assigned users (up to 3 visible, then a +N overflow badge).
- Shared UserMultiSelect component (public/components/user-multi-select.js): checkbox-based dropdown used in both the task modal and the calendar event modal; replaces the previous single-user select element.
- assigned_to filter extended: GET /api/v1/tasks?assigned_to= and GET /api/v1/calendar?assigned_to= now match any task/event where the user appears in the assignments list.
Changed
- API response for tasks and calendar events now includes assigned_users: [{id, display_name, color}] array alongside the legacy assigned_to / assigned_name / assigned_color fields.
- Recurring task completion copies all multi-person assignments to the new recurring instance.
- Sync tab grouped into dedicated "CalDAV & CardDAV" and secondary "Cloud Services" sections
- Reusable `renderSubTabs()` component for shared pill-style navigation bars across settings and kitchen tabs
Full changelog
Changes
Settings — Sync tab restructured
Open standards (CalDAV, CardDAV, ICS subscriptions) are now grouped first under a dedicated "CalDAV & CardDAV" section. Cloud services (Google Calendar, Apple Calendar) move to a secondary "Cloud Services" section below. Fixes a raw <h2> heading inside the CalDAV card, which caused inconsistent heading sizes compared to all other settings cards.
Shared sub-tabs navigation component
Extracted renderSubTabs() as a single reusable implementation for all sub-module navigation bars (public/utils/sub-tabs.js + public/styles/sub-tabs.css). Settings tabs and kitchen tabs now share the same pill-style bar with icons, labels, sticky positioning, horizontal scrolling, and group separators. Removes approximately 120 lines of duplicated CSS from kitchen-tabs.css and settings.css. New sub-module navigation can use renderSubTabs() directly without any additional CSS.
Test loader improvement
test-browser-loader.mjs now automatically resolves browser-absolute /utils/*.js imports to the public/ directory, removing the need for per-module manual stubs.
Full Changelog
https://github.com/ulsklyc/oikos/blob/main/CHANGELOG.md
- Docker now uses host‑mounted bind mounts for DATA_DIR (default ./data) and BACKUP_DIR (default ./backups); set these paths via .env if needed.
Full changelog
Fixed
- Modal: add
onClosecallback toopenModal()so promise-based modals (confirmModal,promptModal,selectModal) resolve correctly on Escape and overlay-click without duplicate event listeners. - Modal: fix
_initialFormTimeoutleak — timeout is now tracked and cancelled on re-open or close, preventing stale dirty-check snapshots. - Calendar: replace
popup.innerHTMLwithinsertAdjacentHTMLin the event popup (project constraint); addtruncateDescription()to cap long event descriptions at 500 characters. - Validation: extend
DATETIME_REto accept ISO 8601 datetimes with milliseconds and timezone offsets; normalise datetime inputs toYYYY-MM-DDTHH:MMbefore storing.
Changed
- Docker: switch from named Docker volume to host-mounted bind mounts;
DATA_DIR(default./data) andBACKUP_DIR(default./backups) can be set in.envto control storage locations. - Startup log: include app version in the server start message.
Minor fixes and improvements.
Full changelog
Changed
- Documentation: SPEC.md updated to reflect v0.45–v0.47 changes — CardDAV Accounts and CardDAV Addressbook Selection tables added; Contacts table expanded with multi-value fields and CardDAV columns; new contact_phones, contact_emails, contact_addresses sub-tables documented; Birthdays table reflects configurable reminder offset columns; External Calendars table notes apple→caldav migration; Tasks module documents bulk actions; Contacts module documents CardDAV multi-account sync; Birthdays module reflects flexible reminder offsets; Settings module updated for Synchronization tab, module toggles, scheduled backups, and CardDAV UI.
- README: Birthdays feature description updated to reflect customizable reminder offsets; Backup feature description updated to mention automatic scheduled backups.
Removed
- Repository: archived implemented cleanup plan (
docs/designs/2026-05-04-repo-cleanup-design.md→docs/archive/designs/); removed settings sidebar prototype HTML (docs/designs/2026-05-04-settings-sidebar-demo.html).
Minor fixes and improvements.
Full changelog
Changed
- Dependencies: updated express-rate-limit from 8.4.1 to 8.5.0 (async store initialization support) and tsdav from 2.1.8 to 2.2.0 (native fetch, enhanced OAuth token handling, improved CalDAV/CardDAV sync reliability, security improvements).
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.47.1...v0.47.2
Fixed crash on Settings page caused by undefined loadCalDAVAccounts and loadCardDAVAccounts functions.
Full changelog
Fixed
- Settings page crash: fixed ReferenceError "loadCalDAVAccounts is not defined" when opening Settings. Root cause: loadCalDAVAccounts and loadCardDAVAccounts were defined inside the render function but called from bindIcsEvents (outside render scope). Functions are now top-level exports with user parameter.
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.47.0...v0.47.1
- Unified Synchronization tab replaces Calendar tab, grouping Calendar Sync and Contact Sync sections with visual CSS separators.
- Complete CardDAV UI for adding/deleting accounts (iCloud, Nextcloud, Radicale, Baikal), toggling addressbooks, manual sync trigger, real‑time status badges, and empty‑state onboarding.
Full changelog
Settings UX Overhaul & CardDAV UI
This release significantly improves the Settings experience with better organization and a complete user interface for CardDAV contact synchronization.
Added
- Settings UX overhaul: renamed Calendar tab to Synchronization with dedicated sections for Calendar Sync and Contact Sync. Improved information architecture with visual tab grouping using CSS separators between functional areas (module settings, synchronization, personal, administration).
- CardDAV UI: complete user interface for CardDAV contact synchronization in Settings. Add/delete CardDAV accounts (iCloud, Nextcloud, Radicale, Baikal), enable/disable individual addressbooks, manual sync trigger, real-time status indicators. Empty state onboarding for first-time setup.
- Status badges: visual sync status indicators (success, error, syncing) with animated spinner for active syncs across CalDAV and CardDAV integrations.
Changed
- Settings navigation: Calendar tab replaced by unified Synchronization tab containing both calendar and contact sync options. Existing CalDAV calendar accounts remain accessible in the Calendar Sync section.
Technical Details
- 21 files changed, 4267 insertions, 43 deletions
- All 109 tests passing
- i18n updates for all 14 supported locales
- Backward compatible with existing CalDAV setup
- Flexible birthday reminders with preset offsets (none, at time, 15min, 1h, 1d, 2d, 1w, 2w) and custom intervals in minutes, hours, days, or weeks
- UI integration of reminder settings into the birthday modal
- Option to completely disable birthday reminders
Full changelog
What's New
Flexible Birthday Reminders
Configure exactly when to be reminded of upcoming birthdays with:
- Preset offsets: none, at time, 15min, 1h, 1d, 2d, 1w, 2w
- Custom intervals: minutes, hours, days, or weeks
- Integrated UI in birthday modal
- Optional: disable reminders entirely
Bug Fixes
- Service worker now properly handles non-HTTP protocols (e.g., browser extensions)
Installation
Docker:
docker pull ghcr.io/ulsklyc/oikos:0.46.0
See Installation Guide for details.
Contributors
- @rafaelfoster for the birthday reminders feature (#123)
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.45.0...v0.46.0
- Automatic database migration via `server/db.js` (Migration 30) applies the new CardDAV schema tables (`carddav_accounts`, `carddav_addressbook_selection`, `contact_phones`, `contact_emails`, `contact_addresses`).
- CardDAV Multi‑Account Sync with eight new API endpoints, per‑addressbook toggles, connection testing, and manual/auto sync triggers.
- Multi‑Value Contact Fields supporting phone numbers, emails, addresses with labels, primary flags, atomic updates, and validation.
Full changelog
CardDAV Contacts Integration
This release adds comprehensive CardDAV support for contacts with multi-account management and multi-value fields.
New Features
CardDAV Multi-Account Sync
- Connect multiple CardDAV servers (Nextcloud, iCloud, Radicale, Baikal) simultaneously
- 8 new API endpoints for account management under
/api/v1/contacts/cardav/ - Per-addressbook enable/disable via checkboxes
- Test connections before saving
- Manual sync trigger per account
- Automatic addressbook discovery and refresh
Multi-Value Contact Fields
- Multiple phone numbers, email addresses, and physical addresses per contact
- Each entry has a label (mobile, work, home, etc.), value, and optional "primary" flag
- Atomic transaction support with replacement semantics on update
- Backward compatible with existing single-field contacts
- Full validation with length limits and format checks
Technical Details
- New service:
server/services/cardav-sync.js - New router:
server/routes/cardav.js - Extended router:
server/routes/contacts.js(multi-value support) - Database tables:
carddav_accounts,carddav_addressbook_selection,contact_phones,contact_emails,contact_addresses - 109 tests across 20 test suites (all passing)
- Full OpenAPI documentation
Related
- Pull Request: #122
- Migration: Automatic via
server/db.js(Migration 30)
Full Changelog: https://github.com/ulsklyc/oikos/blob/main/CHANGELOG.md#0450---2026-05-04
Fixed CalDAV migration crash caused by CHECK constraint violation.
Full changelog
Fixed
- CalDAV migration crash: fixed CHECK constraint violation during v0.44.0 migration that caused container restart loop. The apple→caldav
external_sourceconversion now happens during table rebuild instead of before, preventing the constraint error (#119, #120).
Full changelog: https://github.com/ulsklyc/oikos/blob/main/CHANGELOG.md
- Existing Apple CalDAV data is automatically migrated to the new `caldav_accounts` and `caldav_calendar_selection` tables.
- New backend service `server/services/caldav-sync.js` and API routes `/calendar/caldav/*` are added; ensure they are deployed.
- Removed the single Apple CalDAV integration; replaced with a comprehensive multi‑account CalDAV system requiring migration of existing data.
- Support for simultaneous connection to multiple CalDAV providers (iCloud, Nextcloud, Radicale, Baikal, etc.)
- Per‑account calendar selection via checkboxes in Settings → Calendar
- Bidirectional sync and outbound target selection when creating events
Full changelog
Generic CalDAV Multi-Account Sync
This release replaces the single Apple CalDAV integration with a comprehensive multi-account CalDAV solution.
New Features
- Multiple CalDAV Accounts: Connect iCloud, Nextcloud, Radicale, Baikal, and any CalDAV-compatible server simultaneously
- Per-Account Calendar Selection: Choose which calendars to sync with checkboxes in Settings → Calendar
- Bidirectional Sync: Full two-way synchronization between Oikos and your CalDAV servers
- Outbound Target Selection: When creating events, optionally choose which CalDAV account/calendar to sync to
- Automatic Migration: Existing Apple CalDAV data is automatically migrated to the new system
Technical Changes
- New database tables:
caldav_accounts,caldav_calendar_selection - New backend service:
server/services/caldav-sync.js - New API routes:
/calendar/caldav/* - Enhanced UI in Settings and Calendar event modal
- 7 new comprehensive tests (all passing)
Documentation Updates
- README.md: Updated Calendar feature description
- docs/SPEC.md: Added new table schemas and updated Calendar module documentation
- Full i18n support in German and English
Fixes
- None (feature release)
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.43.0...v0.44.0
Closes #90
- Automatic scheduled backups with configurable cron schedule, directory, and retention policy via .env variables (BACKUP_ENABLED, BACKUP_SCHEDULE, BACKUP_DIR, BACKUP_KEEP).
Full changelog
Added
- Automatic scheduled backups: database backups are now created automatically on a configurable cron schedule (default: 2 AM daily). Old backups are rotated automatically, keeping only the last N copies (default: 7). Configuration via
.envvariables:BACKUP_ENABLED,BACKUP_SCHEDULE,BACKUP_DIR,BACKUP_KEEP. Settings → Backup displays scheduler status, schedule, retention policy, last backup timestamp, and a manual trigger button.
- Module toggles in Settings → General let admins disable/enable specific modules (Tasks, Calendar, etc.) while preserving data
- Bulk actions for tasks in List view: select multiple items and apply mark done/open, archive, or delete
Full changelog
Added
- Module toggles (Settings → General, admin-only): individual modules (Tasks, Calendar, Shopping, Meals, Recipes, Birthdays, Notes, Contacts, Budget, Documents) can be disabled to hide them from the navigation. Data is preserved and reappears when the module is re-enabled. Dashboard and Settings remain essential and cannot be disabled.
- Bulk actions for tasks (List view only): select multiple tasks via checkboxes and apply batch operations (mark done, mark open, archive, delete). Bulk select toggle appears in the toolbar; selected count and action bar appear when tasks are checked. Kanban view remains single-task oriented.
- Birthday badge on nav item when any family member has a birthday within the next 3 days
- Recent filter chips in task bar, persisted via localStorage
- Live search field for event icon picker with category grouping
Full changelog
Added
- Birthday badge: the birthdays nav item now shows a badge when any family member has a birthday within the next 3 days.
- Recent filter chips: the task filter bar now shows up to three recently used filters as quick-access chips, persisted in
localStorage. - Calendar icon search: the event icon picker now includes a live search field to quickly find icons by keyword, with results grouped by category.
- Calendar icon categories: event icons are now organised into labelled category groups (transport, sports, health, nature, leisure, social, work, home, food, other).
- Repeat indicator on calendar events: events with a recurrence rule now display a small repeat icon in both month and week views.
- 3-day week view on mobile: the calendar week view automatically switches to a 3-day window on screens narrower than 640 px for better readability.
- Widget size presets: the dashboard widget size selector uses named presets (Tiny, Narrow, Standard, Large, Full) instead of raw grid dimension values.
Changed
- Required-field markers: title fields in the task, event, and budget modals now show a required-field asterisk via the
.required-markerCSS class. - Modal drag handle touch target: the bottom-sheet drag handle has a 44 px tall invisible hit area so it can be grabbed comfortably.
- Swipe affordance: list rows with swipe actions show a subtle chevron hint to signal the gesture.
- Budget tab height: budget tab buttons have a minimum height of 40 px to meet touch-target requirements.
- Typography tightening with tighter letter‑spacing and text-wrap: balance
- Warm‑tinted elevation shadows matching the warm neutral palette
- Regular buttons use a medium radius (12 px) for clearer distinction
Full changelog
Changed
- Typography tightening: page titles and modal titles use tighter letter-spacing (
-0.5 px/-0.8 pxon desktop) andtext-wrap: balanceto eliminate orphaned words on wrapped headings. - Warm-tinted shadows: all elevation shadows (
smthroughxl) now use a warm-tinted base colour (rgba(18, 14, 8, …)) that matches the warm neutral palette instead of pure black. - Button radius: regular buttons use
--radius-md(12 px) instead of--radius-sm(8 px), creating a clear visual distinction from text inputs. - Empty-state icons: icons in empty states pick up a 40 % tint of the current module accent colour, making them feel contextually connected to each module rather than uniformly grey.
- Search section labels: category headings inside the search overlay are now sentence-case instead of all-caps, improving readability.
Fixed
- Tabular figures: currency amounts (budget summary cards, transaction list, loan cards, chart rows), weather temperature, dashboard metrics, and calendar time labels now use
font-variant-numeric: tabular-numsso digit columns remain visually aligned.
- Loans tracker tab in Budget with CRUD, balance/due tracking, and auto‑close of paid loans
- Configurable dashboard widget sizes (columns × rows) persisted per user
- Four additional date format options: MM.DD.YYYY, YYYY.MM.DD, YYYY/MM/DD, DD/MM/YYYY
Full changelog
Added
- Budget loans tracker (PR #117 by @rafaelfoster): a new Loans tab in the Budget module lets you create instalment-based loans, record individual payments, track remaining balance and due months, and filter budget transactions by loan. Paid-off loans are automatically marked as closed. Full CRUD with confirmation modals.
- Dashboard widget sizes: each dashboard widget now has a configurable size (columns × rows). Sizes are persisted in user preferences and survive page reloads.
- Extended date formats: Settings → General now offers four additional date format options —
MM.DD.YYYY,YYYY.MM.DD,YYYY/MM/DD, andDD/MM/YYYY— alongside the existing formats.
Fixed
dmydate format preserved: the existingDD.MM.YYYYbehaviour of thedmypreference is unchanged for all current users; a newDD/MM/YYYYoption (dmy_slash) is available for those who want slashes.
Fixed budget entry date input to use native date pickers on iOS and Android.
Full changelog
Fixed
- Budget date picker: the date input in Budget → New Entry / Edit Entry now uses a native date picker on iOS and Android instead of a plain text field.
Minor fixes and improvements.
Full changelog
What's Changed
- Update swedish translation by @olsson82 in https://github.com/ulsklyc/oikos/pull/115
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.39.0...v0.39.1
- User‑configurable time format preference integrated across app UI, storage, API
Full changelog
What's Changed
- Added a user-configurable time format preference to the app and wired it through settings, storage, API preferences, and time entry/display paths. by @rafaelfoster in https://github.com/ulsklyc/oikos/pull/114
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.38.4...v0.39.0
Fixed dashboard portrait mode on mobile by removing an overriding CSS rule.
Full changelog
Fixed
- Dashboard portrait mode on mobile: layout no longer overflows to landscape width;
overflow: visibleoverride in the Admin Dashboard Layout CSS block has been removed so the correctoverflow: cliptakes effect, and.app-contentnow usesoverflow-x: hidden(instead ofclip) to properly contain layout overflow at the scroll container level
Fixed horizontal scrollbar appearing in dashboard portrait mode on Android.
Full changelog
Fixed
- Dashboard portrait mode on Android: horizontal scrollbar no longer appears due to subpixel overflow in the main scroll container (
overflow-x: clipadded to.app-content)
Fixed recurring weekly events with INTERVAL > 1 to skip the correct number of weeks.
Full changelog
Fixed
- Recurring calendar events with
FREQ=WEEKLY;INTERVAL=N;BYDAY=...(N > 1) now correctly skip N−1 weeks between occurrences instead of repeating every week
Minor fixes and improvements.
Full changelog
Changed
- Docs: SPEC.md —
family_documentsandfamily_document_accesstables added;calendar_eventsextended withiconand four attachment columns;contactsandbirthdaysextended withfamily_user_id; Tasksstatusincludesarchived; Documents module section added; Calendar section updated with icons, file attachments, and overlapping event rendering; Settings section updated with Backup Management tab and family member contact fields - Docs: BACKLOG.md — completed features table brought up to date through v0.38.0 (v0.30.0–v0.38.0 entries added)
- Docs: README.md — Backup entry added to the feature table; Documents entry updated with exact category count
- Docs: CONTRIBUTING.md —
innerHTMLsecurity note updated to reflect currentinsertAdjacentHTML/replaceChildren/esc()pattern; individual test-suite commands listed
Success toasts are suppressed after 50 saves to reduce noise for power users.
Full changelog
Added
- FAB entry animation now stops after 5 page views (long loop progressive reduction)
- Search keyboard shortcut hint (
/) hides permanently after first keyboard use - Success toasts are suppressed after 50 successful saves to reduce noise for power users
- Empty state CTA button fades in with a short delay to draw attention as the primary action
- Form fields pulse with a red glow on the second or subsequent validation failure on the same field
- Shopping quick-add input shows a brief accent-colour glow after each successful item add
- Hover, active, and focus states with accent colour highlight and subtle scale feedback for the More sheet search bar
- Search bar icon changes to accent colour on hover and press
- Keyboard shortcut hint (`/`) displayed inside search bar on desktop
Full changelog
Changed
- Search bar in More sheet: added hover, active, and focus states with accent colour highlight and subtle scale feedback
- Search bar icon changes to accent colour on hover and press for clearer trigger affordance
- Keyboard shortcut hint (
/) shown inside search bar on desktop as discoverability signal
- Removed Search from primary bottom navigation tab bar; replaced with Tasks.
Full changelog
Changed
- Bottom navigation: Tasks replaces Search as a primary tab bar item
- More menu: layout changed from two columns to a three-column grid (two rows of three)
- Search: embedded as a narrow bar at the top of the More sheet instead of a standalone bottom-nav button
- Consistent upload option in the calendar
- Fiz images rendering
Full changelog
What's Changed
- Consistent upload option in the calendar, and fiz images rendering by @rafaelfoster in https://github.com/ulsklyc/oikos/pull/110
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.36.1...v0.37.0
- Default date format changed from US MM/DD/YYYY to DD.MM.YYYY for new users
Full changelog
Fixed
- Date input: default date format changed from US (
MM/DD/YYYY) to day-month-year (DD.MM.YYYY) for new users - Date input: dot-separated dates (
DD.MM.YYYY) are now accepted in addition to slash-separated dates - Date input:
dmyplaceholder and display format updated to use dots instead of slashes
- Empty states in Tasks, Notes, Contacts, Shopping, Recipes, and Budget now include a primary CTA button linked to the page FAB
- `friendlyError(err)` helper added to `window.oikos` with status‑code aware error messages (offline, forbidden, not found, server error, timeout)
- New common.error* i18n keys for offline, forbidden, notFound, server, and timeout in all 15 locales
Full changelog
Added
- Navigation: Kitchen (Meals/Recipes/Shopping) is now grouped as a single "Küche" entry in the desktop sidebar, consistent with the mobile bottom bar
- UX: empty states in Tasks, Notes, Contacts, Shopping, Recipes and Budget now include a primary CTA button that triggers the page FAB
- UX:
friendlyError(err)helper added towindow.oikos; unhandled promise rejections now show status-code-aware messages (offline, forbidden, not found, server error, timeout) instead of raw error text - i18n: five new
common.error*keys (offline, forbidden, notFound, server, timeout) added to all 15 locale files
Changed
- Navigation: more-button icon changed from
grid-2x2toellipsis(matches the sheet it opens) - Navigation: desktop sidebar expands labels at 1 280 px instead of 1 440 px
- UX: search overlay input field is now at the top, results below (standard top-to-bottom scan path)
- UX: touch targets for kitchen tabs and shopping list tabs raised to 44 px (iOS minimum)
- UX: dashboard metric values enlarged to
xl/boldand labels styled as2xs/uppercasefor clearer data hierarchy - Onboarding: step 2 text and icon updated to accurately describe the navigation structure (···-button and module groups); step 3 text and icon updated to explain the FAB and swipe gestures
- System Backup and Restore tool
Full changelog
What's Changed
- Added a system Backup and Restore tool by @rafaelfoster in https://github.com/ulsklyc/oikos/pull/109
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.34.1...v0.35.0
Fixed kitchen tabs bar disappearing after navigating from Shopping due to overwritten container.
Full changelog
Fixed
- Kitchen tabs bar disappeared after navigating to Shopping, because the page overwrote the container a second time after loading data
- Bottom bar now contains Dashboard, Calendar, Küche, Suche, Mehr (5 items).
- More sheet layout changed to a 2‑column grid with larger touch targets; search trigger removed.
- Drag‑handle added at the top of More sheet; swipe‑down gesture closes it.
- Meals, Recipes and Shopping removed from the More sheet; now accessible only via the Kitchen tab bar and desktop sidebar.
- New "Küche" (Kitchen) button in bottom bar groups Meals, Recipes and Shopping with a persistent internal tab bar.
- New "Suche" (Search) button added to bottom bar for one‑tap search overlay access.
- Sticky segment control remembers last active tab via sessionStorage across Küche sub‑modules.
Full changelog
Added
- Navigation: new "Küche" (Kitchen) button in the bottom bar groups Meals, Recipes and Shopping behind a single entry point with a persistent tab bar inside each sub-module
- Navigation: new "Suche" (Search) button added to the bottom bar for one-tap access to the search overlay
- Kitchen tabs bar: sticky segment-control (Meals / Recipes / Shopping) injected at the top of each sub-module page; remembers the last active tab via sessionStorage
- Keyboard shortcuts:
g knavigates to Kitchen (last tab),g k m→ Meals,g k r→ Recipes,g k s→ Shopping - i18n:
nav.kitchen,nav.searchandshortcuts.goKitchenkeys added to all 15 locale files
Changed
- Navigation: bottom bar reorganised — Dashboard, Calendar, Küche, Suche, Mehr (5 items)
- Navigation: Meals, Recipes and Shopping removed from the More sheet; they are accessible via the Kitchen tab bar and the sidebar on desktop
- More sheet: reduced from 3-column to 2-column grid for larger touch targets; search trigger removed
- More sheet: drag-handle added at the top; swipe-down gesture closes the sheet
- Removed the dedicated Search button from the bottom bar.
- Replaced grid-cell search item in More sheet with a full-width pill-shaped trigger at the top.
- Moved search overlay input field to the bottom of the screen (thumb zone) instead of the top.
Full changelog
Changed
- Navigation: removed the dedicated Search button from the bottom bar; the bottom bar now shows three primary module links plus the More button
- Navigation: the More sheet now opens with a full-width pill-shaped search trigger at the top, replacing the grid-cell search item
- Search: the search overlay input field is now positioned at the bottom of the screen (thumb zone) instead of the top
- Overlapping timed events render side-by-side using a column-layout algorithm in week and day views
- Events support optional file attachments (images, PDFs, office docs up to 5 MB); images display inline, others as download links
- Birthdays edit modal redesigned with photo avatar and name/date fields shown side by side
Full changelog
Added
- Calendar: overlapping timed events in week and day views now render side-by-side using a column-layout algorithm instead of stacking on top of each other
- Calendar: events support optional file attachments (images, PDFs, and office documents up to 5 MB); images are shown inline in the event popup, other files as a download link
- Birthdays: redesigned edit modal with photo avatar and name/date fields displayed side by side
Fixed
- Calendar: attachment i18n keys are fully translated in all 15 locales (German translation added; Portuguese diacritics corrected)
- Typography: Plus Jakarta Sans variable font (200–800) self‑hosted under `public/fonts/`.
- Dashboard visual hierarchy – Tasks and Calendar span two columns; Weather and Shopping span two columns at the three‑column breakpoint.
- Subtle accent border on primary widgets using the active module accent colour.
Full changelog
Added
- Typography: Plus Jakarta Sans variable font (200–800 weight) self-hosted under
public/fonts/— consistent branding across all platforms with no CDN dependency at runtime - Dashboard: visual hierarchy for primary widgets — Tasks and Calendar always span two columns; Weather and Shopping span two columns at the three-column breakpoint only
- Dashboard: subtle accent border on primary (wide) widgets using the active module accent colour
Changed
- Module toolbars (Tasks, Notes, Calendar, Contacts, Shopping) are now sticky — they remain visible at the top while scrolling long lists
Fixed
- Sticky toolbars: changed
overflow: hiddentooverflow: clipon Calendar, Notes, Contacts, and Shopping page roots soposition: stickyworks correctly on child toolbar elements - Dashboard: explicit
grid-column: span 1for secondary widgets at the 768 px (two-column) breakpoint to prevent implicit layout jumps
- Bottom navigation: Dashboard, Tasks, Calendar as first three slots; Search promoted to dedicated fourth button
- Sidebar tooltips for collapsed mode (1024–1439 px) show module labels on hover
Full changelog
Changed
- Bottom navigation restructured: Dashboard, Tasks, Calendar as first three primary slots; Search promoted to a dedicated fourth bottom-nav button (no longer buried in the More sheet)
- Sidebar tooltips added for the collapsed mode (1024–1439 px) — hovering an icon now shows a label tooltip so module names remain discoverable without expanding the sidebar
Routine maintenance release for Oikos.
Changelog
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.32.0...v0.32.1
- Family Documents module with upload, search, per‑document visibility (family, selected members, private), category tagging, archive/restore and download
- Drag‑and‑drop upload area in the new‑document modal
- Archive button on task cards with support in kanban view and filter
Full changelog
Added
- Documents: new Family Documents module — upload, search, and manage family files (PDF, images, text, Office) with grid/list view, per-document visibility (family, selected members, private), category tagging (medical, school, identity, insurance, finance, home, vehicle, legal, travel, pets, warranty, taxes, work, other), archive/restore, and download actions (#104)
- Documents: drag-and-drop upload area in the new-document modal (#104)
- Tasks: archive button on task cards; archived status supported in kanban view and filter (#104)
- Tasks: inline reminder preset UI — offset from due date/time with 15 min, 1 h, 1 d, 2 d, 1 w, 2 w, or custom offset presets (#104)
- i18n: Documents and updated Tasks keys translated in all 15 locales
Fixed
- Modal: discard-changes confirmation no longer corrupts overlay state when a confirm dialog is triggered from within another modal (#104)
- RRule: "Until" date field moved inside the recurrence options row for better layout (#104)
- Edit button added to ICS subscription management
Full changelog
What's Changed
- feat: add edit button for ICS subscriptions by @ulsklyc in https://github.com/ulsklyc/oikos/pull/102
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.31.1...v0.31.2
Birthday date fields now use the native iOS date picker.
Full changelog
Fixed
- Settings: birthday date fields (profile, new member, edit member) now use the native date picker on iOS
- Birthdays: birth date field now uses the native date picker on iOS
- Improved family and account management capabilities
- Enhanced calendar event customization options
Full changelog
What's Changed
- This PR improves family/account management and calendar event customization. by @rafaelfoster in https://github.com/ulsklyc/oikos/pull/99
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.30.3...v0.31.0
- Changed access control for Birthday entries: any family member can now view, edit, and delete them regardless of creator
Full changelog
Changed
- Birthdays: all family members can now view, edit, and delete any birthday entry regardless of who created it
Restored native date picker for calendar event modals by changing input type back to "date".
Full changelog
Fixed
- Calendar: date inputs in the event modal reverted from
type="text"totype="date", restoring the native date picker on iOS and other mobile browsers
Fixed Greek translation typo Διδαγραφή → Διαγραφή.
Full changelog
What's Changed
Fixed
- i18n/el: corrected typo
Διδαγραφή→Διαγραφήinrecipes.deleteConfirm(fix was missing from v0.30.0 release build)
- Added recipe strings translated into 13 locales (ar, el, es, fr, hi, it, ja, pt, ru, sv, tr, zh, uk)
- Added `emptyHint.recipes` to all updated locales; Ukrainian locale gains full `emptyHint` translations for all modules
- Translated `nav.recipes` in all 13 locales
Full changelog
What's Changed
Added
- i18n: recipe strings translated in 13 locales (ar, el, es, fr, hi, it, ja, pt, ru, sv, tr, zh, uk) — contributed by @baragoon
- i18n:
emptyHint.recipesadded to all updated locales; Ukrainian locale additionally gains fullemptyHinttranslations for all modules - i18n:
nav.recipestranslated in all 13 locales
Fixed
- i18n/el: corrected typo
Διδαγραφή→Διαγραφήinrecipes.deleteConfirm
Special thanks to @baragoon for contributing the i18n translations!
Fixed dashboard weather widget visibility with white text on white background.
Full changelog
Fixed
- Dashboard: weather widget background gradient was overridden by the higher-specificity
.dashboard .widgetrule, causing white text on a white background in light mode
Minor fixes and improvements.
Full changelog
Changed
- Docs: SPEC updated with Reminders, Birthdays, and Family Management tables and module sections; Users table reflects
family_roleandavatar_datacolumns - Docs: README lists Reminders and Birthdays in the feature tagline and Highlights section
- Docs: BACKLOG completed-features table brought up to date through v0.29.1
Minor fixes and improvements.
Full changelog
What's Changed
- chore(deps): bump express-rate-limit from 8.3.2 to 8.4.1 in the production-dependencies group by @dependabot[bot] in https://github.com/ulsklyc/oikos/pull/94
New Contributors
- @dependabot[bot] made their first contribution in https://github.com/ulsklyc/oikos/pull/94
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.29.0...v0.29.1
- Persisted event icons for calendar entries
- Richer reminder and date handling flow
Full changelog
What's Changed
- Improves the calendar event customization experience with persisted event icons and a richer reminder/date handling flow by @rafaelfoster in https://github.com/ulsklyc/oikos/pull/95
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.28.1...v0.29.0
Fixed TypeError in upsertGoogleEvents during Google Calendar sync, enabling event import.
Full changelog
Fixed
- Google Calendar:
upsertGoogleEventsuseddb.transaction()instead ofdb.get().transaction(), causing aTypeError: Cannot read properties of undefined (reading 'status')on every initial sync — no events were imported
- PWA offline banner appears at top when connectivity is lost and hides on restore
- Global keyboard shortcuts: / (search), n (new), ? (overview), g d/t/c/s/n (navigate modules)
- Dashboard widget order adjustable via drag‑and‑drop; persisted in user preferences
Full changelog
Added
- Navigation: sidebar nav items now show a native tooltip in the icon-only breakpoint (1024–1279 px), making all 11 modules discoverable without labels
- PWA: offline banner appears at the top of the screen when the device loses connectivity, and hides automatically when the connection is restored
- Desktop: global keyboard shortcuts —
/(search),n(new),?(shortcut overview),g d/t/c/s/n(navigate to module) - Dashboard: widget order is now adjustable via drag-and-drop in the Customize modal; order is persisted in user preferences
- UX:
deleteWithUndoutility inux.js— birthdays deletion now offers an undo toast identical to tasks, notes, contacts, and meals - UX: contextual onboarding hints added to empty states in all modules (tasks, contacts, notes, budget, shopping, birthdays, recipes)
Changed
- Dashboard: widget title icons use
--color-text-secondaryinstead of the module accent color, reducing visual noise when all widgets are visible - Performance:
reminders.cssis now lazy-loaded on demand instead of being included in every page load
Fixed
- UI: modal close button increased from 40 px to 44 px to meet Apple HIG minimum tap target
- UI:
.widget__linkelements now have a 44 px minimum touch target height with correct padding - CSS: removed dead
.fabCSS block — all pages use.page-fab - UX: toasts can now be dismissed by swiping horizontally (> 40 px)
Fixed Google Calendar sync crashes on null/undefined items and ensured OAuth callback waits for sync to report errors.
Full changelog
Fixed
- Google Calendar: null/undefined items returned by the Google API are now skipped instead of crashing the sync with a
TypeError - Google Calendar: the OAuth callback now awaits the initial sync before redirecting, so sync failures are correctly shown as an error in the UI instead of a false success
- More family‑oriented member management flow and profile customization
Full changelog
What's Changed
- Adds a more family-oriented member management flow and profile customization. by @rafaelfoster in https://github.com/ulsklyc/oikos/pull/91
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.26.5...v0.27.0
- Birthday photo maximum size raised to 5 MB
Changelog
Changed
- Birthdays: increased maximum photo upload size from ~0.9 MB to 5 MB
- Dashboard: weather widget moved to first position in default order
- Dashboard: widgets in the same grid row share equal height via flex stretch
Full changelog
Changed
- Dashboard: weather widget is now the first entry in the default widget order
- Dashboard: widgets in the same grid row now share the same height (via flex stretch), eliminating the patchwork gaps between shorter and taller widgets
Fixed birthday dialog appearing after successful save and enabled vertical scrolling on Dashboard widgets.
Full changelog
Fixed
- Birthdays: "Discard changes?" dialog appeared immediately after successfully saving a birthday because
closeModal()was called withoutforce: true, triggering the dirty-form check on a programmatic close - Dashboard (PWA): widget items (tasks, events, meals, notes, birthdays, shopping lists) occasionally blocked vertical swipe-to-scroll; added
touch-action: pan-yso the browser passes vertical pan gestures through to the scroll container
- Removed Dashboard KPI summary bar (duplicated widget categories).
- Replaced two-column main/side workspace layout with a flat responsive grid, aligning all widgets left across screen sizes.
Full changelog
Fixed
- Dashboard: KPI summary bar removed — it duplicated the same widget categories (tasks, calendar, birthdays…) that are already visible as full widgets directly below
- Dashboard: replaced the two-column main/side workspace layout with the established flat responsive grid so all widgets are consistently left-aligned across all screen sizes in the web view
Fixed dashboard crash and empty shopping‑lists widget due to undefined path and invalid SQL.
Full changelog
Fixed
- Dashboard:
path is not definedcrash on every navigation —renderPage()referenced a barepathvariable instead ofroute.path - Dashboard: shopping lists widget caused a server-side SQL error (
HAVINGclause on non-aggregate query) resulting in an empty widget for all users
- Service worker now caches mutable JS/CSS assets using network‑first strategy to prevent stale‑asset issues after deployments
- Birthdays module: track birthdays with optional photo/notes; auto‑syncs to calendar as yearly recurring event and reminder system
- Birthdays dashboard widget: displays upcoming birthdays with age and days‑until labels
- Budget Overview dashboard widget: shows monthly income, expenses, balance, savings rate, and top expense category
Full changelog
Added
- Birthdays module: track family birthdays with name, birth date, optional photo and notes; each entry is automatically synced to the calendar as a yearly recurring event and to the reminder system
- Birthdays dashboard widget: shows the next upcoming birthdays at a glance with age and days-until labels
- Family Participants dashboard widget: displays the number of users added to the family with avatar initials
- Budget Overview dashboard widget: shows monthly income, expenses, balance, savings rate and top expense category
- Dashboard widget customisation extended to include the three new widgets (birthdays, budget, family)
- Settings › General: admin option to set a custom application name shown in the sidebar, browser title and login screen
- Birthday translations across all 16 supported locales
Changed
- Service worker: mutable JS and CSS assets now use network-first caching to eliminate stale-asset issues after deployments
Fixed test suite to implement setAttribute/removeAttribute for aria‑invalid validation.
Full changelog
Fixed
- Test suite:
makeInputmock intest-modal-utils.jsnow implementssetAttribute/removeAttributeso blur-validation tests correctly verify the newaria-invalidattribute behaviour
Form validation now sets aria‑invalid for error announcements.
Full changelog
Added
- Navigation: a dedicated screen-reader announcer (
aria-live="polite") announces the page name on every route change instead of reading the entire page content
Changed
- Color pickers (notes, calendar): swatches now use
role="radiogroup"with localized color names instead of hex codes,aria-checkedreflects the selected state, and Arrow keys navigate between options - Navigation badges: badge counts are now hidden from screen readers (
aria-hidden); the parent nav link'saria-labelis updated to include the count in plain text - Main content area: removed
aria-live="polite"from<main>— it was causing screen readers to read the full page on every navigation
Fixed
- Form validation:
aria-invalid="true"is now set on invalid inputs in all modals and on the login form so screen readers can announce field errors
- Modal save button displays a spinner during async API calls and handles validation/API error states.
- Toast Undo button provides tactile press feedback (scale change, removes tap highlight) within the 5‑second window.
Full changelog
Changed
- Tasks: completing a task now animates the strikethrough line instead of snapping it on instantly
- Modal: save button shows a spinner during async API calls; the spinner disappears immediately if form validation fails, and on API error when the button is re-enabled
- Toast: the Undo button now gives tactile press feedback (scale + removes browser tap highlight) for reliable interaction within the 5-second window
- Renamed navigation item "Pinnwand" to "Notizen"
- Dashboard onboarding overlay guides new users through the three core navigation areas
- Navigation 'More' button now displays name and icon of the active secondary module
Full changelog
Added
- Navigation: the "More" button now shows the name and icon of the active secondary module instead of the generic label, making it clear which module is open
- Dashboard: first-time onboarding overlay guides new users through the app's three core navigation areas
Changed
- Navigation: renamed "Pinnwand" to "Notizen" for clarity
- Login: submit button shows a spinner during authentication; empty fields are highlighted individually with red borders instead of a single generic error message
Fixed
- Modal: closing a modal when the form has unsaved changes no longer double-fires the guard due to a missing
_isClosingflag; the close button now uses an arrow-function listener to avoid stale closure issues
- Modal closure shows "Discard changes?" confirmation when form data is unsaved
Full changelog
Added
- Modal: closing a modal (via Escape, swipe, overlay click, or X button) now shows a "Discard changes?" confirmation dialog when the form has been modified since it was opened; saving or deleting bypasses the prompt
Delete actions now remove items immediately with a 5‑second undo toast.
Full changelog
Changed
- Delete actions in all seven modules (tasks, notes, budget, calendar, contacts, meals, recipes) and shopping list deletion no longer show a confirmation dialog; instead the item is removed immediately and a toast with an Undo button gives a 5-second window to reverse the action before the API call is made
Minor fixes and improvements.
Full changelog
Changed
- Docs:
SPEC.mdupdated to reflect all changes since v0.24.0 — Budget Entries table now documentssubcategorycolumn and DB-backedcategoryFK; newBudget Categories,Budget Subcategories, andAPI Tokensdata-model tables added; Settings section updated with API Tokens tab, corrected language list (added Japanese, Arabic, Hindi, Portuguese), and tab count (six → seven); Budget module section now covers subcategories, custom categories, and all new endpoints; new API Documentation section documents OpenAPI 3.0 spec and authentication options; design tokens--blur-2xsand--module-remindersadded to Colors section - Docs:
README.mdHighlights updated — Budget Tracking now mentions DB-backed subcategories; new API Tokens entry added
- Empty widget states render as a compact inline row (icon + text) on mobile, saving ~40px vertical space per empty widget
- Widget reordering in the "Anpassen" modal now uses View Transition API for smooth animations while respecting `prefers-reduced-motion`
Full changelog
Changed
- Dashboard: empty widget states now render as a compact inline row (icon + text) instead of a centred column, saving ~40px of vertical space per empty widget on mobile
Fixed
- Dashboard: widget body bottom padding increased from 12px to 16px for slightly more breathing room
- Dashboard: widget reordering in "Anpassen" modal now uses the View Transition API for smooth animations; respects
prefers-reduced-motion
- Admins can create named API Bearer/X-API-Key tokens with optional expiry, revocation, and last‑used tracking via a new "API Tokens" settings section.
- OpenAPI 3.0 specification now served at `/api/v1/openapi.json` and `/openapi.json` (downloadable).
- Budget endpoints added: `GET /api/v1/budget/categories` and `GET /api/v1/budget/categories/:key/subcategories` with optional localisation.
Full changelog
Added
- API token authentication: admins can create named Bearer / X-API-Key tokens for external integrations; tokens are SHA-256-hashed at rest, support optional expiry and revocation, and track last-used timestamp
- Settings: new "API Tokens" section for admins to create and revoke tokens; the full token value is shown only once immediately after creation
- OpenAPI 3.0 specification served at
/api/v1/openapi.jsonand/openapi.json(download via?download=1) - Budget: new endpoints
GET /api/v1/budget/categoriesandGET /api/v1/budget/categories/:key/subcategorieswith optional?lang=localisation
Changed
server/logger.jsnow serialisesErrorobjects into structured JSON fields (name, message, stack) instead of logging{}
- Added @media (prefers-contrast: more) block to layout.css with explicit borders for ghost/secondary buttons, removal of decorative shadows on cards, 2px border on form inputs, thicker focus rings (3px, 4px offset), and underline indicator for active nav items
Full changelog
Added
- Accessibility:
layout.cssnow has a@media (prefers-contrast: more)block — ghost and secondary buttons get explicit borders, cards lose decorative shadows, form inputs get a 2px border, focus rings become thicker (3px, 4px offset), and active nav items get an underline as a colour-independent indicator
Fixed
- Design tokens: corrected
--sidebar-width-expandedcomment from1280px+to1440px+to match the actual breakpoint inlayout.css
- Added blur design tokens: --blur-2xs (2px) fills gap below --blur-xs
- Added reminder module token --module-reminders with WCAG AA cyan colors and dark‑mode variant
Full changelog
Added
- Design tokens:
--blur-2xs: blur(2px)added to the blur scale — fills the gap below--blur-xs(4px), used for subtle overlay blurs - Design tokens:
--module-reminders: #0E7490(Cyan-700, WCAG AA) added for the reminders feature; dark mode variant#22D3EE(Cyan-400)
Fixed
- Design tokens: hardcoded
blur(16px),blur(2px), andblur(12px)inlayout.cssreplaced withvar(--blur-md),var(--blur-2xs), andvar(--blur-sm)—prefers-reduced-transparencynow correctly disables all backdrop-filter effects including bottom nav, more-sheet backdrop, and sticky headers - Accessibility:
layout.cssnow has aprefers-reduced-transparencyblock for.nav-bottom,.more-backdrop, and.sticky-header— these three elements previously kept their backdrop-filter active even when the user requested reduced transparency - Reminders: reminder bell icon in toasts now uses
var(--module-reminders)instead of the genericvar(--color-accent)
Fixed undefined design token references and invisible hover text in dashboard components.
Full changelog
Fixed
- Design tokens: added missing
--shadow-xland--shadow-xstokens (with dark mode variants) — resolves undefined CSS custom property references in kanban drag ghost and dashboard widget toggle - Design tokens:
--color-surface-raisedreplaced with--color-surface-hoverindashboard.css— was undefined, causing unstyled hover states in the widget customizer - Design tokens:
--color-textreplaced with--color-text-primaryindashboard.css— was undefined, causing invisible text on hover in the widget customizer - Design tokens: hardcoded
font-weightvalues (700,500,600) inreminders.cssreplaced with--font-weight-bold,--font-weight-medium,--font-weight-semibold
Increased the minimum size of small icon buttons to meet iOS accessibility guidelines.
Full changelog
Fixed
- Accessibility: Skip-to-content link added — keyboard users can bypass navigation and jump directly to main content
- Accessibility: Removed
role="presentation"from modal overlay — restores screen reader access and resolves conflict with existingaria-label - Accessibility: Search overlay now traps keyboard focus — tabbing can no longer escape the overlay into the hidden page
- Interaction: Modal swipe-to-close —
draggingflag stays active on upswing so the panel snaps back correctly instead of getting stuck - Rendering: SVG gradient IDs in the logo are now unique per render — prevents DOM ID collisions on multiple mounts
- Touch targets:
.btn--icon-smminimum size raised from 36×36 px to 44×44 px (--target-base) — meets iOS minimum touch target guideline - Design tokens: Added
--target-base: 44px; documented--target-sm: 32pxas visual-only (not a touch target)
- DB migration 15 migrates existing budget entries to the new slug-based category system
- Expense categories stored as English slugs in `budget_categories` table
- Subcategory support with 35 predefined subcategories across 8 top-level categories
- Custom category and subcategory creation via UI (+ buttons) and new API endpoints
Full changelog
Added
- Budget: expense categories are now stored in the database (
budget_categoriestable) as stable English slugs, replacing hardcoded German strings - Budget: subcategory support for all expense entries — 35 predefined subcategories across 8 top-level categories (housing, food, transport, personal_health, leisure, shopping_clothing, education, financial_other)
- Budget: users can add custom categories and subcategories directly from the entry modal via inline "+ category" / "+ subcategory" buttons
- Budget: new API endpoints
POST /api/v1/budget/categoriesandPOST /api/v1/budget/categories/:key/subcategoriesfor custom category/subcategory creation - Budget: subcategory displayed alongside category in each entry's metadata line
- Budget: CSV export now includes a subcategory column and English column headers
- i18n: all 14 non-German locales extended with new budget category keys (
catHousing,catTransport,catPersonalHealth,catShoppingClothing,catFinancialOther) and all 35 subcategory label keys - All server-side log messages and API error strings translated from German to English — contributed by @rafaelfoster
Changed
- Budget category labels for existing entries migrated to new slug keys via DB migration 15; display names remain fully localised through the i18n system
Fixed missing Italian translations in the recipes section.
Full changelog
Fixed
- Italian (it) locale: translated all missing strings in the recipes section (
nav.recipes,meals.savedRecipeLabel,meals.savedRecipePlaceholder,meals.saveAsRecipe,meals.recipeScaleLabel, and allrecipes.*keys) — contributed by @albanobattistella
- Replaced all remaining hardcoded color and size values in layout, glass, dashboard, and reminders CSS with CSS custom properties.
- Added multiple new design tokens (--text-2xs, --color-overlay-glass, etc.) to tokens.css.
Full changelog
Changed
- Design tokens: replaced all remaining hardcoded color and size values in
layout.css,glass.css,dashboard.css, andreminders.csswith CSS custom properties - Design tokens: added
--text-2xs,--color-overlay-glass,--color-backdrop-glass,--glass-border-overlay,--glass-highlight-mid,--glass-inset-bottom-base,--glass-inset-bottom-hover,--glass-inset-thumb, and--glass-inset-inputtotokens.css
Fixed missing translation keys causing fallback to German for all non‑German locales.
Full changelog
Fixed
- All non-German locales (ar, el, en, es, fr, hi, it, ja, pt, ru, sv, tr, uk, zh): added missing translation keys for
nav.more,calendar.ics.reset/resetToast,settings.ics.*,tasks.filter*,tasks.swiped*,search.*, andreminders.*— these were falling back to German strings for all non-German users
Minor fixes and improvements.
Full changelog
What's Changed
- fix: update swedish translation by @olsson82 in https://github.com/ulsklyc/oikos/pull/81
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.23.13...v0.23.14
- DOM‑based XSS eliminated in Installer (GitHub Advisory #7)
Full changelog
Security
- Installer: replaced template-literal URL construction with the
URLconstructor when setting the final "Open Oikos" link, eliminating a potential DOM-based XSS vector (CodeQL js/xss-through-dom, GitHub Advisory #7)
Fixed iOS PWA bottom navigation bar gap caused by overflow clipping.
Full changelog
Fixed
- iOS PWA: bottom navigation bar gap resolved by removing
overflow: hiddenfrom<html>(iOS Safari bug: this property clipsposition: fixeddescendants) and restoring thebody::afterfill approach; nav bar height is no longer inflated by the safe area padding
Fixed iOS PWA bottom navigation gap by adding padding for the safe‑area inset.
Full changelog
Fixed
- iOS PWA: bottom navigation bar now extends into the home indicator safe area via
padding-bottom: env(safe-area-inset-bottom), reliably eliminating the gap at the screen bottom
Fixed iOS PWA safe‑area fill to match the bottom navigation bar's surface color in light and dark modes.
Full changelog
Fixed
- iOS PWA: safe area fill now uses the same surface color as the bottom navigation bar, so it matches in both light and dark mode
Fixed iOS PWA layout gap by extending body::after to fill the home indicator safe area.
Full changelog
Fixed
- iOS PWA: a
body::afterpseudo-element now fills the home indicator safe area with the same glass background as the bottom navigation, eliminating the gap between the nav bar and the screen edge
Fixed iOS PWA bottom navigation bar to extend into the home indicator safe area.
Full changelog
Fixed
- iOS PWA: bottom navigation bar now extends into the home indicator safe area, removing the gap between the nav and the screen edge
- Sidebar logo replaced with official docs/logo.svg (house + chimney on gradient background) driven by CSS tokens
Full changelog
Fixed
- Navigation: sidebar logo now uses the official
docs/logo.svgartwork (house + chimney on gradient background) instead of a generic Lucide home icon; gradient colors are driven by CSS tokens
- Dashboard greeting widget changes gradient (warm amber‑orange before 11:00, indigo during the day, violet after 18:00)
- FAB speed-dial open/close uses spring cubic-bezier for natural feel
- Sidebar logo replaced with SVG house icon on a gradient background
Full changelog
Changed
- Dashboard: greeting widget now adapts its gradient to the time of day — warm amber-orange in the morning (before 11:00), indigo during the day, and violet in the evening (after 18:00)
- Dashboard: FAB speed-dial open/close rotation now uses a spring cubic-bezier for a more natural feel
- Navigation: sidebar logo is now a proper SVG house icon on a gradient background instead of the CSS letter placeholder
- Widget header icons, badges, and links now use module-specific accent colors (green, violet, orange, pink, amber).
- Meal slots display type‑specific colors on icon and label when planned.
- Pinned note cards receive a subtle background tint matching the note's color.
Full changelog
Changed
- Dashboard: each widget now uses its module accent color (green for tasks, violet for calendar, orange for meals, pink for shopping, amber for notes) for its header icon, badge, and link instead of the global indigo accent
- Dashboard: meal slots now display their type-specific color (amber for breakfast, green for lunch, indigo for dinner, orange for snack) on icon and label when a meal is planned
- Dashboard: pinned note cards now show a subtle background tint matching the note's color
- Dashboard: widget and card hover lift increased from 1 px to 2 px for more perceptible feedback on desktop
- Navigation: active bottom-nav tab now shows a pill-shaped highlight behind the icon for a clearer location indicator
- Shopping widget: progress bar height increased from 4 px to 6 px for better visual weight
- Empty state icons inside widgets now use the tertiary text color instead of the disabled color for improved visibility
Minor fixes and improvements.
Full changelog
Changed
- Docs: web installer (
node tools/installer/install-server.js) is now Option A in all installation guides (README.md,docs/installation.md, GitHub Pagesdocs/install.html); the pre-built Docker image method is relabelled Option B and the build-from-source method Option C
Fixed weather widget wind speed calculation and unit labeling for imperial units.
Full changelog
Fixed
- Weather widget: wind speed is no longer multiplied by 3.6 when
OPENWEATHER_UNITS=imperial(the API already returns mph; the conversion was only correct for metric/standard) - Weather widget: wind unit label now shows
mphfor imperial andkm/hfor metric/standard instead of always showingkm/h
Fixed calendar ICS-synced events rendering at the correct local hour and day.
Full changelog
Fixed
- Calendar: ICS-synced events now render at the correct local hour and day in week/day/month/agenda views; day-matching and hour-positioning previously used raw string slices which returned UTC values instead of browser-local time for events stored with a
Zsuffix
- Installer host and port inputs now validated (strict hostname regex, integer range 1‑65535) to prevent XSS‑through‑DOM (CodeQL js/xss-through-dom alert #7).
Full changelog
Security
- Installer: host and port inputs are now validated against a strict hostname regex and integer range check (1–65535) before being used in any DOM sink or URL template — prevents XSS-through-DOM (CodeQL
js/xss-through-domalert #7)
- External calendar `external_calendars` table stores display name and color; UI shows colored `event-cal-label` badge for synced Google/Apple events
- Helper `fmtLocation(raw)` normalizes ICS LOCATION strings by stripping backslash escapes and converting semicolons/newlines to comma‑separated inline text
Full changelog
Added
- Calendar:
external_calendarsDB table (migration v14) stores display name and color per synced Google/Apple calendar;calendar_eventsgains acalendar_ref_idFK used for join-based name/color lookup in all calendar and dashboard queries - Calendar: Google and Apple sync services now fetch the calendar's display name and background color via
upsertExternalCalendar()and persist them to the new table - Calendar: event popup, agenda, month, week, and day views now show the external calendar name as a colored
event-cal-labelbadge whencal_nameis present - Calendar: event popup and dashboard events list now display the event location using
fmtLocation()which strips RFC 5545 backslash-escapes and normalizes semicolons/newlines to comma-separated inline text - Utils:
fmtLocation(raw)helper added tohtml.jsfor normalizing ICSLOCATIONproperty strings - i18n: task due-date keys (
tasks.overdue,tasks.dueSoon,tasks.dueToday,tasks.dueTomorrow,tasks.noDueDate) added to all 16 supported locale files
Changed
- Dashboard: widget headers flattened — glass card replaced with transparent surface + bottom border; clock icon added to the urgent-tasks chip; overdue and due-soon counts computed separately using
effectiveDue()for accuracy - Glass toolbar (desktop ≥ 1024 px): rounded card style replaced with flat background +
border-top: 3px solid var(--module-accent)+ bottom border only, consistent with other page toolbars - Shopping and Budget page headers:
border-top: 3px solid var(--module-accent)accent stripe added, matching the visual language of all other module headers - Calendar agenda: event color indicator changed from a 10 px circle to a 3 px full-height left bar, matching the dashboard upcoming-events style
- Tasks: filter panel now defaults to
status: 'open'on first load instead of showing all tasks including completed ones - SW cache: bumped to
oikos-shell-v50/oikos-pages-v45/oikos-assets-v45; strategy changed from Stale-While-Revalidate to Cache-First with post-update bypass window
Fixed
- Tasks / Dashboard: sort order now strictly follows effective due date ascending; overdue tasks always surface first; priority used only as tiebreaker. Server-side sort moved to JavaScript for timezone-correct
due_timehandling - Tasks: due date chip now shows the time component when
due_timeis set; overdue/soon/today/tomorrow states computed against current moment rather than midnight - Dashboard: widget navigation links changed from
<a href>to<button type="button">to prevent iOS Safari touch-event interception - Dashboard: FAB shortcut buttons now programmatically open the target page's add modal directly without requiring a second tap
- Dashboard: task items open a quick-action sheet (Edit / Mark done) instead of navigating directly
- Calendar: week-view allday row no longer stretches column widths when event titles are long
- Calendar: incorrect
|| 'var(--color-accent)'color fallback removed from all five event rendering sites - Modal: sheet swipe adds a 10 px dead zone;
touchendtransform reset deferred viarequestAnimationFrame— fixes iOS buttons not responding after a partial swipe - Modal: race condition fixed where opening a confirm dialog before the previous close animation finished caused its buttons to be permanently unresponsive
- Router: page auto-reloads 8 s after the SW-update toast is shown
- Layout: modal overlay
overflow: hidden; form inputs getmin-width: 0; box-sizing: border-boxto prevent overflow in two-column grid containers - PWA: double
padding-bottomon PWA bottom nav removed, fixing extra gap on iPhone safe-area screens - Reminders: field grid changed to
repeat(2, minmax(0, 1fr))to prevent content overflow
Minor fixes and improvements.
Full changelog
What's Changed
- fix(docs): update setup commands formatting for better readability by @baragoon in https://github.com/ulsklyc/oikos/pull/76
Full Changelog: https://github.com/ulsklyc/oikos/compare/v0.22.2...v0.22.3
Fixed JSON parse error in de.json and ICS calendar subscriptions now respect COUNT parameter.
Full changelog
Fixed
- Locale file (
de.json) no longer causes a JSON parse error that made the app completely unusable. Therecipes.deleteConfirmvalue contained a bare ASCII double-quote inside a JSON string, which prematurely terminated the string and broke every page load. - ICS calendar subscriptions now respect the
COUNTparameter in RRULE (RFC 5545). Previously, events with a limited number of occurrences (e.g.RRULE:FREQ=WEEKLY;COUNT=3) were incorrectly shown as upcoming because the expansion loop iterated to the sync window end regardless of the occurrence limit.
- Offline pre‑caching of /pages/recipes.js and /styles/recipes.css enables Recipes page usage without network
Full changelog
Fixed
- App no longer gets stuck on the "Oikos" splash screen when opened in a new tab. Two root causes addressed: (1)
sw.jswas not updated in v0.22.0, so the browser kept the old Service Worker and served stale cached files via Stale-While-Revalidate — cache versions are now bumped (shell v35, pages v30) to force reinstallation and fresh file delivery. (2) A fatal error ininitI18n()(e.g. locale fetch failure while offline) left the splash screen visible forever — the router IIFE now catches such errors, hides the splash screen, and renders a recoverable error state. - Service Worker now pre-caches
/pages/recipes.jsand/styles/recipes.cssintroduced in v0.22.0, enabling offline access to the Recipes page.
- Database migration #13 adds `recipes` and `recipe_ingredients` tables and a `recipe_id` FK column on `meals`. Run the migration before deploying.
- Recipes module with create, edit, duplicate, delete actions and `/recipes` route
- Add to meal plan action pre-fills Meals modal with selected recipe details
- Meals modal supports auto‑fill from saved recipes, quantity scaling, and one‑click save as new recipe
Full changelog
Added
- Recipes module: create, edit, duplicate, and delete reusable recipes with title, notes, a recipe link, and a per-ingredient category. Accessible via the new
/recipesroute and nav entry. - "Add to meal plan" action on recipe cards navigates to Meals and pre-fills the modal with the selected recipe.
- Meals modal: select a saved recipe to auto-fill title, notes, URL, and ingredients; scale ingredient quantities by a numeric factor; save the current meal as a new recipe in one click.
GET/POST /api/v1/recipes,PUT/DELETE /api/v1/recipes/:idREST endpoints with full validation and ingredient sync.- Migration 13:
recipesandrecipe_ingredientstables;recipe_idFK column onmeals.