In October 2025, the SuluEventBundle was an event management system featuring a recycle bin, time control and Smart Content (see the previous post). Something was missing that visitors could understand straight away: a calendar. I started work on it on 30 October; nine days later, on 7 November, it was up and running, localised and featuring multiple calendars on a single page.

Before that, I’d had a clear-out in October. The ‘active’ status of an event was replaced by a publication status with a specific date and time (11 October), and the admin search has also been able to find drafts since 13 October. On 16 October, I also integrated the SuluSharedTools bundle, which was to cause the bundle a bit of a detour a few weeks later (more on that below).

One commit, many features

The first calendar commit, dated 30 October, comprises 31 files and just over 2,000 lines. It contains more than just a calendar; it includes everything needed to make the calendar on the website useful:

  • an API that returns events for a specified time period
  • the front-end based on FullCalendar
  • a content type that allows the calendar to be embedded on pages
  • recurring events
  • iCal export
  • RSS and Atom feeds
  • settings for sharing on social media per event
  • a limit on requests to the calendar API

The following days were spent putting the finishing touches to the project.

The calendar

The calendar displays the month, week and year, as well as a weekly and monthly list. You can configure which views visitors see and whether they are allowed to switch between them in the admin panel. There, you can also set the start of the week, week numbers, weekends, the number of events per day, the time, type and location in the popover, the default colour and the time range for the weekly view. In the annual view, you can specify how many months are displayed side by side.

An event is considered an all-day event if it starts at 00:00 and ends at 00:00, or if it has no end time at all. In this case, the calendar does not display a time. The calendar API accepts a maximum of 100 requests per hour per IP address; this value can be changed in the Symfony configuration. On 6 November, the ability to display multiple calendars on a single page was added.

As for the installation, I’ll be honest: it’s ‘not exactly straightforward’. FullCalendar is integrated into the project via npm, which requires adjustments to the Webpack configuration.

Monthly view. Clicking on an entry opens a pop-up showing the type, time, short description and location.

The calendar settings in the admin panel: start of the week, events per day, permitted views and time range for the weekly view.

Event types with colours

Every event has a type, and every type has a name and a colour. The calendar colours the entries accordingly, and the selection in the form displays the colour. The bundle comes with ten types. If you wish to define your own, you can do so in the project configuration. Custom types completely replace those provided by the bundle; they are not merged. I made this is by design.

Recurring events: calculate or save

An event can recur daily, weekly, monthly or annually, at fixed intervals and on specific days of the week. The end date can be set to ‘never’, ‘after a certain number of occurrences’ or ‘until a specific date’.

Technically, there are two ways to turn the rule into specific dates. In the first, occurrences are calculated when someone queries a time period, for example in the calendar. They only exist at the moment of the query. In the second, a console command creates actual entries, by default for the next 90 days. This is intended for a cron job. The saved entries are standard events. According to the documentation, this helps with performance and indexing.

Both methods coexist; the bundle does not commit to one over the other.

iCal and Feeds

Visitors can download individual events as .ics files or subscribe to the entire calendar, including via webcal://. RSS and Atom feeds are available for new events in each language. The URLs are simple: /events/calendar.de.ics for the subscription and /events/feed.de.atom for the feed.

When optimisation is applied in the wrong place

On 4 November, I optimised the bundle for performance. On 5 November, I reversed the change. The commit explains why: the speed was not affected by my code, but by a bug in SuluSharedTools.

This is the downside of a shared bundle that people often overlook: it saves on code, but a bug in it affects all bundles at once, and you tend to look for it in the wrong place at first. With Sulu 3, SuluSharedTools has been removed.

After that

Version 2.0.0 was released on 5 November. The Sulu 2 line subsequently received minor updates until 12 November, with version 2.0.6 following in April 2026. The transition to Sulu 3 began at the end of November. This is the subject of the next post.

Previously: Recycle Bin, Timing and Activities in the SuluEventBundle.

Repository: manuxi/SuluEventBundle on GitHub, with documentation at calendars, recurrences and feeds and iCal.