docs: update SPEC, BACKLOG, and README for v0.20–v0.23 changes

- SPEC.md: add Recipes + Recipe Ingredients tables, recipe_id FK on Meals,
  External Calendars table, calendar_ref_id FK on Calendar Events, Recipes
  module section, recipe integration in Meals module, external calendar
  name/color badge and location display in Calendar module
- BACKLOG.md: add completed entries for ICS subscriptions, web/CLI installer,
  bootstrap setup endpoint, Recipes module, external calendar names/colors,
  event location, and Tasks/Dashboard improvements
- README.md: add Recipes to module list and Highlights section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ulas Kalayci
2026-04-22 08:02:52 +02:00
parent eaf48eb5fb
commit e5669fec24
3 changed files with 56 additions and 1 deletions
+10
View File
@@ -53,3 +53,13 @@ New suggestion? → [Open an issue](https://github.com/ulsklyc/oikos/issues/new?
| - | Budget: TRY (Turkish Lira) and RUB (Russian Ruble) added to currency list | v0.16.3 | | - | Budget: TRY (Turkish Lira) and RUB (Russian Ruble) added to currency list | v0.16.3 |
| - | i18n: Japanese (ja), Arabic (ar), Hindi (hi), Portuguese (pt) locales (567 keys each) | v0.19.0 | | - | i18n: Japanese (ja), Arabic (ar), Hindi (hi), Portuguese (pt) locales (567 keys each) | v0.19.0 |
| - | Budget: AED (UAE Dirham), BRL (Brazilian Real), INR (Indian Rupee), SAR (Saudi Riyal) added to currency list | v0.19.0 | | - | Budget: AED (UAE Dirham), BRL (Brazilian Real), INR (Indian Rupee), SAR (Saudi Riyal) added to currency list | v0.19.0 |
| - | ICS/webcal URL subscriptions: per-subscription color, shared/private visibility, auto-sync, SSRF protection, ETag conditional fetch, RRULE expansion, `user_modified` guard, "Reset to original" link | v0.20.38 |
| - | Web installer (`tools/installer/`): browser-based wizard, auto-configures `.env`, starts Docker, creates admin account | v0.21.0 |
| - | CLI installer (`install.sh`): 7-step interactive wizard, prerequisite check, secret generation, optional integrations, Docker startup, `--env-file` non-interactive mode | v0.21.0 |
| - | Bootstrap endpoint `POST /api/v1/auth/setup`: first-run admin creation via HTTP without shell access | v0.21.0 |
| - | Recipes module: CRUD with notes, recipe link, per-ingredient categories; duplicate; "Add to meal plan"; save meal as recipe | v0.22.0 |
| - | Meals: select recipe to auto-fill modal, scale ingredient quantities | v0.22.0 |
| - | External calendar display names & colors: `external_calendars` table (migration v14), colored `event-cal-label` badge in all calendar views | v0.23.0 |
| - | Calendar event location display with RFC 5545 backslash-escape normalization (`fmtLocation()`) | v0.23.0 |
| - | Tasks: filter defaults to `status: open`; effective due date sort; due chip shows time component | v0.23.0 |
| - | Dashboard: FAB shortcuts open new-item modal directly after navigation | v0.23.0 |
+3 -1
View File
@@ -2,7 +2,7 @@
<img src="docs/logo.svg" alt="Oikos" width="120" /> <img src="docs/logo.svg" alt="Oikos" width="120" />
<h1>Oikos</h1> <h1>Oikos</h1>
<p><strong>Self-hosted family planner for small households</strong></p> <p><strong>Self-hosted family planner for small households</strong></p>
<p>Tasks · Shopping Lists · Meal Planning · Calendar Sync · Budget · Notes · Contacts</p> <p>Tasks · Shopping Lists · Meal Planning · Recipes · Calendar Sync · Budget · Notes · Contacts</p>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT License"></a> <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT License"></a>
<a href="https://github.com/ulsklyc/oikos/releases"><img src="https://img.shields.io/github/v/release/ulsklyc/oikos?style=flat-square&color=007AFF&label=release" alt="Latest Release"></a> <a href="https://github.com/ulsklyc/oikos/releases"><img src="https://img.shields.io/github/v/release/ulsklyc/oikos?style=flat-square&color=007AFF&label=release" alt="Latest Release"></a>
@@ -49,6 +49,8 @@
**Meal Planning:** Weekly drag-and-drop planner with ingredient lists and shopping export **Meal Planning:** Weekly drag-and-drop planner with ingredient lists and shopping export
**Recipes:** Create, edit, duplicate, and delete reusable recipes with notes, a recipe link, and per-ingredient categories. Pre-fill meal slots from a recipe and scale ingredient quantities; save any meal as a recipe with one click.
**Calendar Sync:** Two-way sync with Google Calendar (OAuth) and Apple iCloud (CalDAV); subscribe to any public ICS/webcal URL with per-subscription color, private/shared visibility, and automatic sync **Calendar Sync:** Two-way sync with Google Calendar (OAuth) and Apple iCloud (CalDAV); subscribe to any public ICS/webcal URL with per-subscription color, private/shared visibility, and automatic sync
**Budget Tracking:** Income and expenses, recurring entries, configurable currency (15 currencies), monthly trends, CSV export **Budget Tracking:** Income and expenses, recurring entries, configurable currency (15 currencies), monthly trends, CSV export
+43
View File
@@ -67,8 +67,27 @@ Custom, household-wide category list for shopping items. Replaces the old hardco
| title | TEXT | NOT NULL | | title | TEXT | NOT NULL |
| notes | TEXT | | | notes | TEXT | |
| recipe_url | TEXT | nullable, URL to recipe | | recipe_url | TEXT | nullable, URL to recipe |
| recipe_id | INTEGER | FK → Recipes (ON DELETE SET NULL), nullable |
| created_by | INTEGER | FK → Users, NOT NULL | | created_by | INTEGER | FK → Users, NOT NULL |
### Recipes
Reusable recipe cards that can be pre-filled into meal slots.
| Column | Type | Constraint |
|--------|------|-----------|
| title | TEXT | NOT NULL |
| notes | TEXT | |
| recipe_url | TEXT | nullable |
| created_by | INTEGER | FK → Users (CASCADE delete) |
### Recipe Ingredients
| Column | Type | Constraint |
|--------|------|-----------|
| recipe_id | INTEGER | FK → Recipes (CASCADE delete), NOT NULL |
| name | TEXT | NOT NULL |
| quantity | TEXT | |
| category | TEXT | NOT NULL (default 'Sonstiges') |
### Meal Ingredients ### Meal Ingredients
| Column | Type | Constraint | | Column | Type | Constraint |
|--------|------|-----------| |--------|------|-----------|
@@ -94,6 +113,18 @@ Custom, household-wide category list for shopping items. Replaces the old hardco
| recurrence_rule | TEXT | iCal RRULE | | recurrence_rule | TEXT | iCal RRULE |
| subscription_id | INTEGER | FK → ICS Subscriptions (CASCADE delete) | | subscription_id | INTEGER | FK → ICS Subscriptions (CASCADE delete) |
| user_modified | INTEGER | 0/1 — prevents sync overwrite when 1 | | user_modified | INTEGER | 0/1 — prevents sync overwrite when 1 |
| calendar_ref_id | INTEGER | FK → External Calendars (ON DELETE SET NULL) |
### External Calendars
Display metadata (name, color) for synced Google/Apple calendars. Populated automatically during sync.
| Column | Type | Constraint |
|--------|------|-----------|
| source | TEXT | 'google' or 'apple', NOT NULL |
| external_id | TEXT | Calendar ID from the provider, NOT NULL |
| name | TEXT | Display name from the provider, NOT NULL |
| color | TEXT | Background color from the provider (HEX) |
| UNIQUE | | (source, external_id) |
### Notes ### Notes
| Column | Type | Constraint | | Column | Type | Constraint |
@@ -212,8 +243,18 @@ Weekly view (MonSun), slots: breakfast / lunch / dinner / snack.
- Week navigation forward/back - Week navigation forward/back
- Drag & drop between days/slots - Drag & drop between days/slots
- Autocomplete from meal history - Autocomplete from meal history
- **Recipe integration:** Select a saved recipe from the meal modal to auto-fill title, notes, URL, and ingredients. Scale ingredient quantities by a numeric factor. Save the current meal as a new recipe with one click.
- **Customizable meal visibility:** In Settings, users can toggle which meal types (breakfast, lunch, dinner, snack) are shown in the planner. Stored as household-wide preference in `sync_config` (key: `visible_meal_types`). At least one type must remain active. - **Customizable meal visibility:** In Settings, users can toggle which meal types (breakfast, lunch, dinner, snack) are shown in the planner. Stored as household-wide preference in `sync_config` (key: `visible_meal_types`). At least one type must remain active.
### Recipes (`/recipes`)
Reusable recipe cards linked to meal slots.
- CRUD: title, notes, recipe link, per-ingredient category
- Duplicate existing recipes
- "Add to meal plan" navigates to `/meals` with the selected recipe pre-filled in the modal
- REST API: `GET/POST /api/v1/recipes`, `PUT/DELETE /api/v1/recipes/:id` with ingredient sync
### Calendar (`/calendar`) ### Calendar (`/calendar`)
**Views:** Month (default, dot indicators), Week (hour grid), Day (timeline), Agenda (list). **Views:** Month (default, dot indicators), Week (hour grid), Day (timeline), Agenda (list).
@@ -224,6 +265,8 @@ Weekly view (MonSun), slots: breakfast / lunch / dinner / snack.
- **Google Calendar:** OAuth 2.0, Calendar API v3, two-way sync - **Google Calendar:** OAuth 2.0, Calendar API v3, two-way sync
- **Apple Calendar:** CalDAV (tsdav), two-way sync - **Apple Calendar:** CalDAV (tsdav), two-way sync
- **ICS Subscriptions:** Subscribe to any public ICS/webcal URL (e.g. public holidays, sports schedules). Per-subscription color, private/shared visibility, manual "Sync now" and automatic sync on the shared interval. RRULE events expanded into a rolling ±6/+12 month window. SSRF-protected (DNS pre-resolution), ETag/Last-Modified conditional fetch, 10 MB limit, 15 s timeout. User-edited events are protected from being overwritten (`user_modified`); a "Reset to original" link restores them. - **ICS Subscriptions:** Subscribe to any public ICS/webcal URL (e.g. public holidays, sports schedules). Per-subscription color, private/shared visibility, manual "Sync now" and automatic sync on the shared interval. RRULE events expanded into a rolling ±6/+12 month window. SSRF-protected (DNS pre-resolution), ETag/Last-Modified conditional fetch, 10 MB limit, 15 s timeout. User-edited events are protected from being overwritten (`user_modified`); a "Reset to original" link restores them.
- **External calendar names & colors:** Google and Apple sync stores each calendar's display name and background color in the `external_calendars` table (migration v14). A colored `event-cal-label` badge appears in event popups, agenda, month, week, and day views when `cal_name` is present.
- **Event location:** Event popup and dashboard display the location field with RFC 5545 backslash-escape normalization (`\n`, `\,`, `\;`, `\\`) via `fmtLocation()` in `public/utils/html.js`.
- Configurable sync interval (default 15 min) - Configurable sync interval (default 15 min)
- External events visually distinguishable - External events visually distinguishable
- Conflicts: external event wins, local additions are preserved - Conflicts: external event wins, local additions are preserved