# Feature Specification: Add Event to Calendar **Feature**: `013-calendar-export` **Created**: 2026-03-06 **Status**: Draft **Source**: Migrated from spec/userstories.md ## User Scenarios & Testing ### User Story 1 - Download .ics file (Priority: P1) A guest who wants to remember the event opens the event page and downloads an iCalendar file to import into their personal calendar application. The file contains all relevant event details: title, description, start date/time, location, and the public event URL. The UID in the file is derived from the event token so that re-downloading the file and re-importing it updates the existing calendar entry rather than creating a duplicate. **Why this priority**: Core calendar integration — the most common and universally supported way to add an event to a calendar across all platforms. **Independent Test**: Can be fully tested by visiting a valid event page, clicking the `.ics` download link, and verifying the downloaded file is a valid iCalendar (RFC 5545) document with the correct event fields and a stable UID. **Acceptance Scenarios**: 1. **Given** a valid event page, **When** the guest clicks the `.ics` download link, **Then** a standards-compliant iCalendar file is downloaded containing the event title, description (if present), start date and time, location (if present), the public event URL, and a unique UID derived from the event token. 2. **Given** the guest downloads the `.ics` file twice for the same event, **When** they import both files into a calendar application, **Then** the calendar application updates the existing entry rather than creating a duplicate (due to the stable UID). 3. **Given** a guest holding only the event link (no RSVP, no login), **When** they access the `.ics` download link, **Then** the file is served without requiring any authentication or personal data. 4. **Given** an event whose expiry date has passed, **When** the guest accesses the `.ics` download link, **Then** the file is still served (the guest can still obtain the calendar record of a past event). --- ### User Story 2 - Subscribe via webcal:// link (Priority: P2) A guest subscribes to the event via a `webcal://` link so that their calendar application automatically picks up any changes — such as a rescheduled date or updated location — when the organizer edits the event via US-5. **Why this priority**: Adds live-update value on top of the static `.ics` download. Requires the `.ics` download (P1) to already work. Most useful in conjunction with US-5 (Edit event details). **Independent Test**: Can be tested by opening the `webcal://` URL in a calendar application and verifying it subscribes to the feed and shows the correct event details. **Acceptance Scenarios**: 1. **Given** a valid event page, **When** the guest clicks the `webcal://` subscription link, **Then** their calendar application subscribes to the feed and displays the event. 2. **Given** a subscribed `webcal://` feed and an organizer who edits the event date via US-5, **When** the calendar application syncs the feed, **Then** the calendar entry is updated to reflect the new date. 3. **Given** a `webcal://` endpoint, **When** it is accessed, **Then** it serves identical iCalendar content as the `.ics` download, using the same event token in the URL. --- ### User Story 3 - Cancelled event reflected in calendar (Priority: P3) When an event is cancelled (US-18), the `.ics` file and `webcal://` feed include `STATUS:CANCELLED` so that subscribed calendar applications reflect the cancellation automatically on their next sync. **Why this priority**: Quality-of-life enhancement dependent on US-18 (cancel event). Deferred until US-18 is implemented. **Independent Test**: Can be tested by cancelling an event and verifying the calendar feed includes `STATUS:CANCELLED`. **Acceptance Scenarios**: 1. **Given** an event that has been cancelled (US-18), **When** a calendar application syncs the `webcal://` feed, **Then** the calendar entry is updated to show the cancelled status. 2. **Given** an event that has been cancelled (US-18), **When** the guest downloads the `.ics` file, **Then** it includes `STATUS:CANCELLED`. > **Note**: Deferred until US-18 is implemented. --- ### Edge Cases - What happens when the event has no description or location? The `.ics` file must omit those optional fields rather than including blank values. - What happens if the server has no public URL configured? The event URL included in the `.ics` file must always be the correct public event URL. - What happens if the event's date or timezone changes after a guest already imported the `.ics` file? The static import will be stale; the `webcal://` subscription will auto-update on next sync. ## Requirements ### Functional Requirements - **FR-001**: System MUST expose a server-side endpoint that generates and serves a standards-compliant iCalendar (RFC 5545) `.ics` file for any event identified by its event token. - **FR-002**: The `.ics` file MUST include: event title, description (if present), start date and time, location (if present), the public event URL, and a unique UID derived from the event token. - **FR-003**: The UID in the `.ics` file MUST be stable across regenerations (same event token always produces the same UID) so that calendar applications update existing entries on re-import rather than creating duplicates. - **FR-004**: The `.ics` file MUST be generated server-side; no external calendar or QR code service is called. - **FR-005**: System MUST expose a `webcal://` subscription endpoint that serves identical iCalendar content as the `.ics` download, using the same event token in the URL. - **FR-006**: Both the `.ics` download link and the `webcal://` subscription link MUST be accessible to any visitor holding the event link — no RSVP, login, or personal data required. - **FR-007**: No personal data, name, or IP address MUST be logged when either link is accessed. - **FR-008**: Both links MUST remain available and functional after the event's expiry date has passed. - **FR-009**: When an event is cancelled (US-18), the `.ics` file and `webcal://` feed MUST include `STATUS:CANCELLED`. [Deferred until US-18 is implemented] ### Key Entities - **CalendarFeed**: A virtual resource derived from the Event entity. Identified by the event token. Serialized to iCalendar (RFC 5545) format on demand. Has no independent storage — always generated from current event state. ## Success Criteria ### Measurable Outcomes - **SC-001**: Downloading the `.ics` file and importing it into a standard calendar application (Google Calendar, Apple Calendar, Outlook) results in the event appearing with correct title, date/time, and location. - **SC-002**: Re-importing the `.ics` file after an event edit updates the existing calendar entry rather than creating a duplicate. - **SC-003**: Subscribing via `webcal://` and triggering a calendar sync after an event edit (US-5) reflects the updated details in the calendar application. - **SC-004**: Both endpoints are accessible without authentication and without transmitting any personal data. - **SC-005**: No external service is contacted during `.ics` generation or `webcal://` feed serving.