Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Statamic Inbox Laravel Package

goldnead/statamic-inbox

goldnead/statamic-inbox is a lightweight Statamic addon that adds a simple control-panel inbox for collecting, reviewing, and managing incoming messages and form submissions. It keeps communication organized and accessible from the Statamic dashboard and is easy to install and extend within Laravel.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by installing the package and publishing its config and migrations, then define at least one mailbox (with its brand and address) — almost everything in the package, including the new CLI, is scoped per mailbox and per brand.

  1. composer require the package, run php artisan vendor:publish for config + migrations, php artisan migrate.
  2. Configure at least one inbound mailbox and a brand in the config/DB as documented in the README.
  3. Locate the settings screen in the Control Panel — as of v0.2.4 the package declares settingsNavParent(), so with statamic-brand-context 1.16+ its settings appear as the sub-item "Einstellungen" under the addon's own navigation entry. On older brand-context versions the entry stays where it was.
  4. Verify the install end-to-end without touching the UI: php artisan inbox:summary.

That last step is the fastest smoke test you have. If the command returns counts and no fetch problems, your mailboxes are wired up; if last_error or folder errors show up, you have a connection/credential problem before you ever load a page.

First real use case: run php artisan inbox:summary --details to see whether conversations are actually arriving and being classified into the right tabs. It tells you what is in the inbox (new / open / unread-open / stale / snoozed) without opening a single conversation.

Look first at Support\ConversationQuery — as of v0.2.3 it is the single place where tab logic lives, and it is the correct entry point for anything you build that needs "the numbers".

Implementation Patterns

Treat ConversationQuery as your query API, not the controller. The listing tabs, the unread badge in the nav, and inbox:summary all resolve through Support\ConversationQuery now. Anything you build that needs tab counts, unread counts, or a filtered conversation set — a dashboard widget, a JSON endpoint for a mobile app, a Slack notifier — should call into it rather than re-deriving where clauses. This is the main integration tip of this release: the package has given you a seam, use it. Re-implementing tab logic in your own code is how you end up with a badge that disagrees with the list.

Agent/ops monitoring over SSH. inbox:summary is designed to be the thing your on-call agent (human or automated) runs first. Patterns that work:

  • Cron or a health-check job over SSH: inbox:summary --json, parse the fixed shape, alert when "waiting longer than --wartet days" or the fetch-problem counts go non-zero.
  • Per-brand triage: inbox:summary --brand=acme --details gives the first five conversations behind each number (subject, other side, age) — enough to decide who should look, without pulling message bodies into a terminal, a log, or an LLM context.
  • Multi-brand daily digest: loop the brands and emit one combined summary.

Safe to run anywhere, any time. The command is strictly read-only: no writes, no events, no log lines, and it does not flip unread. That means you can run it in production on a timer, from a monitoring box, or ad hoc during an incident without worrying about side effects, audit noise, or racing with agents in the UI.

Separate "is it broken" from "is it busy". The fetch-problem fields (last_error, folder errors, messages given up on) are operational signal; the new/open/waiting numbers are workload signal. Wire them to different alerts — a non-zero last_error should page someone, a large "waiting > 7 days" number should not.

Document settings location conditionally. Because the settings entry moved for brand-context 1.16+ and did not move for older installs, onboarding docs, screenshots and support macros that say "go to Settings → …" are now only half-true. Either state the brand-context version requirement, or phrase it as "under the addon's own navigation entry" and let the reader find the sub-item.

Same name as the parent entry, counters included. The sub-item deliberately mirrors the navigation entry's name (including when that entry renders a counter). If you generate docs, tests or a CP-side integration that reads nav labels, read them from the nav — do not hardcode "Einstellungen" or "Settings".

Gotchas and Tips

Re-check your controller customisations after the 0.2.3 release. If you had subclassed ConversationsController or copied its tab logic into your own code, that logic is now duplicated. The tab counts and nav badge are unchanged in behaviour, but they no longer originate in the controller — so an override that used to affect the badge may silently stop doing so. Move such overrides to ConversationQuery and delete the copies.

The settings relocation is not a package bug. v0.2.4 only adds settingsNavParent() ([section, name] of the addon's own CP nav entry). With statamic-brand-context 1.16+ the settings show as the sub-item under that entry; addons without a navigation of their own share one "Addon-Suite" page under Settings. On older brand-context versions the method is simply ignored and the previous layout stays. So "the sub-item is missing" is almost always a brand-context version mismatch, not a mail/inbox problem — check composer show statamic/brand-context before debugging anything else.

Upgrade is a no-op for your data. No migration, no new config key. The risk is purely presentational: a composer update that pulls brand-context 1.16 will move the settings entry in the same deploy, and people who bookmarked the old location will file tickets. Expect "where did the settings go?" and pre-empt it in the release note to your users.

--wartet is days, default 7. The flag name is German (as is "snoozed until today" phrasing in the output). Don't guess at units or pass hours; a --wartet=168 is not what you want.

The --json shape is "fixed" — but you are on 0.x. Fixed means stable within the intended contract, not that it will never change before 1.0. Pin the package version in composer.json and add a smoke test that asserts the keys you depend on, so a future release fails your CI rather than your alerting.

--details never returns bodies. This is deliberate and it's the reason the command is safe to pipe into logs and agent context. If you need message content, that is a different code path — go through ConversationQuery and your own authorisation, not the CLI.

No events, no log lines, no unread mutation. Because it is silent, you cannot use inbox:summary as an audit trail or as a way to "touch" conversations. Equally, an agent reading the summary has not read the mail — the unread count will not move, so don't let a summary run be mistaken for triage.

Distinguish snoozed from snoozed-until-today. Two separate numbers are reported; only the latter is due to resurface. Reminder digests should use the "until today" figure or you will nag agents about snoozes that are still legitimately parked.

last_error is your first debugging stop. When conversations stop arriving, run inbox:summary --brand=<affected> before digging into logs — it surfaces the fetch error and folder-level problems directly, which is usually faster than reading the queue or mail logs.

Extension points to watch: Support\ConversationQuery is new (v0.2.3) and deliberately shared by three call sites, so its method surface is the most likely thing to shift in upcoming 0.x releases — keep your calls thin and wrapped in one of your own service classes rather than sprinkled across views and jobs. settingsNavParent() (v0.2.4) is now the CP's declared hook for settings placement; if you were patching navigation by hand or overriding views to move the settings screen, replace that with the supported method and let brand-context do the placement.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
adachsoft/php-code-style