Loading...

This is taking longer than expected.

Back to the help centre

Announcements

Publish a notice to every user by megaphone, email and web push.

Announcements are notices an administrator publishes for everyone: a maintenance window, a new feature, a change of terms. Each one is a page inside the application, an entry in a megaphone dropdown, and optionally an email. This guide covers turning the module on, publishing, what users see, and what the queue has to do.

Turn it on

Option Env variable Default What changes
features.announcements FEATURE_ANNOUNCEMENTS false On: the Announcements resource appears at /admin/announcements, the megaphone dropdown appears in the top bar of the application, and /account/announcements opens. Off: the resource is hidden and its routes return 403, the account pages return 404, the dropdown is not rendered.

FEATURE_ANNOUNCEMENTS is not listed in .env.example; add it yourself.

FEATURE_ANNOUNCEMENTS=true

The flag is read from config/features.php, so it takes effect after php artisan config:clear when configuration is cached.

Publish one

Go to /admin/announcements and click Create. The form:

Field Rules Notes
Title required, up to 255 characters Shown in the dropdown, the list, the page and the email subject.
Slug optional, unique Left empty, it is generated from the title. It is the last segment of the public URL, /account/announcements/{slug}.
Description required A Markdown editor (Toast UI). Stored as Markdown, rendered as HTML on the page and in the email.
Status required, default Draft draft or published, the cases of App\Enums\AnnouncementStatus. Only published announcements are visible to users.
Send Email default off Whether the publication also sends an email. Hidden on the index and detail views.

The announcement form

Two more fields, Published At and Created At, are read-only on the detail view.

There is no audience selector and no scheduled publication: every published announcement reaches every account at the moment you save it with the status Published. Publish drafts when you mean it.

What happens on save, in App\Observers\AnnouncementObserver:

  • Saving with status Published for the first time fills Published At with the current time. Switching back to Draft clears it; publishing again stamps a new time, so the announcement comes back on top as unread for everyone.
  • Every time the status becomes Published — on creation or after a change — the job App\Jobs\SendAnnouncementEmailsJob is dispatched to the queue with the announcement. Editing the title or body of an announcement that is already published dispatches nothing.

Announcements soft-delete, so the Trash view of the resource can restore one. Permissions follow the usual shape (create announcement, retrieve announcement, update announcement, delete announcement); see /help/roles-and-permissions.

What users see

The reader side is three Livewire components in app/Livewire/Auth/Announcements/: Dropdown, Index and Show.

The megaphone. The top bar of the application shows a megaphone icon next to the notifications bell. A red badge carries the number of unread announcements, capped at 9+. Clicking it opens a dropdown with the ten most recent published announcements, newest first, each with its title and a 60-character excerpt; unread ones carry a coloured left border. The dropdown has Mark as Read, which marks everything read at once, and View all announcements.

The list. /account/announcements (also linked as Announcements in the account sidebar) pages through published announcements, ten per page, with title, 150-character excerpt and publication date.

The page. /account/announcements/{slug} renders the full Markdown with the publication date and a link back to the list. Only published announcements resolve; a draft's slug returns 404.

How reading is tracked

Read state is one timestamp per account: users.last_announcement_read_at. An announcement is unread when its Published At is later than that timestamp, or when the timestamp is empty. Two things set it to the current time: opening any announcement page, and Mark as Read in the dropdown. Both mark every announcement read, not just one.

There is no per-announcement read record and no read count. The admin panel shows nothing about who read what; what it does keep is which emails went out, described below.

Email and web push

The job runs User::whereNull('blocked_at') in chunks of 100 and sends each account App\Notifications\Announcements\AnnouncementNotification. Unverified accounts are included; blocked ones are not. The notification chooses its channels per account:

Channel Sent when
Mail Send Email is on for the announcement AND the account has Notify me by email of all actions on my account enabled in its profile.
Web push The account has at least one push subscription, whether or not Send Email is on. See /help/web-push-and-the-pwa.

The notification does not use the database channel, so it does not appear in the notifications centre; the megaphone is its in-app form. An account with neither condition receives nothing beyond the megaphone badge.

The email uses the application's standard mail layout through resources/views/emails/announcements/announcement.blade.php: the subject is {app name} — {title}, the body is the rendered Markdown, and a Read announcement button opens the announcement page. Every email that is actually sent is recorded in Communication Logs at /admin/communication_logs with the recipient, the notification class, the subject and the HTML body; a failed send is recorded there too with its status. That log is the closest thing to a delivery report the panel offers.

The job and the notification both implement ShouldQueue, so nothing is sent until a worker runs:

php artisan queue:work

Without a worker the announcement is still published and visible in the megaphone immediately; only the emails and pushes wait. Set up the worker as a service in production, as described in /help/queues-and-scheduled-work, and make sure the mailer in .env works before turning Send Email on for a large user base: one publication sends one email per account.