Shirecal

Shirecal is a Val Town HTTP val that turns a JSON payload of Middle-earth events into an iCalendar (.ics) feed. The val stores events in Val Town blob storage and always serves the next upcoming instance for each event (including multi-day spans).

Routes

  • GET / – Returns an .ics file with the next occurrence of every stored event.
  • GET /?format=json – Returns the currently stored events as JSON.
  • PUT / – Replaces all stored events. Body must be JSON shaped like { "events": ShireEvent[] }.

Event shape

interface ShireEvent { start: string; // MM-DD end?: string; // MM-DD (optional) text: string; // Narrative snippet used as the calendar description characters: string[]; // Key figures tied to the event (e.g. ["Frodo", "Sam"]) sourceText: string; // e.g. "The Two Towers" sourceChapter: string; // e.g. "The Forbidden Pool" sourceMovie?: string; // e.g. "The Two Towers (Extended Edition)" sourceTimestamp?: string; // HH:MM:SS within the chosen cut location: string; // Where the scene happens (best-effort label) }
  • start and end are month/day strings (MM-DD).
  • Leave end blank for single-day events.
  • When end is earlier than start (e.g. 12-29 to 01-02), the event wraps into the next year automatically.
  • characters drives the calendar event summary (Gandalf's Journey, Frodo & Sam, etc.). Include the central figures mentioned in the narrative.
  • sourceText and sourceChapter annotate where the moment appears in Tolkien's canon so subscribers can trace the scene.
  • sourceMovie / sourceTimestamp (optional) point to the film adaptation and timestamp; use Not in film when the scene never made it to the screen.
  • Movie deep links are generated at runtime from the timestamp using the official YouTube Movies URLs for each Extended Edition.
  • location keeps a concise label for the place; we surface it inside the event body and set the ICS LOCATION property.