morgenruf.dev

Celebrations

Birthdays and work anniversaries, posted in a Slack channel on your company's working days.

Overview

Celebrations is a module. It reads birthdays and start dates from the member profile, and once a day it posts whoever is celebrating in a channel you choose, with a πŸŽ‰ from the bot so people pile on. It plans around your working week and your company's holiday list, so nothing is posted on a day nobody is around to see it.

It is off by default. A workspace admin turns it on.

Turning It On

  1. Open the Celebrations page

    In the dashboard, Celebrations is in the sidebar after Kudos. You can set everything up while the module is still off.

  2. Pick a channel and a timezone, then save

    Both are required. The other settings have defaults (see Settings).

  3. Invite the bot to that channel

    /invite @Morgenruf
    slack
  4. Turn on celebrations

    A workspace admin clicks Turn on celebrations. The button is enabled once a channel and a timezone are saved.

ℹ️

Once it is on, Morgenruf also sends one DM to each person with no dates on file, asking for them. See Asking for dates.

Letting HR run it

Celebrations can be delegated. A workspace admin gives someone the Celebrations grant from the Members page, and that person can look after it without being a workspace admin. The grant is offered once Celebrations is on, because Members lists grants for active features only.

Workspace admin Celebrations admin Member
Turn Celebrations on or offyesnono
Change settings, working days and holidaysyesyesno
See the next 30 days of celebrationsyesyesno
Ask for datesyesyesno
Read settings and holidaysyesyesyes
Edit other people's profiles, import datesyesnono

A Celebrations admin who sets it up sees a note to ask a workspace admin to turn it on.

Settings

Setting Default Notes
Channel none Required. Where the posts go. Invite @Morgenruf to it.
Timezone none Required. The clock your company celebrates on. Separate from any standup's timezone, because the people who run standups and the people who run celebrations are often different.
Post at 09:00 24-hour time in the Celebrations timezone.
Working days Monday to Friday Any set of days, at least one. For example Sunday to Thursday.
Celebrate birthdays on
Celebrate work anniversaries on
Holidays empty Your company's days off. See below.

The page also shows Coming up: every celebration in the next 30 days and the day each one will be posted. Only workspace admins and Celebrations admins see it, since it lists birthdays.

Holidays

Morgenruf does not ship a holiday calendar. Your company's own list is the only source. Add holidays one at a time (adding a date that is already listed renames it), remove them, or import a list:

date,name
2026-12-24,Christmas Eve
2026-12-25,Christmas Day
2026-12-26,Boxing Day
csv
  • One date,name per line. The date,name header is optional.
  • Dates are YYYY-MM-DD. Names are required, up to 80 characters.
  • The same date twice in one file makes the second line invalid.
  • Dates more than a year in the past are refused. At most 1,000 lines per import.
  • The import shows a preview first and saves nothing until you confirm.

Working days and holidays belong to the workspace, not to Celebrations alone, so later features can plan around the same calendar. For now they are edited from the Celebrations page. Holidays more than a year old are removed by a nightly job.

How Posting Works

Once a day, at the post time in the Celebrations timezone, and only on working days:

  1. Morgenruf collects everyone with a birthday or a work anniversary on that day, or on any day off between it and the next working day.
  2. It skips anyone who ticked Don't celebrate me publicly, anyone deactivated, and anyone who has left.
  3. It skips start dates less than a year ago, and start dates in the future.
  4. It posts one message per kind per day: all of that day's birthdays together, and all of its anniversaries together. Then it adds a πŸŽ‰ to each post.

29 February birthdays and start dates are celebrated on 28 February in years without one. Names are mentions, listed alphabetically by first name.

Weekends and holidays

A celebration that falls on a day off (outside the working days, or on a listed holiday) is posted on the last working day before it, as its own message. With Monday to Friday working days:

Celebration on Posted on Opens with
SaturdayFriday"Tomorrow is..."
SundayFriday"On Sunday it's..."
Monday, a listed holidayFriday"On Monday it's..."
25 December, with 24 to 26 December all listed as holidays on weekdays23 December"On 25 December it's..."

The exact rule for the opening words:

  • The next day is "Tomorrow is".
  • A day outside the working week, or a holiday straight after one (a long weekend's Monday), is named by weekday: "On Sunday it's", "On Monday it's".
  • Any other holiday is named by date: "On 25 December it's".
  • Anything seven or more days away is always named by date.

The second line of an early post is "Off for the weekend, so let's celebrate early.", or "It's a day off, so let's celebrate early." when the day is a listed holiday.

Catch-up and no double posts

The daily job fires at the post time and then once an hour for up to 8 more hours, always on the same day, so a server that was down at post time still posts that day. Each post is recorded in the database before it is sent, which makes every later firing a no-op: a restart, a later firing or a second pod never posts the same celebration twice.

If Slack refuses a post, the record is released and the next hourly firing tries again. A post Slack accepted is never sent a second time.

The πŸŽ‰ Reaction

After each post the bot adds a πŸŽ‰ so people pile on. That needs the reactions:write Slack scope. The scope is optional: without it the post still goes out, just without the reaction, and no workspace is forced to reinstall.

A workspace that installed Morgenruf before this scope existed does not have it. The Celebrations page says so ("Posts go out without the πŸŽ‰ reaction until Slack is re-authorised") and shows a Re-authorise Slack link to workspace admins. After re-authorising, posts get the reaction. A reaction that fails is logged and never costs the post.

Asking for Dates

Most people will not open their profile on their own, so Celebrations asks them with a DM:

M
Morgenruf9:00 AM
πŸ‘‹ Hi Priya! Your team celebrates birthdays and work anniversaries in #celebrations.

Add yours so nobody misses it. Only day and month are kept.

[ Add my dates ]   [ Skip me ]
  • Add my dates opens the profile form.
  • Skip me turns off public celebration for that person (any dates they have stay) and replaces the DM with "Got it. You will not be celebrated publicly. Change your mind any time with /morgenruf profile."

Only active people in the Slack directory with no birthday and no start date, who have not opted out, are asked. Bots are never asked. A DM that cannot be delivered is not retried.

The one-time DM

With Celebrations on, the daily job sends the DM once to everyone still missing dates, including people who join the workspace later. It goes out with the first daily run, so on a working day at the post time, 100 people per firing; the rest follow on the next hourly firings. Nobody gets this DM twice.

The Ask for dates button

Ask for dates is on the Celebrations page, and on the Members page while Celebrations is on. It shows how many people would be asked and the message they would get before sending anything. It DMs only people still missing dates, and reaches each person at most once every 30 days (the one-time DM counts). It needs a channel and a timezone saved first.

Joining the channel

When someone joins the celebrations channel and has no dates on file, they get the same DM, under the same 30 day limit, however often they leave and rejoin.

Message Examples

The text is fixed in this version and is not customisable. Posts never use pronouns, since the profile does not store them.

M
Morgenruf9:00 AM
πŸŽ‚ Today is @Priya's birthday!
Wishing you a lovely day, Priya. πŸ’›
M
Morgenruf9:00 AM
πŸŽ‚ Today is a birthday double: @Priya and @Tom!
Wishing you both a lovely day. πŸ’›
M
Morgenruf9:00 AM
πŸŽ‚ Today is the birthday of @Ana, @Priya and @Tom!
Happy birthday to all of you. πŸ’›
M
MorgenrufFri 9:00 AM
πŸŽ‚ Tomorrow is @Priya's birthday!
Off for the weekend, so let's celebrate early. 🎈
M
MorgenrufFri 9:00 AM
πŸŽ‚ On Monday it's @Priya's birthday!
It's a day off, so let's celebrate early. 🎈
M
Morgenruf9:00 AM
πŸŽ‰ Today is @Tom's 3-year work anniversary!
Thanks for three great years, Tom. πŸ™Œ
M
Morgenruf9:00 AM
πŸŽ‰ Today is @Tom's first work anniversary! πŸ₯³
One year already. Thanks for everything, Tom.
M
Morgenruf9:00 AM
πŸŽ‰ Today is a work anniversary double: @Priya (2 years) and @Tom (5 years)!
Thanks to you both for everything. πŸ™Œ

An early post for three or more birthdays ends "...so let's celebrate early. Happy birthday to all of you. 🎈". Three or more anniversaries read "the work anniversary of @Ana (1 year), @Priya (2 years) and @Tom (5 years)" and end "Thanks to all of you for everything. πŸ™Œ"