Virtual ics file

I once did this, a bit in a hurry:

site/models/event.php

<?php 
use Kirby\Cms\Page;
use Kirby\Cms\File;
use Jsvrcek\ICS\Model\Calendar;
use Jsvrcek\ICS\Model\CalendarEvent;
use Jsvrcek\ICS\Model\Description\Location;

use Jsvrcek\ICS\Utility\Formatter;
use Jsvrcek\ICS\CalendarStream;
use Jsvrcek\ICS\CalendarExport;


class ICSFile extends File {
  private $eventStart = null;
  private $eventEnd = null;
  private $eventName = null;
  private $wholeDay = false;
  private $eventLocation = null;
  private $timezone = null;


  // this needs to exist or deleting the page won't work
  public function delete(): bool
  {
    return true;
  }
  
  public function __construct($eventPage) {
    
    $this->eventStart = new DateTime($eventPage->date(), $this->timezone);
    if($eventPage->enddate()->isEmpty()) {
      $this->eventEnd = clone $this->eventStart;
      $this->eventEnd->setTime(23,59,59);
      if($this->eventStart->format('H:i:s') === '00:00:00') {
        $this->wholeDay = true;
      }
    } else {
      $this->eventEnd = new DateTime($eventPage->enddate(), $this->timezone);
    }


    $this->eventName = $eventPage->title();
    $this->eventLocation = $eventPage->place();
    $this->eventUrl = $eventPage->url() . '.ics';
    $this->timezone = new DateTimeZone('Europe/Zurich');

    parent::__construct([
      'filename' => 'calendar.ics',
      'url' => $this->eventUrl,
      'template' => 'attachment',
      'parent' => $eventPage,
      'content' => []
    ]);
  }

  public function writeContent(array $data, string $languageCode = null): bool {
    // not supported
  }

  public function read() {
    $event = new CalendarEvent();
    $location = new Location();

    $location
      ->setName($this->eventLocation);

    $event
      ->setStart($this->eventStart)
      ->setEnd($this->eventEnd)
      ->setAllDay($this->wholeDay)
      ->setSummary($this->eventName)
      ->addLocation($location);

    $calendar = new Calendar();
    $calendar
      ->setProdId('s1syphos')
      ->setTimezone($this->timezone)
      ->addEvent($event);
    $calendarExport = new CalendarExport(new CalendarStream, new Formatter());
    $calendarExport->addCalendar($calendar);

    return $calendarExport->getStream();
  }
}

class EventPage extends Page {
  public function files() {
    $files = parent::files();

    $virtualFile = new ICSFile($this);
    $files->add($virtualFile);
    return $files;
  }
}

It uses this GitHub - jasvrcek/ICS: Object-oriented php library for creating .ics iCal files to format the ICS file - you probably have your own solution, but I guess you’ll get the idea