Every Monday, emails anyone starting in the next week and tells the team in Slack who is joining.

UsesGmailGoogle SheetsSlack

Welcome next week's new starters

Every Monday at 07:00, your new starter roster is read, anyone whose start date falls within the next seven days gets a short welcome email, and your team channel in Slack is told who is joining, in what role and on which day, so nobody arrives to a room that was not expecting them.

The welcome email is written from the roster, not by AI: it greets the person by first name and gives their role and start date, so there is nothing to review and nothing to get confidently wrong. Lodol remembers who it has welcomed, so nobody is emailed or announced twice, even if you run it again by hand, and anyone further out is picked up on a later Monday. A hire with no email address is still announced to the team. If a start date can't be read, a column is missing or a message fails to send, the run is marked as failed and names the people affected, instead of looking like a quiet week.

You need Google Sheets, Gmail and Slack connected, the link to your roster, and the ID of the Slack channel for the announcements. The roster tab needs 'Name', 'Role', 'Email' and 'Start date' columns.

ScheduleRun every Monday at 07:00.Run every Monday at 07:00.
ValuesSet rosterUrl to blank.Set rosterUrl to blank.
ValuesSet slackChannelId to blank.Set slackChannelId to blank.
ValuesSet rosterTab to New hires.Set rosterTab to New hires.
ValuesSet daysAhead to 7.Set daysAhead to 7.
Google SheetsGoogle SheetsRead the rows of rosterUrl. Save it as roster.Read the rows of rosterUrl. Save it as roster.
Decisions & LoopsIf roster.headers is emptyIf roster.headers is empty
Yes
Decisions & LoopsStop and report a problem: The '@rosterTab' tab of your roster is empty. It needs a header row with Name, Role, Email and Start date, then one row per new starter.Stop and report a problem: The '@rosterTab' tab of your roster is empty. It needs a header row with Name, Role, Email and Start date, then one row per new starter.
No
No steps
ListsKeep each item in [Name, Role, Email, Start date] where roster.headers doesn't contain item and save it as missingColumns.Keep each item in [Name, Role, Email, Start date] where roster.headers doesn't contain item and save it as missingColumns.
Decisions & LoopsIf missingColumns isn't emptyIf missingColumns isn't empty
Yes
TextJoin missingColumns with , and save it as missingList.Join missingColumns with , and save it as missingList.
Decisions & LoopsStop and report a problem: The '@rosterTab' tab is missing these columns: missingList. Its header row needs Name, Role, Email and Start date, spelled exactly like that. Nobody was welcomed or announced.Stop and report a problem: The '@rosterTab' tab is missing these columns: missingList. Its header row needs Name, Role, Email and Start date, spelled exactly like that. Nobody was welcomed or announced.
No
No steps
Dates & TimesGet today's date and save it as todayDate.Get today's date and save it as todayDate.
Stored ValuesGet the stored value 'welcomed_new_starters'. Save it as welcomedStore.Get the stored value 'welcomed_new_starters'. Save it as welcomedStore.
ValuesSet done to an empty list.Set done to an empty list.
Decisions & LoopsIf welcomedStore.found is yesIf welcomedStore.found is yes
Yes
ValuesChange done to welcomedStore.value.Change done to welcomedStore.value.
No
No steps
ValuesSet welcomed to an empty list.Set welcomed to an empty list.
ValuesSet noEmail to an empty list.Set noEmail to an empty list.
ValuesSet unreadable to an empty list.Set unreadable to an empty list.
ValuesSet problems to an empty list.Set problems to an empty list.
ValuesSet notes to an empty list.Set notes to an empty list.
Decisions & LoopsFor each hire in roster.rows:For each hire in roster.rows:
Decisions & LoopsIf hire.Name is blank and hire["Start date"] is blankIf hire.Name is blank and hire["Start date"] is blank
Yes
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
ValuesSet daysUntil to 0.Set daysUntil to 0.
Decisions & LoopsIf a step below fails, save the error as dateErrorIf a step below fails, save the error as dateError
Try
Dates & TimesCount the days from todayDate to hire["Start date"] and save it as daysUntil.Count the days from todayDate to hire["Start date"] and save it as daysUntil.
On error
ListsAdd hire.Name (row hire.row_number) to the end of unreadable and save it as unreadable.Add hire.Name (row hire.row_number) to the end of unreadable and save it as unreadable.
Decisions & LoopsSkip to the next item.Skip to the next item.
Decisions & LoopsIf daysUntil is greater than or equal to 0 and daysUntil is less than or equal toโ€ฆIf daysUntil is greater than or equal to 0 and daysUntil is less than or equal toโ€ฆ
Yes
TextTrim hire.Name and save it as hireName.Trim hire.Name and save it as hireName.
Decisions & LoopsIf hireName is blankIf hireName is blank
Yes
ListsAdd a starter with no name (row hire.row_number) to the end of unreadable and save it as unreadable.Add a starter with no name (row hire.row_number) to the end of unreadable and save it as unreadable.
Decisions & LoopsSkip to the next item.Skip to the next item.
No
No steps
TextSplit hireName by a space and save it as nameParts.Split hireName by a space and save it as nameParts.
Dates & TimesMake hire["Start date"] readable as โ€œMonday, November 2โ€ and save it as startDay.Make hire["Start date"] readable as โ€œMonday, November 2โ€ and save it as startDay.
Dates & TimesMake hire["Start date"] readable as โ€œ2026-11-02โ€ and save it as startKey.Make hire["Start date"] readable as โ€œ2026-11-02โ€ and save it as startKey.
TextBuild the text @startKey email @hireName and save it as emailKey.Build the text @startKey email @hireName and save it as emailKey.
TextBuild the text @startKey team @hireName and save it as teamKey.Build the text @startKey team @hireName and save it as teamKey.
TextTrim hire.Email and save it as hireEmail.Trim hire.Email and save it as hireEmail.
Decisions & LoopsIf hireEmail is blank and done doesn't contain teamKeyIf hireEmail is blank and done doesn't contain teamKey
Yes
ListsAdd hireName to the end of noEmail and save it as noEmail.Add hireName to the end of noEmail and save it as noEmail.
Else if @hireEmail isn't blank and @done doesn't contain @eโ€ฆ
Decisions & LoopsIf a step below fails, save the error as emailErrorIf a step below fails, save the error as emailError
Try
GmailGmailSend an email to hireEmail.Send an email to hireEmail. Subject: Welcome aboard, nameParts[0]Hi nameParts[0], We are looking forward to your first day on startDay. You are joining us as hire.Role. Someone will be in touch before then with your kit and your first-day details. If anything is unclear in the meantime, just reply to this message. See you soon.
ListsAdd emailKey to the end of done and save it as done.Add emailKey to the end of done and save it as done.
On error
ListsAdd The welcome email to hireName did not send (emailError.message). to the end of problems and save it as problems.Add The welcome email to hireName did not send (emailError.message). to the end of problems and save it as problems.
Otherwise
No steps
Decisions & LoopsIf done doesn't contain teamKeyIf done doesn't contain teamKey
Yes
Decisions & LoopsIf a step below fails, save the error as slackErrorIf a step below fails, save the error as slackError
Try
SlackSlackSend a message to slackChannelId.Send a message to slackChannelId.*Starting soon:* hireName joins as hire.Role on startDay - say hello when they arrive.
ListsAdd teamKey to the end of done and save it as done.Add teamKey to the end of done and save it as done.
ListsAdd hireName (startDay) to the end of welcomed and save it as welcomed.Add hireName (startDay) to the end of welcomed and save it as welcomed.
On error
ListsAdd hireName was not announced in Slack (slackError.message). to the end of problems and save it as problems.Add hireName was not announced in Slack (slackError.message). to the end of problems and save it as problems.
No
No steps
No
No steps
ListsKeep each item in done where the text before in item is greater than or equal to todayDate and save it as done.Keep each item in done where the text before in item is greater than or equal to todayDate and save it as done.
Decisions & LoopsIf a step below fails, save the error as saveErrorIf a step below fails, save the error as saveError
Try
Stored ValuesSet the stored value 'welcomed_new_starters' to done.Set the stored value 'welcomed_new_starters' to done.
On error
ListsAdd Lodol could not note who was welcomed (saveError.message), so running this again before their first day would welcome them a second time. to the end of problems and save it as problems.Add Lodol could not note who was welcomed (saveError.message), so running this again before their first day would welcome them a second time. to the end of problems and save it as problems.
Decisions & LoopsIf welcomed isn't emptyIf welcomed isn't empty
Yes
TextJoin welcomed with , and save it as welcomedList.Join welcomed with , and save it as welcomedList.
ListsAdd Announced to the team: welcomedList. to the end of notes and save it as notes.Add Announced to the team: welcomedList. to the end of notes and save it as notes.
No
No steps
Decisions & LoopsIf noEmail isn't emptyIf noEmail isn't empty
Yes
TextJoin noEmail with , and save it as noEmailList.Join noEmail with , and save it as noEmailList.
ListsAdd No email address on the roster for noEmailList, so they were announced but not emailed. to the end of notes and save it as notes.Add No email address on the roster for noEmailList, so they were announced but not emailed. to the end of notes and save it as notes.
No
No steps
Decisions & LoopsIf unreadable isn't emptyIf unreadable isn't empty
Yes
TextJoin unreadable with , and save it as unreadableList.Join unreadable with , and save it as unreadableList.
ListsAdd Could not read the start date for unreadableList. Write it as a date such as 2026-11-02; until then they are not welcomed or announced. to the end of problems and save it as problems.Add Could not read the start date for unreadableList. Write it as a date such as 2026-11-02; until then they are not welcomed or announced. to the end of problems and save it as problems.
No
No steps
TextJoin notes with a space and save it as noteText.Join notes with a space and save it as noteText.
Decisions & LoopsIf problems isn't emptyIf problems isn't empty
Yes
TextJoin problems with a space and save it as problemList.Join problems with a space and save it as problemList.
Decisions & LoopsStop and report a problem: problemList noteText.Stop and report a problem: problemList noteText.
No
No steps
Decisions & LoopsIf notes is emptyIf notes is empty
Yes
Decisions & LoopsFinish the run: Nobody new to welcome: no one on the roster starts in the next week who has not been welcomed already.Finish the run: Nobody new to welcome: no one on the roster starts in the next week who has not been welcomed already.
No
No steps
Decisions & LoopsFinish the run: noteText.Finish the run: noteText.