i have successfully rebuild my Discourse instance🥲
Discourse’s official discourse-calendar plugin already supports .ics export, which is extremely useful for sharing Discourse events externally. However, many communities — particularly in education, government, or enterprise — rely on external iCal feeds to publish event information (e.g. from Moodle, Office365, Google Calendar, or institutional CMS platforms).
At present, there is no built-in way to import or sync from .ics sources. This limits Discourse’s use as a true calendar hub for communities that already publish important schedules elsewhere.
Feature Proposal
Add iCal feed sync (import from .ics URLs) to the Discourse Calendar plugin.
Core Features
Configure an .ics feed URL for a calendar-enabled category or topic.
Automatically import events into the calendar, matching the .ics feed.
Specify a sync interval (e.g. hourly, daily) or allow a manual “Sync now” button.
Use the event UID field to prevent duplicates and update modified events cleanly.
Optional Configs
Tag or label imported events to show their external source.
Choose between:
One-way sync (external → Discourse only),
or two-way sync (editing synced events inside Discourse pushes changes back — future scope).
Support multiple .ics feeds per calendar, merged into one view.
Visual indication that an event is externally synced (e.g. “Synced from: outlook.university.edu”).
Use Cases
Sector
Example Use Case
Education
Auto-populate student forums with term dates, course schedules, exams, etc.
Government
Sync official events from CMS or intranet to a public-facing community calendar
Companies
Mirror internal meeting calendars (from Outlook or Google Calendar)
Events forums
Integrate speaker lists or session schedules from external providers
Security and Privacy
Calendar feeds could support public or tokenized access (e.g. URL containing secret token).
Support for OAuth2 / Basic Auth could be a future enhancement.
Similar need discussed in older threads, e.g. here
Compatibility
This feature would not require discourse-events (now deprecated), and would work natively with the existing Discourse Calendar syntax ([calendar] and [event]). Users would still be able to create native Discourse events manually — iCal sync would just augment these calendars.
Would love to hear if this feature is already on the roadmap — or if others in the community would find it valuable.
@Ethsim2 This would be a huge feature, and I’ve been digging into how feasible it is now that Discourse is switching to FullCalendar.
@sam linked directly to fullcalendar.io recently, and it turns out FullCalendar now has first-class support for .ics feeds via their official plugin system — so the heavy lifting is already done by the library.
Proposal: Enable .ics Feed Sync Using FullCalendar’s Native Support
With the upcoming FullCalendar v6 integration into Discourse, the groundwork is in place to support this feature natively.
FullCalendar’s @fullcalendar/icalendar plugin (with ical.js under the hood) allows you to load public .ics feeds like so:
That’s all it takes to render a remote iCal feed into the calendar UI — no custom parsing, just plug-and-play.
Suggested Implementation Steps for Discourse
Add @fullcalendar/icalendar and ical.js to the plugin (once FullCalendar v6 is fully landed).
Add an admin/plugin setting (or per-category option) for inputting one or more .ics URLs.
On the client side, render the feed into the calendar view.
(Optional) Implement server-side syncing that:
Periodically fetches the feed
Parses new/updated events
Creates or updates associated Discourse topics
Sync Frequency
It’s important to note that FullCalendar’s default .ics handling only fetches the feed on initial calendar load in the browser. That means:
There’s no daily or automatic refresh.
Users will see a stale copy unless they reload or manually trigger a refresh.
There is no persistence — if a user navigates away, the feed data is gone.
To make this truly useful, Discourse would ideally:
Run a daily (or scheduled) Sidekiq job that fetches the feed server-side.
Cache the parsed events for consistent rendering across users.
Optionally link events to topics or create new ones for full integration.
This would allow proper sync behavior and revive a key feature previously handled by Angus’s plugin — but using a clean and maintainable foundation.
Benefits
Seamlessly integrates .ics feeds from Google Calendar, Outlook, iCal, etc.
Makes Discourse a calendar consumer, not just an exporter.
Great for community forums, student groups, civic events, etc.
Built entirely on supported FullCalendar features — minimal custom JS needed.
Would love to see this land now that the calendar plugin is getting attention again. Happy to help test it or contribute to a proof-of-concept.
Sorry @Halden42 but I’m a bit confused about your post.
I understand that Discourse is “fixing the foundations” of the calendar system with the FullCalendar upgrade, but I’m worried about how much time it would take me to manually populate a busy calendar. I use the Discourse GUI every day for everything, and having to duplicate content outside the interface is a non-starter.
I noticed you mentioned a feature I really miss from Angus’s plugin, which I think captures the main point of syncing events into Discourse:
This part would be essential for my use case.
But I’m concerned because you didn’t go into any detail about how that could be implemented. Could you explain what that would look like in practice? Would Discourse create one topic per event? Would it support updates or deletions if the source calendar changes?
That’s the part I’d need to rely on most, and I’m just not sure yet how close we are to it.
Thanks @Ethsim2 — that’s a great follow-up, and I think your concern is exactly the right one: it’s not just about displaying events from an .ics feed, it’s about embedding them into Discourse in a useful, trackable way.
When I said “link events to topics or create new ones,” I was imagining a setup similar to how Angus’s plugin used to work — where each event in the feed would correspond to a topic on Discourse, and updates to the feed would be reflected in the topic over time.
Right now, FullCalendar on its own doesn’t persist events — it just renders them from the feed on page load. So if an event disappears from the feed (i.e. it’s been cancelled or deleted externally), it just quietly vanishes from the calendar UI.
But that’s not good enough for most forum-based workflows, especially where event posts are used for discussion, RSVPs, or announcements.
Here’s what I’d propose for that:
Instead of removing the topic when an event disappears from the feed, Discourse could:
Keep the topic in place
Add a line at the top like: ⚠️ This event has been cancelled or removed from the source calendar.
Optionally lock or unlist the topic, depending on admin preference
This would preserve context, allow replies, and make the cancellation visible — without deleting anything. Technically, this is pretty doable: we’d just flag that the UID no longer exists in the .ics file and update the matching topic’s status.
So yes — while FullCalendar itself doesn’t manage that status, Discourse could handle it on the sync layer. The job that fetches the feed (e.g. via Sidekiq) would keep track of which events used to exist and no longer do, and mark the corresponding topic accordingly.
If enough people are interested in this, I think we could build out a proper spec. It wouldn’t be hard to prototype.
Thanks for the thoughtful reply @Halden42 — this clears up a lot.
What you described here…
…is exactly the core use case I’ve been trying to recover since moving off Angus’s plugin. For me, the most critical part is not just rendering events visually, but syncing a live external calendar into the forum, where each event has a topic, and changes to that event (e.g. cancellation, reschedule) are reflected in that topic over time.
I’d be happy with a one-way sync model to start—read-only from .ics to Discourse—and even just basic update detection would cover 90% of my use cases. A “cancelled” status showing in the event topic if it’s removed from the feed would be ideal too, rather than deleting the topic outright.
If there’s a preferred place to propose a spec for this—perhaps once the FullCalendar upgrade stabilises—I’d be very interested in contributing or testing.
Thanks @ethsim2 — this would be incredibly helpful for our council’s use of Discourse.
We maintain multiple Office 365 calendars — each with its own .ics feed — for different kinds of meetings: Executive Committee, Public Engagement Sessions, Internal Working Groups, and so on. These feeds are already well-structured and regularly maintained by clerks and admin teams.
What we urgently need is a way to:
Subscribe to different .ics feeds per category (e.g. one feed per meeting type)
Automatically create a new topic in the corresponding Discourse category
Validate that the topic ends up in the correct category, similar to how Angus’s plugin let us filter by tags or other metadata
Reflect changes (time, title) in the topic if the calendar event updates
Optionally flag or close the topic if the event is cancelled or removed from the feed
For councils like ours, categories are used to manage granular visibility — some meetings are private (e.g. executive or planning), others are public. A misfiled topic could result in sensitive data being exposed, so category-level validation is a must-have.
We’d love to see something like this supported officially in the upcoming FullCalendar overhaul. It would significantly reduce manual work and make Discourse far more viable as a single source of truth for meeting coordination and transparency.
I’m a pharmacy student in the U.S., and our university provides all our rotation schedules, exams, and practicals through a calendar portal. The feed URLs don’t end in .ics, but when I open them in Chrome, they immediately download a valid .ics file. So they’re definitely standard iCal feeds — just with a different URL structure.
Up until recently, I was using Angus’s plugin, and it handled these feeds perfectly. Each event would generate a topic, and I could route different feeds into different categories (e.g. “Therapeutics,” “Rotations,” “Exams”), which helped our study group stay organized.
But since the recent this.router error broke the plugin, I’ve had to disable it — like Ethsim2 — and now there’s no easy way to keep our calendar in sync.
If the official plugin could support:
Inbound .ics feeds (even if the URL doesn’t end in .ics)
Topic creation with category targeting
Feed-specific configuration (e.g. one feed → one category)
Update detection and optional event cancellation handling
…that would make Discourse a powerful tool for academic collaboration. It was working perfectly for us before the plugin broke — so I’d love to see this functionality land natively.
Happy to share a sample calendar URL privately if that helps with testing.