Discourse Calendar


Official calendar plugin for Discourse.

:link: GitHub: https://github.com/discourse/discourse-calendar

:arrow_right: Install: Follow the plugin installation guide.

The Discourse calendar plugin allows you to create a dynamic calendar in the first post of a topic. You can add new calendar items by posting a reply with a date using “Insert Date” modal.


To embed the calendar, add the following BBCode (note the separate lines) in the first post of a topic:


Optionally you can hide weekends and other days with special attributes. Hidden days are 0 to 6 for Sunday to Saturday respectively. As currently implemented, Monday is the first day of every week, regardless of the viewer’s locale settings and this is not currently configurable.

You can also set the default view to:

  • Month (month)
  • Week (basicWeek), which shows days in columns
  • List (listNextYear) which lists all entries in the next year.

In addition, you can ignore timezones by setting fullDay attribute.

For example:

[calendar weekends="false" hiddenDays="1,2" defaultView="listNextYear" fullDay="true"]

To add events to the calendar, use the Insert Date function from the composer options menu to insert a single date or date range (or two dates) in any reply to the topic. For example,

[date=2018-12-20 timezone="America/Boise"] → [date=2018-12-21 timezone="America/Boise"]

Any text above this line will describe the calendar entry. For example:

It's my birthday!
[date=2018-12-20 timezone="America/Boise"] → [date=2018-12-21 timezone="America/Boise"]

You can also create repeating events by using the Recurrence feature in the date-entry widget. For example:

I could never get the hang of Thursdays.
[date=2021-12-16 time=09:00:00 timezone="America/New_York" recurring="1.weeks"]

The tool won’t let you create recurring events with a duration, and it seems to ignore the actual date when you do this. But you can have something happen every Thursday.

Note that the calendar itself always is in UTC, so events that are a 24-hour single day in your timezone may appear to span multiple days. The plugin settings all day event start time and all day event end time can be used to reduce the impact of this if your users happen to be in a timezone where that works out to be convenient. (It is unclear what timezone these settings use.)

Once the reply is submitted, the date range should be added to the calendar in the top post in the topic, and displayed after a reload of the topic.

Once the event is over the post containing the dates can be automatically deleted, based on the delete expired event posts after plugin configuration option. You can also use the topic timer to auto-delete replies.

Holiday Calendar

There is an optional, special “holiday calendar”, primarily intended to help manage site staff holidays.

This is controlled by the setting holiday calendar topic id. By setting holiday_calendar_topic_id to the ID of a topic which has a calendar in the top post, that calendar becomes special — instead of regular calendar entries, any replies will be taken as “vacation time” for that user. These entries will be automatically (and randomly) colored. (It is not possible to control the colors, nor to get colored entries in the normal type of calendar.)

Additionally, the emoji :desert_island: will appear next to the names of people on vacation in their user cards, and a calendar icon next to their name when @username mentioned in a post.

Note that while any user with access to post in the topic can add an entry, these indicators are only visible to moderators and admins; this is not currently configurable.

The calendar will also by default include an entry for every user for every holiday in that user’s locale, if they’ve set one. This can be quite overwhelming. Adding

.calendar .grouped-event {
  display: none;

to a theme component and adding that to all themes will hide this as a temporary workaround.


The plugin has an “Event” feature, but consider it in alpha state. This works entirely differently, and creates a site-wide calendar from entries across multiple topics, rather than per-topic calendars. For more information on this see 🗓 Discourse Event.

This should not be confused with the Events plugin (note plural), which is entirely different.


Dynamic Events Calendar

Holiday Calendar

Holiday Flair


Holiday Mention Icon







Good day.
Thank you very much for the plugin. I have 2 questions.

  1. The starting day in the calendar is Sunday. How do I change it?
  2. How do I change the language of the calendar? I can’t see any setting for it.

Thank you very much.

1 Like

Hello and welcome! :wave: The answer to both of these questions, I think, is to edit your interface user preferences. By default this is English (US) but you can choose your language which will also change some locale behaviors for you, such as when the week starts and how dates are displayed.

1 Like

Hello Tobias,
we disabled the function and already set the interface to German.
We then enabled the setting so that every user can change his/her own interface language, I chose German, but it still didn’t change anything.
Any new ideas?

1 Like

Huh. On my site, days always start on Monday, even though my interface language is “English (US).”

I’d love for it to follow the user’s locale!

1 Like

There’s also another thing I saw. When I compare my screenshot to Anton’s, he has buttons in the upper right corner, changing his layout to “month/week/list”. That’s also missing from my view.

1 Like

:face_with_raised_eyebrow: :thinking: :grinning_face_with_smiling_eyes: nope, not yet at least ! but that would be great, and indeed fullcalendar is localised. I managed to hack something with my limited coding skill:
the idea is to add 4 buttonText for the calendar in the initializer

    return new window.FullCalendar.Calendar($calendar[0], {
      locale: I18n.locale,
      buttonText: {
        today: I18n.t("discourse_calendar.buttontext_today"),
        month: I18n.t("discourse_calendar.buttontext_month"),
        basicWeek: I18n.t("discourse_calendar.buttontext_basicweek"),
        listNextYear: I18n.t("discourse_calendar.buttontext_listnextyear")

and in the locale client file

      buttontext_today: "Today"
      buttontext_month: "Month"
      buttontext_basicweek: "Week"
      buttontext_listnextyear: "List"

and add the https://cdn.jsdelivr.net/npm/fullcalendar@4.0.0-alpha.3/dist/locales-all.js to the loaded public/javascipts

1 Like

the calendars displayed from a [calendar][/calendar] and upcoming events are indeed not built the same way


Ahhh, I see.

These things are so different I really feel like they should be split back out into separate plugins.


out of my depth I’m afraid, they do share fullcalendar… ¯\_ (ツ)_/¯
but with the last commit FEATURE: fullDay calendar option (#207) · discourse/discourse-calendar@e852072 · GitHub as example, I think I might try to add a color parameter :grin:

1 Like

Ok now I understand the idea.
So the [calendar] tag adds a calendar in the first post.
The [event] tag adds an event in a global calendar. This global calendar is opened with the menu and you can add multiple events to that calendar.
The [calendar] is seperate for every new post. So I just created 2 new posts with different event dates, but the 2 separate calendars don’t show the event of the other.
I gotta say though the [event] function is way more useful to me at least, since it’s a global calendar which I can open with a button from the menu which shows all the events.
Thanks for clearing that up!


It might also be useful to note that a calendar in the first post of a topic displays up to two dates per post (a start and an end) as an “event”, for all the posts of its topic.


As someone told me: go ahead, it’s a wiki :slight_smile:


…a new badge :blush:
Cat Bear GIF


@kris.kotlarek I don’t think your recent edit is right. Specifically, it was my impression that setting fullDay to true does not ignore timezones, but will in fact create what seem to be two day events if all day event start time or all day event end time in UTC overlap midnight in the local time zone.

Can you confirm?


One of the reasons to introduce fullDay option was to make holidays easier to understand.

Let’s say we have two users, one in Australia and one in Poland (10 hours difference). User in Poland would create a record in the calendar, full day off 2022-01-10 00:00:01 - 2022-01-10 23:59:59.

Without fullDay option, user from Australia would see that as 2022-01-09 14:00:01 - 2022-01-10 13:59:59 . In calendar, it would be displayed as two days, when actually it is just one.

So fullDay=true will simplify display. User from Australia will exactly see one day marked on calendar - 2022-01-10.

That’s why I wrote that it is ignoring timezones. A user from Poland marks 2022-01-10 as day of, and all users in different timezones will see it as 2022-01-10 (not as 2 days).

Does it make sense?


Ah, I see. Yes, that makes sense.

Thinking about this a bit more — it feels a little awkward for the calendar to work this way. It seems like it would be better for this to be the default for all events which specify a day but not a time, but for events with actual times to stay to their “true” time.