docs: replace em dashes with hyphens in public-facing docs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -48,4 +48,4 @@ Paste output here.
|
||||
|
||||
## Additional Context
|
||||
|
||||
Any other context — screenshots, related issues, or configuration details.
|
||||
Any other context - screenshots, related issues, or configuration details.
|
||||
|
||||
+2
-2
@@ -24,5 +24,5 @@ Neue Vorschläge? → [Issue öffnen](https://github.com/ulsklyc/oikos/issues/ne
|
||||
| BL-08 | Dashboard: Wetter-Widget Refresh | v0.4.0 |
|
||||
| BL-09 | Kontakte: vCard-Import / -Export | v0.4.0 |
|
||||
| BL-10 | PWA: Offline-Fallback für kritische Seiten | v0.4.0 |
|
||||
| — | UX Polish (Animationen, Bottom Sheet, FAB, Stagger, Vibration) | v0.2.0 |
|
||||
| — | Event-Listener-Leaks, CSS-Lücken, Modal-Tests | v0.2.1 |
|
||||
| - | UX Polish (Animationen, Bottom Sheet, FAB, Stagger, Vibration) | v0.2.0 |
|
||||
| - | Event-Listener-Leaks, CSS-Lücken, Modal-Tests | v0.2.1 |
|
||||
|
||||
+23
-23
@@ -10,46 +10,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
## [0.5.5] - 2026-04-03
|
||||
|
||||
### Fixed
|
||||
- Fix iCloud Calendar sync failing with FOREIGN KEY constraint error — `created_by` was hardcoded to user ID 1 instead of resolving dynamically (fixes #4)
|
||||
- Sync all iCloud calendars instead of only the first one — previously only a single calendar was imported, ignoring Family, subscribed, and other calendars
|
||||
- Add missing `cfgDel` helper function used by `clearCredentials` — disconnecting Apple Calendar would crash
|
||||
- Fix iCloud Calendar sync failing with FOREIGN KEY constraint error - `created_by` was hardcoded to user ID 1 instead of resolving dynamically (fixes #4)
|
||||
- Sync all iCloud calendars instead of only the first one - previously only a single calendar was imported, ignoring Family, subscribed, and other calendars
|
||||
- Add missing `cfgDel` helper function used by `clearCredentials` - disconnecting Apple Calendar would crash
|
||||
- Skip unreachable or broken calendars gracefully instead of aborting the entire sync
|
||||
|
||||
## [0.5.4] - 2026-04-03
|
||||
|
||||
### Fixed
|
||||
- Fix SQLCipher PRAGMA key syntax error on fresh install — hex-encoded key must be wrapped in double quotes for valid PRAGMA syntax (fixes #3)
|
||||
- Fix SQLCipher PRAGMA key syntax error on fresh install - hex-encoded key must be wrapped in double quotes for valid PRAGMA syntax (fixes #3)
|
||||
|
||||
## [0.5.3] - 2026-04-03
|
||||
|
||||
### Security
|
||||
- Fix SQLCipher PRAGMA key interpolation — encryption keys containing single quotes no longer crash on startup; key is now hex-encoded
|
||||
- Enforce minimum password length (8 characters) when admin creates new users — previously any 1-character password was accepted
|
||||
- Fix SQLCipher PRAGMA key interpolation - encryption keys containing single quotes no longer crash on startup; key is now hex-encoded
|
||||
- Enforce minimum password length (8 characters) when admin creates new users - previously any 1-character password was accepted
|
||||
- Add length bounds on username (64 chars) and display_name (128 chars) to prevent unbounded input
|
||||
- Add input length bounds on login (username 64 chars, password 1024 chars)
|
||||
- Invalidate all other sessions when a user changes their password — previously active sessions survived password reset
|
||||
- Session and CSRF cookies now have `secure: true` by default; HTTP is only allowed when `SESSION_SECURE=false` is explicitly set in `.env` — previously cookies were sent without `Secure` flag in non-production environments
|
||||
- Document authorization model in SECURITY.md — clarify that all family members share read/write access to all data by design
|
||||
- Invalidate all other sessions when a user changes their password - previously active sessions survived password reset
|
||||
- Session and CSRF cookies now have `secure: true` by default; HTTP is only allowed when `SESSION_SECURE=false` is explicitly set in `.env` - previously cookies were sent without `Secure` flag in non-production environments
|
||||
- Document authorization model in SECURITY.md - clarify that all family members share read/write access to all data by design
|
||||
|
||||
### Changed
|
||||
- Use multi-stage Docker build to exclude build tools (python3, make, g++) from runtime image
|
||||
- Exclude `docs/` directory from Docker image via `.dockerignore`
|
||||
- Consolidate `dotenv.config()` to single call in `server/index.js` — remove duplicate calls from `server/db.js` and `server/auth.js`
|
||||
- Consolidate `dotenv.config()` to single call in `server/index.js` - remove duplicate calls from `server/db.js` and `server/auth.js`
|
||||
|
||||
## [0.5.2] - 2026-04-01
|
||||
|
||||
### Security
|
||||
- Add rate limiting to SPA fallback route to prevent file system hammering via unauthenticated wildcard requests
|
||||
- Add CSRF protection to auth routes that change state (logout, create user, change password, delete user) — previously bypassed global CSRF middleware due to router registration order
|
||||
- Fix incomplete vCard escaping in contacts export — backslash characters are now escaped first before other special characters (`,`, `;`, newline), preventing injection via contact fields
|
||||
- Add CSRF protection to auth routes that change state (logout, create user, change password, delete user) - previously bypassed global CSRF middleware due to router registration order
|
||||
- Fix incomplete vCard escaping in contacts export - backslash characters are now escaped first before other special characters (`,`, `;`, newline), preventing injection via contact fields
|
||||
- Restrict CI workflow GITHUB_TOKEN to `contents: read` (principle of least privilege)
|
||||
|
||||
## [0.5.1] - 2026-04-01
|
||||
|
||||
### Fixed
|
||||
- Meals: fixed crash when dragging a meal slot — `dragging` state is now destructured before `cleanup()` runs, preventing a null-reference error on drop
|
||||
- Meals: fixed crash when dragging a meal slot - `dragging` state is now destructured before `cleanup()` runs, preventing a null-reference error on drop
|
||||
- i18n: `t()` now resolves dot-notation keys against nested locale JSON objects (e.g. `t('nav.tasks')` correctly returns `"Aufgaben"` instead of the raw key string); affects all pages, components, and navigation
|
||||
- PWA: replaced placeholder "O" icons with the actual Oikos house logo across all icon variants (192, 512, maskable 192, maskable 512, apple-touch-icon, favicon); maskable variants use full-bleed background with logo within the 80% safe zone — fixes Android home screen showing only a blue circle
|
||||
- PWA: replaced placeholder "O" icons with the actual Oikos house logo across all icon variants (192, 512, maskable 192, maskable 512, apple-touch-icon, favicon); maskable variants use full-bleed background with logo within the 80% safe zone - fixes Android home screen showing only a blue circle
|
||||
- PWA: weather widget icons (OpenWeatherMap) now render correctly in installed PWA on Android; service worker no longer intercepts cross-origin image requests (opaque responses caused silent rendering failures in standalone mode)
|
||||
- Settings: language selector replaced from cramped radio buttons to a native `<select>` dropdown using the standard `form-input` style
|
||||
|
||||
@@ -62,8 +62,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Added
|
||||
- i18n: full internationalisation system (`public/i18n.js`) with German (de) and English (en) support; language auto-detected from `navigator.language`, overridable via Settings
|
||||
- i18n: all user-facing strings moved to locale files (`public/locales/de.json`, `public/locales/en.json`); 489 translation keys covering all modules
|
||||
- i18n: locale switch without page reload — all pages, components and navigation re-render via `locale-changed` custom event
|
||||
- i18n: `oikos-locale-picker` Web Component in Settings — three options: System (follows browser language), Deutsch, English
|
||||
- i18n: locale switch without page reload - all pages, components and navigation re-render via `locale-changed` custom event
|
||||
- i18n: `oikos-locale-picker` Web Component in Settings - three options: System (follows browser language), Deutsch, English
|
||||
- i18n: dates and times formatted with `Intl.DateTimeFormat` using the active locale; `formatDate()` and `formatTime()` exported from `i18n.js`
|
||||
- i18n: fallback chain (active locale → German → key) ensures no untranslated keys are shown even if a future locale file is incomplete
|
||||
- i18n: adding a new language requires only one JSON file (`public/locales/xx.json`) and one line in `SUPPORTED_LOCALES`
|
||||
@@ -71,25 +71,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
## [0.4.0] - 2026-03-31
|
||||
|
||||
### Fixed
|
||||
- Mobile: toast notifications no longer overlap with the bottom navigation bar — introduced `--nav-bottom-height` token (scroll area 56px + dots indicator 12px) used consistently by toast container and app content padding
|
||||
- Mobile: toast notifications no longer overlap with the bottom navigation bar - introduced `--nav-bottom-height` token (scroll area 56px + dots indicator 12px) used consistently by toast container and app content padding
|
||||
- Mobile: FAB and page-FAB are now hidden when the virtual keyboard is open, preventing them from covering form inputs; detection uses `visualViewport.resize` with a 75% height threshold
|
||||
- UI: added missing dark-mode colour overrides for shopping, notes, contacts, budget, and settings module tokens — accent stripes now render at readable pastel values in dark theme
|
||||
- UI: added missing dark-mode colour overrides for shopping, notes, contacts, budget, and settings module tokens - accent stripes now render at readable pastel values in dark theme
|
||||
- UI: meals week-navigation bar now shows module accent top-border stripe; settings page now declares --module-accent for consistency with all other modules
|
||||
|
||||
### Added
|
||||
- Shopping: swipe-left to toggle checked/unchecked, swipe-right to delete items on mobile; × delete button hidden on mobile in favour of swipe gesture
|
||||
- Notes: client-side full-text search bar in toolbar — filters by title and content instantly; shows "Keine Treffer" empty state when no match
|
||||
- Notes: client-side full-text search bar in toolbar - filters by title and content instantly; shows "Keine Treffer" empty state when no match
|
||||
- Dashboard: weather widget refresh button (top-right corner) + automatic 30-minute refresh interval; interval is cleared when navigating away
|
||||
- Contacts: vCard export button per contact (downloads .vcf file); vCard import via file input in toolbar (parses FN, TEL, EMAIL, ADR, NOTE, CATEGORIES fields)
|
||||
- PWA: offline fallback page (`/offline.html`) served by service worker when network is unavailable and index.html is not cached; page includes a reload button
|
||||
- UI: module accent colours now applied to three visual layers — active nav tab (bottom bar + sidebar), toolbar top-border stripe, and list/card left-border stripe — giving each module a distinct colour identity
|
||||
- UI: module accent colours now applied to three visual layers - active nav tab (bottom bar + sidebar), toolbar top-border stripe, and list/card left-border stripe - giving each module a distinct colour identity
|
||||
|
||||
## [0.3.0] - 2026-03-31
|
||||
|
||||
### Added
|
||||
- Calendar: recurring events are now expanded in GET /api/v1/calendar — all occurrences within the requested date window are returned as virtual instances; duration is preserved; instances are marked with is_recurring_instance=1 and shown with a ↻ icon in the agenda view; /upcoming also expands recurring events within a 90-day window
|
||||
- Calendar: recurring events are now expanded in GET /api/v1/calendar - all occurrences within the requested date window are returned as virtual instances; duration is preserved; instances are marked with is_recurring_instance=1 and shown with a ↻ icon in the agenda view; /upcoming also expands recurring events within a 90-day window
|
||||
- Budget: recurring entries auto-generate instances for each viewed month; instances deleted by the user are skipped permanently via `budget_recurrence_skipped` table; generated instances are marked with ↩ in the transaction list
|
||||
- Budget: month-over-month comparison in summary cards — each card (Einnahmen, Ausgaben, Saldo) shows a trend line (▲/▼ + delta amount vs. previous month); previous month summary is fetched in parallel with current month
|
||||
- Budget: month-over-month comparison in summary cards - each card (Einnahmen, Ausgaben, Saldo) shows a trend line (▲/▼ + delta amount vs. previous month); previous month summary is fetched in parallel with current month
|
||||
- Meals: drag & drop between slots and days using Pointer Events (touch + mouse); ghost element follows pointer; drop on occupied slot swaps meals; reduced-motion: no ghost animation, interaction still works
|
||||
- Settings: Apple CalDAV credentials form (URL, Apple-ID, app-specific password) with live connection test; admin can connect and disconnect via UI without restarting the server; DB-stored credentials take precedence over .env vars; auto-sync runs every 15 min (configurable via SYNC_INTERVAL_MINUTES)
|
||||
|
||||
@@ -128,7 +128,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [0.1.0] - 2026-03-29
|
||||
|
||||
Initial release of Oikos — a self-hosted family planner for 2–6 person households. Runs as a Docker container behind Nginx with SSL, no cloud dependency.
|
||||
Initial release of Oikos - a self-hosted family planner for 2–6 person households. Runs as a Docker container behind Nginx with SSL, no cloud dependency.
|
||||
|
||||
### Added
|
||||
|
||||
|
||||
+18
-18
@@ -10,7 +10,7 @@ Have a question before diving in? Start a thread in [Discussions](https://github
|
||||
|
||||
**Oikos enforces a strict "no frameworks, no build tools" policy.** This is a permanent architectural decision, not a temporary limitation.
|
||||
|
||||
Specifically — the following will **not** be merged:
|
||||
Specifically - the following will **not** be merged:
|
||||
|
||||
- Frontend frameworks (React, Vue, Svelte, Angular, etc.)
|
||||
- Bundlers or transpilers (Webpack, Vite, Rollup, esbuild, TypeScript, etc.)
|
||||
@@ -35,7 +35,7 @@ git clone https://github.com/ulsklyc/oikos.git
|
||||
cd oikos
|
||||
npm install
|
||||
cp .env.example .env
|
||||
# Set SESSION_SECRET — leave DB_ENCRYPTION_KEY empty (no SQLCipher needed locally)
|
||||
# Set SESSION_SECRET - leave DB_ENCRYPTION_KEY empty (no SQLCipher needed locally)
|
||||
npm run dev
|
||||
```
|
||||
|
||||
@@ -47,7 +47,7 @@ npm run dev
|
||||
npm test # All suites
|
||||
```
|
||||
|
||||
Tests use the Node.js built-in test runner with in-memory SQLite. No running server or database required — tests import route handlers directly.
|
||||
Tests use the Node.js built-in test runner with in-memory SQLite. No running server or database required - tests import route handlers directly.
|
||||
|
||||
---
|
||||
|
||||
@@ -60,16 +60,16 @@ server/
|
||||
index.js # Express entry point, middleware chain
|
||||
db.js # SQLite connection + migration runner (append-only)
|
||||
auth.js # Session auth + user management
|
||||
routes/ # API route handlers — one file per module
|
||||
routes/ # API route handlers - one file per module
|
||||
services/ # Business logic (calendar sync, recurrence engine)
|
||||
public/
|
||||
index.html # SPA shell (single entry point)
|
||||
router.js # Client-side History API router
|
||||
api.js # Fetch wrapper (auth, CSRF, error handling)
|
||||
styles/
|
||||
tokens.css # Design tokens — all colors, radii, shadows, fonts
|
||||
tokens.css # Design tokens - all colors, radii, shadows, fonts
|
||||
components/ # Reusable Web Components (oikos-* prefix)
|
||||
pages/ # Page modules — each exports a render() function
|
||||
pages/ # Page modules - each exports a render() function
|
||||
sw.js # Service worker
|
||||
offline.html # Offline fallback page (served by service worker)
|
||||
test-[module].js # One test file per module (project root)
|
||||
@@ -80,8 +80,8 @@ docs/ # Product spec, screenshots
|
||||
|
||||
- Every API route lives in `server/routes/` and follows the same `try/catch` → JSON response pattern
|
||||
- Every frontend page is an ES module in `public/pages/` that exports `render()`
|
||||
- All design values come from `tokens.css` — never hardcode colors, radii, or shadows
|
||||
- Database migrations are appended to the `migrations` array in `server/db.js` — never modify existing entries
|
||||
- All design values come from `tokens.css` - never hardcode colors, radii, or shadows
|
||||
- Database migrations are appended to the `migrations` array in `server/db.js` - never modify existing entries
|
||||
|
||||
---
|
||||
|
||||
@@ -133,7 +133,7 @@ Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/):
|
||||
|
||||
**Types:** `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `style` (formatting, not CSS)
|
||||
|
||||
**Scope:** The module or area affected — `tasks`, `shopping`, `meals`, `calendar`, `budget`, `notes`, `contacts`, `auth`, `db`, `ui`, `pwa`
|
||||
**Scope:** The module or area affected - `tasks`, `shopping`, `meals`, `calendar`, `budget`, `notes`, `contacts`, `auth`, `db`, `ui`, `pwa`
|
||||
|
||||
**Examples:**
|
||||
|
||||
@@ -149,15 +149,15 @@ chore: update express to 4.21
|
||||
**Rules:**
|
||||
|
||||
- Subject line: imperative mood, lowercase, no period, max 72 characters
|
||||
- Body (optional): explain *why*, not *what* — the diff shows the what
|
||||
- One logical change per commit — don't mix features with formatting
|
||||
- Body (optional): explain *why*, not *what* - the diff shows the what
|
||||
- One logical change per commit - don't mix features with formatting
|
||||
|
||||
### 5. Open a pull request
|
||||
|
||||
- Target branch: `main`
|
||||
- Title: follows the same Conventional Commits format as your commits
|
||||
- Description: explain what the PR does, why, and link the related issue (`Closes #123`)
|
||||
- Keep PRs focused — one feature or fix per PR
|
||||
- Keep PRs focused - one feature or fix per PR
|
||||
|
||||
**Before opening:**
|
||||
|
||||
@@ -178,29 +178,29 @@ PRs are reviewed by the maintainer. Expect feedback within a few days. Once appr
|
||||
- ES modules everywhere (`import`/`export`, never `require`)
|
||||
- Semicolons: **yes**
|
||||
- Header comment in every file: purpose, module, dependencies
|
||||
- `try/catch` in every route handler — no unhandled promise rejections
|
||||
- No `eval()`, no `innerHTML` with user input — use `textContent` or DOM API
|
||||
- `try/catch` in every route handler - no unhandled promise rejections
|
||||
- No `eval()`, no `innerHTML` with user input - use `textContent` or DOM API
|
||||
|
||||
### Frontend
|
||||
|
||||
- Web Component prefix: `oikos-` (one component per file)
|
||||
- All UI text in **German** (the app targets German-speaking families)
|
||||
- Date format: `DD.MM.YYYY` — Time format: `HH:MM` (24h)
|
||||
- CSS uses design tokens from `public/styles/tokens.css` — never hardcode values
|
||||
- Date format: `DD.MM.YYYY` - Time format: `HH:MM` (24h)
|
||||
- CSS uses design tokens from `public/styles/tokens.css` - never hardcode values
|
||||
- Pages export a `render()` function, no side effects on import
|
||||
|
||||
### Backend
|
||||
|
||||
- One route file per module in `server/routes/`
|
||||
- API responses: `{ data: ... }` on success, `{ error: string, code: number }` on failure
|
||||
- Database migrations: append to the `migrations` array in `server/db.js` — **never modify existing entries**
|
||||
- Database migrations: append to the `migrations` array in `server/db.js` - **never modify existing entries**
|
||||
- Every table: `id INTEGER PRIMARY KEY`, `created_at TEXT`, `updated_at TEXT` (ISO 8601)
|
||||
|
||||
### Testing
|
||||
|
||||
- One test file per module in the project root (`test-[module].js`)
|
||||
- Tests use in-memory SQLite via `--experimental-sqlite`
|
||||
- Import route handlers directly — no HTTP calls, no running server
|
||||
- Import route handlers directly - no HTTP calls, no running server
|
||||
|
||||
---
|
||||
|
||||
|
||||
+10
-10
@@ -1,6 +1,6 @@
|
||||
# Installation Guide
|
||||
|
||||
Complete setup instructions for Oikos — from Docker installation to your first login.
|
||||
Complete setup instructions for Oikos - from Docker installation to your first login.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@@ -86,7 +86,7 @@ Copy the example environment file and edit it with your own values:
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Open `.env` in a text editor and change at least the two secret values — see the [Environment Variables](#environment-variables) section for full details. The critical ones:
|
||||
Open `.env` in a text editor and change at least the two secret values - see the [Environment Variables](#environment-variables) section for full details. The critical ones:
|
||||
|
||||
```bash
|
||||
# Generate secure values for these:
|
||||
@@ -100,7 +100,7 @@ Generate a secure random string:
|
||||
openssl rand -hex 32
|
||||
```
|
||||
|
||||
Run this command **twice** — once for `SESSION_SECRET` and once for `DB_ENCRYPTION_KEY`. Paste each result into your `.env` file.
|
||||
Run this command **twice** - once for `SESSION_SECRET` and once for `DB_ENCRYPTION_KEY`. Paste each result into your `.env` file.
|
||||
|
||||
### 3. Build and Start the Container
|
||||
|
||||
@@ -171,7 +171,7 @@ All configuration happens in the `.env` file. The container reads these values o
|
||||
|
||||
| Variable | Description | Default | Required |
|
||||
|----------|-------------|---------|----------|
|
||||
| `SESSION_SECRET` | Secret key for signing session cookies. **Change this!** | — | **Yes** |
|
||||
| `SESSION_SECRET` | Secret key for signing session cookies. **Change this!** | - | **Yes** |
|
||||
| `SESSION_SECURE` | Set to `false` if accessing without HTTPS (e.g. direct localhost). Set in `docker-compose.yml` by default. | `true` | No |
|
||||
| `RATE_LIMIT_WINDOW_MS` | Time window for rate limiting (ms) | `60000` | No |
|
||||
| `RATE_LIMIT_MAX_ATTEMPTS` | Max login attempts per window | `5` | No |
|
||||
@@ -188,7 +188,7 @@ openssl rand -hex 32
|
||||
| Variable | Description | Default | Required |
|
||||
|----------|-------------|---------|----------|
|
||||
| `DB_PATH` | Path to the SQLite database file inside the container | `/data/oikos.db` | No |
|
||||
| `DB_ENCRYPTION_KEY` | Encryption key for SQLCipher AES-256. **Change this!** | — | **Yes** |
|
||||
| `DB_ENCRYPTION_KEY` | Encryption key for SQLCipher AES-256. **Change this!** | - | **Yes** |
|
||||
|
||||
Generate a secure `DB_ENCRYPTION_KEY`:
|
||||
|
||||
@@ -202,7 +202,7 @@ openssl rand -hex 32
|
||||
|
||||
| Variable | Description | Default | Required |
|
||||
|----------|-------------|---------|----------|
|
||||
| `OPENWEATHER_API_KEY` | API key from [openweathermap.org](https://openweathermap.org/api) | — | No |
|
||||
| `OPENWEATHER_API_KEY` | API key from [openweathermap.org](https://openweathermap.org/api) | - | No |
|
||||
| `OPENWEATHER_CITY` | City name for weather display | `Berlin` | No |
|
||||
| `OPENWEATHER_UNITS` | Unit system (`metric` or `imperial`) | `metric` | No |
|
||||
| `OPENWEATHER_LANG` | Language for weather descriptions | `de` | No |
|
||||
@@ -211,8 +211,8 @@ openssl rand -hex 32
|
||||
|
||||
| Variable | Description | Default | Required |
|
||||
|----------|-------------|---------|----------|
|
||||
| `GOOGLE_CLIENT_ID` | OAuth 2.0 Client ID from Google Cloud Console | — | No |
|
||||
| `GOOGLE_CLIENT_SECRET` | OAuth 2.0 Client Secret | — | No |
|
||||
| `GOOGLE_CLIENT_ID` | OAuth 2.0 Client ID from Google Cloud Console | - | No |
|
||||
| `GOOGLE_CLIENT_SECRET` | OAuth 2.0 Client Secret | - | No |
|
||||
| `GOOGLE_REDIRECT_URI` | OAuth callback URL | `https://<YOUR-DOMAIN>/api/v1/calendar/google/callback` | No |
|
||||
|
||||
### Apple Calendar Sync (Optional)
|
||||
@@ -220,8 +220,8 @@ openssl rand -hex 32
|
||||
| Variable | Description | Default | Required |
|
||||
|----------|-------------|---------|----------|
|
||||
| `APPLE_CALDAV_URL` | CalDAV server URL | `https://caldav.icloud.com` | No |
|
||||
| `APPLE_USERNAME` | Apple ID email | — | No |
|
||||
| `APPLE_APP_SPECIFIC_PASSWORD` | App-specific password (generate at [appleid.apple.com](https://appleid.apple.com/)) | — | No |
|
||||
| `APPLE_USERNAME` | Apple ID email | - | No |
|
||||
| `APPLE_APP_SPECIFIC_PASSWORD` | App-specific password (generate at [appleid.apple.com](https://appleid.apple.com/)) | - | No |
|
||||
|
||||
### Sync
|
||||
|
||||
|
||||
Reference in New Issue
Block a user