Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Icalendar Generator Laravel Package

spatie/icalendar-generator

Generate RFC 5545 iCalendar (.ics) feeds with a fluent PHP API. Create calendars and events (start/end times, summary, metadata) for use in Apple Calendar, Google Calendar, and other clients. Outputs valid iCalendar text ready to serve or download.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/icalendar-generator
    

    No additional configuration is required—just autoload the package.

  2. First Use Case: Generate a basic event and export it as an .ics file:

    use Spatie\IcalendarGenerator\Components\Event;
    use Spatie\IcalendarGenerator\Components\Calendar;
    
    $event = Event::create()
        ->summary('Team Meeting')
        ->description('Weekly sync with the team')
        ->startsAt(\Carbon\Carbon::now())
        ->endsAt(\Carbon\Carbon::now()->addHours(1))
        ->location('Zoom');
    
    $calendar = Calendar::create('Team Calendar', 'team@example.com')
        ->addEvent($event);
    
    return response($calendar->render(), 200, [
        'Content-Type' => 'text/calendar',
        'Content-Disposition' => 'attachment; filename="meeting.ics"',
    ]);
    
  3. Where to Look First:


Implementation Patterns

Core Workflows

  1. Event Creation: Chain methods for clarity:

    $event = Event::create()
        ->uid('unique-id-here') // Required for updates
        ->dtStamp(\Carbon\Carbon::now()) // Auto-generated if omitted
        ->organizer('user@example.com')
        ->attendees(['attendee1@example.com', 'attendee2@example.com'])
        ->addCustomProperty('X-MYAPP-COLOR', '#FF0000'); // Extensions
    
  2. Recurring Events: Use PeriodRule for recurrence:

    use Spatie\IcalendarGenerator\Components\PeriodRule;
    
    $recurrenceRule = PeriodRule::create()
        ->addFrequency('WEEKLY')
        ->addDayOfWeek('MO', 'WE', 'FR') // Monday, Wednesday, Friday
        ->until(\Carbon\Carbon::now()->addYear());
    
    $event->recursAccordingTo($recurrenceRule);
    
  3. Calendar Management:

    • Multiple Events:
      $calendar = Calendar::create('My Calendar', 'admin@example.com');
      $calendar->addEvent($event1)->addEvent($event2);
      
    • Timezones:
      $event->timezone(\Carbon\Carbon::now()->timezone);
      
  4. Exporting:

    • Inline Response (for web):
      return response($calendar->render(), 200, [
          'Content-Type' => 'text/calendar',
      ]);
      
    • File Download:
      return Storage::disk('public')->put('calendar.ics', $calendar->render());
      
    • Direct Download:
      return response()->streamDownload(
          fn() => print($calendar->render()),
          'meeting.ics'
      );
      
  5. Integration with Laravel:

    • API Endpoint:
      Route::get('/calendar', function () {
          $calendar = Calendar::create('API Calendar', 'api@example.com')
              ->addEvent(Event::create()->summary('API Event')->startsAt(now())->endsAt(now()->addHour()));
      
          return response($calendar->render(), 200, [
              'Content-Type' => 'text/calendar',
          ]);
      });
      
    • Job Queues:
      use Illuminate\Bus\Queueable;
      use Illuminate\Contracts\Queue\ShouldQueue;
      
      class GenerateCalendarJob implements ShouldQueue
      {
          use Queueable;
      
          public function handle()
          {
              $calendar = Calendar::create('Scheduled Calendar', 'jobs@example.com');
              // ... add events
              Storage::put('public/calendars/scheduled.ics', $calendar->render());
          }
      }
      
  6. Custom Properties: Extend iCalendar with vendor-specific fields:

    $event->addCustomProperty('X-MYAPP-CATEGORY', 'work')
          ->addCustomProperty('X-MYAPP-PRIORITY', 'high');
    

Gotchas and Tips

Pitfalls

  1. UID Uniqueness:

    • Issue: Duplicate UID values break recurrence updates in clients (e.g., Google Calendar).
    • Fix: Use a globally unique identifier (e.g., UUID or database auto-increment + timestamp):
      $event->uid('event-' . Str::uuid()->toString());
      
  2. Timezone Handling:

    • Issue: Incorrect timezones may cause events to appear at wrong times.
    • Fix: Always set a timezone explicitly:
      $event->timezone('America/New_York');
      
    • Tip: Use Carbon for consistency:
      $event->startsAt(\Carbon\Carbon::now()->timezone('UTC'));
      
  3. Recurrence Rules:

    • Issue: Complex rules (e.g., EXDATE, RDATE) may not render as expected.
    • Fix: Test in multiple clients (e.g., Google Calendar, Apple Calendar) and validate with icalendar.org.
    • Tip: Use the PeriodRule builder for common patterns:
      $rule = PeriodRule::create()
          ->addFrequency('MONTHLY')
          ->addDayOfMonth(15); // 15th of every month
      
  4. Character Encoding:

    • Issue: Special characters (e.g., é, ñ) may corrupt the .ics file.
    • Fix: Ensure UTF-8 encoding in responses:
      return response($calendar->render(), 200, [
          'Content-Type' => 'text/calendar; charset=utf-8',
      ]);
      
  5. Large Calendars:

    • Issue: Memory issues with thousands of events.
    • Fix: Stream the output or generate in chunks:
      $calendar = Calendar::create('Large Calendar', 'admin@example.com');
      foreach ($events as $event) {
          $calendar->addEvent($event);
      }
      return response()->streamDownload(
          fn() => print($calendar->render()),
          'large_calendar.ics'
      );
      
  6. Client-Specific Quirks:

    • Google Calendar: Ignores DTSTAMP if not set; may misinterpret RRULE with EXDATE.
    • Apple Calendar: Requires ORGANIZER for editable events.
    • Outlook: May not support all X-PROPERTIES; test thoroughly.

Debugging

  1. Validate Output: Use online validators like icalendar.org or tools like ical-buddy:

    composer require vcal/ical-buddy
    
    use Vcal\Ical\Parser;
    $parser = new Parser();
    $parser->parse($calendar->render());
    
  2. Log Raw Output:

    \Log::info('iCalendar Output:', ['raw' => $calendar->render()]);
    
  3. Check for Deprecations: Monitor GitHub Releases for breaking changes.

Extension Points

  1. Custom Components: Extend the package by creating your own component (e.g., Todo):

    namespace App\Icalendar;
    
    use Spatie\IcalendarGenerator\Components\Component;
    
    class Todo extends Component
    {
        public function summary(string $summary): self
        {
            $this->properties['SUMMARY'] = $summary;
            return $this;
        }
    
        // ... other methods
    }
    
  2. Property Extensions: Add vendor-specific properties dynamically:

    $event->addCustomProperty('X-MYAPP-TAGS', 'project:alpha,urgent');
    
  3. Event Modifiers: Create a trait to standardize event creation:

    trait StandardEvent
    {
        public function standardize(): Event
        {
            return $this->dtStamp(now())
                        ->timezone(config('app.timezone'))
                        ->organizer(auth()->user()->email);
        }
    }
    
  4. Middleware for API: Add a middleware to enforce iCalendar headers:

    namespace App\Http\Middleware;
    
    use Closure;
    
    class EnsureIcalendarHeaders
    {
        public function handle($request, Closure $next)
        {
            if ($request->wantsIcalendar()) {
                $response = $next($request);
                return $response->header('Content-Type', 'text/calendar');
            }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport