* Add weekly recurring scheduled posts. Extend scheduled posts so users can schedule weekly repeats and keep the series healthy across sends, reschedules, and UI updates instead of falling back to one-shot behavior. Made-with: Cursor * Add Playwright coverage for recurring scheduled posts. Cover weekly recurring scheduled messages in the scheduled-messages spec so the recurring UI and reschedule flow stay protected without adding a separate test surface. Made-with: Cursor * Fix recurring scheduled post CI failures. Resolve the initial lint and formatting issues and renumber the new scheduled-post migration so it no longer collides with master during Postgres-backed test setup. Made-with: Cursor * Sync recurring scheduled post translation files. Regenerate the affected English translation catalogs so the recurring scheduled post strings match the source extraction order expected by CI. Made-with: Cursor * Fix recurring scheduled post review follow-ups. Preserve overdue cleanup behavior during weekly catch-up, defer delete websocket events until deletion succeeds, and address the remaining migration and UI review nits. Made-with: Cursor * Address recurring scheduled post review feedback Made-with: Cursor * Fix recurring scheduled post CI checks Made-with: Cursor * Make pending scheduled post keyset cursor index-scannable EXPLAIN ANALYZE on a 5M-row ScheduledPosts table showed the pure OR-form cursor forced Postgres to scan idx_scheduledposts_pending_scheduled_at_id from the top on every page (~383ms/page, ~2M rows filtered). Keeping the ScheduledAt <= beforeTime bound outside the tie-break restores the index boundary (~0.12ms/page). Adds storetest coverage for cursor pagination. Co-authored-by: nick.misasi <[email protected]> * Address code quality review findings for recurring scheduled posts Server: - Replace silent-fallback AdvanceWeeklyScheduledNextOccurrence with error-returning ScheduledPost.ComputeNextScheduledAt; a recurring post whose timezone fails to load is now routed through the failed-post path instead of being reposted every job run or silently deleted - Add ScheduledPost.IsRecurring and partition batches in processScheduledPostBatch; advance/delete now run independently so a store failure in one path can't cause reposts in the other - Drop dead generality in UpdateRecurringScheduledPosts (only ScheduledAt varies per row; ErrorCode/ProcessedAt are constants) - Simplify redundant repeat-type condition in GetPendingScheduledPosts Webapp: - Add shared isRecurringScheduledPost helper, replacing six scattered repeat_type === 'weekly' literals - Recurrence timezone is now simply the scheduler's current timezone; removes initialRepeatTimezone/effectiveTimezone plumbing and the modal-label/picker timezone mismatch - Single enforcement point for hiding send-now on recurring posts - Use canonical getTeamIdByChannelId at both SCHEDULED_POST_UPDATED dispatch sites; rewrite errorsByTeamId update case as remove-then-add and add reducer tests Co-authored-by: nick.misasi <[email protected]> * Simplify recurring scheduled post code per review - End a recurring series when its channel no longer exists instead of advancing it forever (matches the one-shot channel-not-found handling) - Collapse the errorsByTeamId SCHEDULED_POST_UPDATED case into the identical SINGLE_SCHEDULED_POST_RECEIVED case (a scheduled post's team can't change) and combine duplicate byId cases; preserves state references on no-op updates - Drop no-op timezone conversions in ComputeNextScheduledAt - Remove redundant checkbox aria-label (label htmlFor already names it) - Schedule new job tests in the past instead of sleeping a real second - Remove redundant test assignment and e2e positional boolean Co-authored-by: nick.misasi <[email protected]> * Remove slop from recurring scheduled post changes - Drop the business-rule CHECK constraint from the recurrence migration; no other migration enforces model-layer validation in the database, and BaseIsValid plus the job's failure handling already own it - Fold the standalone repeat-validation test file into the existing TestScheduledPostBaseIsValid, matching its conventions - Revert unrelated benchmark modernization in utils_test.go - Drop an unneeded cast, unused fixture fields, and naming/assertion inconsistencies in tests Co-authored-by: nick.misasi <[email protected]> * Regenerate ScheduledPostStore mock with mockery ordering Co-authored-by: nick.misasi <[email protected]> * Address CodeRabbit review feedback - Reject the host-dependent 'Local' value for RepeatTimezone; recurring schedules need a fixed zone (UTC or IANA name) - Hide reschedule for deactivated DMs, matching send-now eligibility Co-authored-by: nick.misasi <[email protected]> * Resolve scheduled post team bucket from existing state when channel is unloaded An admin can reschedule before fetchMissingChannels resolves, in which case deriving the team from the channel returns undefined and the update was misfiled under directChannels. getScheduledPostTeamId falls back to the byTeamId bucket that already holds the post. Co-authored-by: nick.misasi <[email protected]> * Retrigger CI after transient enterprise npm network failure Co-authored-by: nick.misasi <[email protected]> * Clear hover/focus before asserting scheduled post header details in e2e The drafts panel hides its timestamp/tag info section while hovered or focus-within; after the reschedule modal closes, focus returns to the row and the 'Repeats weekly' tag assertion saw a hidden element. Co-authored-by: nick.misasi <[email protected]> * Move recurrence columns into baseColumns and dispatch ComputeNextScheduledAt on repeat type Co-authored-by: nick.misasi <[email protected]> * Preserve recurrence when scheduled post updates omit repeat fields Co-authored-by: nick.misasi <[email protected]> * Disallow file attachments on recurring scheduled posts Co-authored-by: nick.misasi <[email protected]> * Stop pinning the channel indicator for recurring-only scheduled posts Co-authored-by: nick.misasi <[email protected]> * Re-home nullable-Type comment onto baseColumns Co-authored-by: nick.misasi <[email protected]> * Gate recurring scheduled posts behind a default-off feature flag Co-authored-by: nick.misasi <[email protected]> * Move presence-preservation rationale to the copy site Co-authored-by: nick.misasi <[email protected]> * Extract draftHasAttachments helper and require allowRecurring at single-caller layers Co-authored-by: nick.misasi <[email protected]> * Return null from the indicator selector when nothing should show Co-authored-by: nick.misasi <[email protected]> * Gate only recurrence transitions and preserve existing series in the modal Co-authored-by: nick.misasi <[email protected]> * Avoid err shadowing in scheduled post update handler Co-authored-by: nick.misasi <[email protected]> * Disable the repeat weekly checkbox with a tooltip when the message has attachments Co-authored-by: nick.misasi <[email protected]> * Return an explicit disposition from postScheduledPost The batch loop inferred 'channel permanently gone' from the one return path with a nil error and an error code set - an invariant a future change could silently break, deleting recurring series by accident. postScheduledPost now returns posted/failed/unsendable explicitly, the switch refuses to delete on an unhandled disposition, and a test pins that both recurring and one-shot posts in a nonexistent channel are permanently deleted. Co-authored-by: nick.misasi <[email protected]> * Fix Repeat weekly attachments tooltip centering on the modal row (#37927) Shrink-wrap the repeat checkbox row so WithTooltip anchors to the control/label instead of the full modal body width. --------- Co-authored-by: Hanzo Dev <[email protected]>
Mattermost is an open core, self-hosted collaboration platform that offers chat, workflow automation, voice calling, screen sharing, and AI integration. This repo is the primary source for core development on the Mattermost platform; it's written in Go and React, runs as a single Linux binary, and relies on PostgreSQL. A new compiled version is released under an MIT license every month on the 16th.
Deploy Mattermost on-premises, or try it for free in the cloud.
Learn more about the following use cases with Mattermost:
Other useful resources:
- Download and Install Mattermost - Install, setup, and configure your own Mattermost instance.
- Product documentation - Learn how to run a Mattermost instance and take advantage of all the features.
- Developer documentation - Contribute code to Mattermost or build an integration via APIs, Webhooks, slash commands, Apps, and plugins.
Table of contents
- Install Mattermost
- Native mobile and desktop apps
- Get security bulletins
- Get involved
- Learn more
- License
- Get the latest news
- Contributing
Install Mattermost
- Download and Install Mattermost Self-Hosted - Deploy a Mattermost Self-hosted instance in minutes via Docker, Ubuntu, or tar.
- Get started in the cloud to try Mattermost today.
- Developer machine setup - Follow this guide if you want to write code for Mattermost.
Other install guides:
- Deploy Mattermost on Docker
- Mattermost Omnibus
- Install Mattermost from Tar
- Ubuntu 20.04 LTS
- Kubernetes
- Helm
- Debian Buster
- RHEL 8
- More server install guides
Native mobile and desktop apps
In addition to the web interface, you can also download Mattermost clients for Android, iOS, Windows PC, macOS, and Linux.
Get security bulletins
Receive notifications of critical security updates. The sophistication of online attackers is perpetually increasing. If you're deploying Mattermost it's highly recommended you subscribe to the Mattermost Security Bulletin mailing list for updates on critical security releases.
Get involved
- Contribute to Mattermost
- Find "Help Wanted" projects
- Join Developer Discussion on a Mattermost server for contributors
- Get Help With Mattermost
Learn more
- API options - webhooks, slash commands, drivers, and web service
- See who's using Mattermost
- Browse over 700 Mattermost integrations
License
See the LICENSE file for license rights and limitations.
Get the latest news
- X - Follow Mattermost on X, formerly Twitter.
- Blog - Get the latest updates from the Mattermost blog.
- Facebook - Follow Mattermost on Facebook.
- LinkedIn - Follow Mattermost on LinkedIn.
- Email - Subscribe to our newsletter (1 or 2 per month).
- Mattermost - Join the ~contributors channel on the Mattermost Community Server.
- IRC - Join the #matterbridge channel on Freenode (thanks to matterircd).
- YouTube - Subscribe to Mattermost.
Contributing
Please see CONTRIBUTING.md. Join the Mattermost Contributors server to join community discussions about contributions, development, and more.




