survos / ux-calendar-bundle
FullCalendar UX integration for Symfony with AssetMapper and Twig components
Package info
github.com/survos/ux-calendar-bundle
Type:symfony-bundle
pkg:composer/survos/ux-calendar-bundle
Fund package maintenance!
Requires
- php: ^8.5
- johngrogg/ics-parser: ^3.5
- survos/kit-bundle: ^2.5
- symfony/config: ^8.1
- symfony/dependency-injection: ^8.1
- symfony/http-kernel: ^8.1
- symfony/options-resolver: ^8.1
- symfony/stimulus-bundle: ^3
- symfony/ux-twig-component: ^3
- twig/twig: ^3.4|^4.0
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^13.0
- symfony/framework-bundle: ^8.1
- symfony/phpunit-bridge: ^8.1
- symfony/twig-bundle: ^8.1
- symfony/var-dumper: ^8.1
This package is auto-updated.
Last update: 2026-08-15 21:44:56 UTC
README
survos/ux-calendar-bundle is a small Symfony UX bundle for rendering FullCalendar with AssetMapper, Twig components, and Stimulus.
Where this fits
Three projects, three jobs — don't confuse them:
| Project | Role |
|---|---|
| survos/ux-calendar-bundle (this) | The rendering/aggregation library: FullCalendar v7 + AssetMapper + a normalized EventSourceInterface to merge iCal feeds. |
| ccal | The Community Calendar Aggregator app: orgs, feeds, moderation, user subscriptions, event flags. Consumes this bundle. |
demo/ (in this repo) |
A minimal smoke-test of the bundle. Not the app — that's ccal. |
Deprecated/archived predecessors that blurred these lines:
survos/rappcal,tacman/CalendarBundle(tattali fork),survos-sites/calendar-demo.
Current scope
- AssetMapper-aware bundle setup
- Twig component for rendering a calendar shell
- Stimulus controller wired to FullCalendar
- Support for passing a JSON feed URL and an optional iCal URL as component input
- Backend contracts for normalized calendar events and event sources
- iCal import via
johngrogg/ics-parser
Example
<twig:full_calendar url="/fc-load-events" icsUrl="https://www.calendarlabs.com/ical-calendar/ics/76/US_Holidays.ics" initialView="dayGridMonth" />
Installing the FullCalendar assets (required)
FullCalendar is deliberately not declared in this bundle's symfony.importmap. Only
@hotwired/stimulus is, because that's the one dependency AssetMapper can resolve safely.
AssetMapper's remote-package provider downloads jsDelivr's /+esm auto-bundled builds, and that
transform mangles FullCalendar's preact class components — you get
Class constructor component cannot be invoked without 'new' at runtime
(fullcalendar#7474). Listing
fullcalendar here would mean every composer require of this bundle silently installs a broken
calendar.
Instead, consumer apps supply the raw published ESM files via a second <script type="importmap">
in their base template, before {{ importmap('app') }}. The browser merges multiple importmaps.
Copy this block (see demo/templates/base.html.twig for the working reference):
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@7.0.0-rc.3/skeleton.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@7.0.0-rc.3/themes/classic/theme.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@7.0.0-rc.3/themes/classic/palette.css"> <script type="importmap"> { "imports": { "preact": "https://cdn.jsdelivr.net/npm/preact@10.29.1/dist/preact.mjs", "preact/hooks": "https://cdn.jsdelivr.net/npm/preact@10.19.5/hooks/dist/hooks.mjs", "preact/jsx-runtime": "https://cdn.jsdelivr.net/npm/preact@10.19.5/jsx-runtime/dist/jsxRuntime.mjs", "preact/compat": "https://cdn.jsdelivr.net/npm/preact@10.19.5/compat/dist/compat.mjs", "preact/compat/client": "https://cdn.jsdelivr.net/npm/preact@10.19.5/compat/client.mjs", "temporal-polyfill/fns/zoneddatetime": "https://cdn.jsdelivr.net/npm/temporal-polyfill@0.3.2/fns/zoneddatetime.js", "temporal-polyfill/fns/plaindatetime": "https://cdn.jsdelivr.net/npm/temporal-polyfill@0.3.2/fns/plaindatetime.js", "temporal-polyfill/fns/instant": "https://cdn.jsdelivr.net/npm/temporal-polyfill@0.3.2/fns/instant.js", "@full-ui/headless-calendar": "https://cdn.jsdelivr.net/npm/@full-ui/headless-calendar@7.0.0-rc.3/index.js", "fullcalendar": "https://cdn.jsdelivr.net/npm/fullcalendar@7.0.0-rc.3/index.js", "fullcalendar/themes/classic": "https://cdn.jsdelivr.net/npm/fullcalendar@7.0.0-rc.3/themes/classic.js", "fullcalendar/daygrid": "https://cdn.jsdelivr.net/npm/fullcalendar@7.0.0-rc.3/daygrid.js", "fullcalendar/timegrid": "https://cdn.jsdelivr.net/npm/fullcalendar@7.0.0-rc.3/timegrid.js", "fullcalendar/list": "https://cdn.jsdelivr.net/npm/fullcalendar@7.0.0-rc.3/list.js" } } </script>
Hand-writing this per app is the known wart — survos/mono#5 tracks moving it behind a Twig helper shipped by this bundle.
iCal
This bundle now includes the first step toward first-class iCal parsing via an EventSourceInterface contract plus an IcsEventSource adapter backed by johngrogg/ics-parser.
The intended architecture is:
EventSourceInterfacefor calendar providers- an event DTO normalized for FullCalendar and iCal export/import
- one or more iCal adapters/parsers
- optional export mapping, likely using
spatie/icalendar-generator - optional entity mapping via attributes and
CalendarEntityInterface
That is the cleaner path if you want JSON feeds, iCal ingestion, and later iCal export to coexist without baking transport details into the Stimulus controller.
Finding calendars
You can find public iCal calendars to test against at Calendar Labs.